Merge branch 'stable-2.16'

* stable-2.16:
  init: fail consistently when plugin is not in the war file

Change-Id: Ib09b14e4b7c609b8d0347bf81e83713fa76a93dd
diff --git a/BUILD b/BUILD
index d924417..5ddf8b1 100644
--- a/BUILD
+++ b/BUILD
@@ -2,10 +2,6 @@
 
 load("//tools/bzl:genrule2.bzl", "genrule2")
 load("//tools/bzl:pkg_war.bzl", "pkg_war")
-load(
-    "@bazel_tools//tools/jdk:default_java_toolchain.bzl",
-    "default_java_toolchain",
-)
 
 config_setting(
     name = "java9",
@@ -15,42 +11,12 @@
 )
 
 config_setting(
-    name = "java10",
+    name = "java_next",
     values = {
-        "java_toolchain": ":toolchain_vanilla",
+        "java_toolchain": "@bazel_tools//tools/jdk:toolchain_vanilla",
     },
 )
 
-# TODO(davido): Switch to consuming it from @bazel_tool//tools/jdk:absolute_javabase
-# when new Bazel version is released with this change included:
-# https://github.com/bazelbuild/bazel/issues/6012
-# https://github.com/bazelbuild/bazel/commit/0173bdbf7bdd1874379d4dd3eb70d5321e0f1816
-# As the interim use a hack that works around it by putting the variable reference
-# behind a select
-config_setting(
-    name = "use_absolute_javabase",
-    values = {"define": "USE_ABSOLUTE_JAVABASE=true"},
-)
-
-java_runtime(
-    name = "absolute_javabase",
-    java_home = select({
-        ":use_absolute_javabase": "$(ABSOLUTE_JAVABASE)",
-        "//conditions:default": "",
-    }),
-    visibility = ["//visibility:public"],
-)
-
-# TODO(davido): Switch to consuming it from @bazel_tool//tools/jdk:toolchain_vanilla
-# when my change is included in released Bazel version:
-# https://github.com/bazelbuild/bazel/commit/0bef68e054eccecd690e5d9f46db8a0c4b2d887a
-default_java_toolchain(
-    name = "toolchain_vanilla",
-    forcibly_disable_header_compilation = True,
-    javabuilder = ["@bazel_tools//tools/jdk:VanillaJavaBuilder_deploy.jar"],
-    jvm_opts = [],
-)
-
 genrule(
     name = "gen_version",
     outs = ["version.txt"],
@@ -79,15 +45,9 @@
 )
 
 pkg_war(
-    name = "polygerrit",
-    ui = "polygerrit",
-)
-
-pkg_war(
     name = "release",
     context = ["//plugins:core"],
     doc = True,
-    ui = "ui_optdbg_r",
 )
 
 pkg_war(
@@ -105,9 +65,6 @@
     "//plugins:plugin-api_deploy.jar",
     "//plugins:plugin-api-sources_deploy.jar",
     "//plugins:plugin-api-javadoc",
-    "//gerrit-plugin-gwtui:gwtui-api_deploy.jar",
-    "//gerrit-plugin-gwtui:gwtui-api-source_deploy.jar",
-    "//gerrit-plugin-gwtui:gwtui-api-javadoc",
 ]
 
 genrule2(
diff --git a/Documentation/BUILD b/Documentation/BUILD
index 4177f51..b322fef 100644
--- a/Documentation/BUILD
+++ b/Documentation/BUILD
@@ -47,7 +47,6 @@
     name = "licenses",
     opts = ["--asciidoctor"],
     targets = [
-        "//gerrit-gwtui:ui_module",
         "//polygerrit-ui/app:polygerrit_ui",
         "//java/com/google/gerrit/pgm",
     ],
@@ -57,7 +56,6 @@
 license_map(
     name = "js_licenses",
     targets = [
-        "//gerrit-gwtui:ui_module",
         "//polygerrit-ui/app:polygerrit_ui",
     ],
     visibility = ["//visibility:public"],
diff --git a/Documentation/access-control.txt b/Documentation/access-control.txt
index d3f5d77..13e3a53 100644
--- a/Documentation/access-control.txt
+++ b/Documentation/access-control.txt
@@ -5,6 +5,12 @@
 to those groups.  Access rights cannot be granted to individual
 users.
 
+To view/edit the access controls for a specific project, first
+navigate to the projects page: for example,
+https://gerrit-review.googlesource.com/admin/repos/ . Then click on
+the individual project, and then click Access. This will bring you
+to a url that looks like
+https://gerrit-review.googlesource.com/admin/repos/gerrit,access
 
 [[system_groups]]
 == System Groups
diff --git a/Documentation/config-cla.txt b/Documentation/config-cla.txt
index 2234808..2c7b194 100644
--- a/Documentation/config-cla.txt
+++ b/Documentation/config-cla.txt
@@ -25,13 +25,15 @@
 ----
 
 Contributor agreements are defined as contributor-agreement sections in
-`project.config`:
+`project.config` of `All-Projects`:
 ----
   [contributor-agreement "Individual"]
     description = If you are going to be contributing code on your own, this is the one you want. You can sign this one online.
     agreementUrl = static/cla_individual.html
     autoVerify = group CLA Accepted - Individual
     accepted = group CLA Accepted - Individual
+    matchProjects = ^/.*$
+    excludeProjects = ^/not/my/project/
 ----
 
 Each `contributor-agreement` section within the `project.config` file must
@@ -75,6 +77,16 @@
 contributor agreement has been accepted. The groups' UUID must also
 appear in the `groups` file.
 
+[[contributor-agreement.name.matchProjects]]contributor-agreement.<name>.matchProjects::
++
+List of project regular expressions identifying projects where the
+agreement is required. Defaults to every project when omitted.
+
+[[contributor-agreement.name.excludeProjects]]contributor-agreement.<name>.excludeProjects::
++
+List of project regular expressions identifying projects where the
+agreement does not apply. Defaults to empty. i.e. no projects excluded.
+
 GERRIT
 ------
 Part of link:index.html[Gerrit Code Review]
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 0cb2b00..589071a 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -273,10 +273,7 @@
 `Become` appears in the top right corner of the page, taking the
 user to a form where they can enter the username of any existing
 user account, and immediately login as that account, without any
-authentication taking place.  This form of authentication is only
-useful for the GWT hosted mode shell, where OpenID authentication
-redirects might be risky to the developer's host computer, and HTTP
-authentication is not possible.
+authentication taking place.
 
 +
 By default, OpenID.
@@ -485,13 +482,12 @@
 +
 When `auth.type` does not normally enable this URL administrators may
 set this to `login/`, allowing users to begin a new web session. This value
-is used as an href in PolyGerrit and the GWT UI, so absolute URLs like
+is used as an href in PolyGerrit, so absolute URLs like
 `https://someotherhost/login` work as well.
 +
 If a ${path} parameter is included, then PolyGerrit will substitute the
 currently viewed path in the link. Be aware that this path will include
 a leading slash, so a value like this might be appropriate: `/login${path}`.
-Note: in the GWT UI this substitution for ${path} is *always* `/`.
 
 [[auth.cookiePath]]auth.cookiePath::
 +
@@ -1175,8 +1171,7 @@
 
 [[change.allowBlame]]change.allowBlame::
 +
-Allow blame on side by side diff in the GWT UI. If set to false, blame cannot be
-used.
+Allow blame on side by side diff. If set to false, blame cannot be used.
 +
 Default is true.
 
@@ -1433,13 +1428,10 @@
 example, to match the string `bug` in a case insensitive way the match
 pattern `[bB][uU][gG]` needs to be used.
 +
-Between the GWT UI and PolyGerrit, the commentlink.name.match regular
-expressions are applied differently. Whereas in the GWT UI the
-expressions are applied to the formatted and escaped HTML result, the
-PolyGerrit UI applies them only to the raw, unformatted and unescaped
-text form. PolyGerrit does not support regex matching against HTML.
-Comment link patterns that are written in this style should be updated
-to match text formats.
+The commentlink.name.match regular expressions are applied to the raw,
+unformatted and unescaped text form. Regex matching against HTML is not
+supported. Comment link patterns that are written in this style should
+be updated to match text formats.
 +
 A common pattern to match is `bug\\s+(\\d+)`.
 
@@ -5103,7 +5095,6 @@
 
 The format is one Base-64 encoded public key per line.
 
-
 == Configuring the Polygerrit UI
 
 Please see link:dev-polygerrit.html[UI] on configuring the Polygerrit UI.
diff --git a/Documentation/config-plugins.txt b/Documentation/config-plugins.txt
index b9c5172..a138b14 100644
--- a/Documentation/config-plugins.txt
+++ b/Documentation/config-plugins.txt
@@ -199,8 +199,7 @@
 
 This plugin allows the rendering of Git repository branch network in a
 graphical HTML5 Canvas. It is mainly intended to be used as a
-"project link" in a gitweb configuration or by other Gerrit GWT UI
-plugins to be plugged elsewhere in Gerrit.
+"project link" in a gitweb configuration.
 
 link:https://gerrit-review.googlesource.com/admin/repos/plugins/branch-network[
 Project] |
diff --git a/Documentation/config-themes.txt b/Documentation/config-themes.txt
index dcfd711..38bfc46 100644
--- a/Documentation/config-themes.txt
+++ b/Documentation/config-themes.txt
@@ -129,9 +129,7 @@
 
 The `window.onload` callback is necessary to ensure that the
 `Gerrit.on()` function has actually been defined by the
-page.  Because GWT loads the module asynchronously any `<script>`
-block in the header or footer will execute before Gerrit has defined
-the function and is ready to register the hook callback.
+page.
 
 GERRIT
 ------
diff --git a/Documentation/dev-bazel.txt b/Documentation/dev-bazel.txt
index 0ecc820..efa17da 100644
--- a/Documentation/dev-bazel.txt
+++ b/Documentation/dev-bazel.txt
@@ -6,7 +6,7 @@
 To build Gerrit from source, you need:
 
 * A Linux or macOS system (Windows is not supported at this time)
-* A JDK for Java 8|9|10
+* A JDK for Java 8|9|10|11|...
 * Python 2 or 3
 * Node.js
 * link:https://www.bazel.io/versions/master/docs/install.html[Bazel]
@@ -14,27 +14,55 @@
 * zip, unzip
 * gcc
 
-[[Java 10 support]]
-Java 10 is supported through vanilla java toolchain
+[[Java 10 and newer version support]]
+Java 10 (and newer is) supported through vanilla java toolchain
 link:https://docs.bazel.build/versions/master/toolchains.html[Bazel option].
-To build Gerrit with Java 10, specify vanilla java toolchain and provide
-path to Java 10 home:
+To build Gerrit with Java 10 and newer, specify vanilla java toolchain and
+provide the path to JDK home:
 
 ```
-  $ bazel build --host_javabase=:absolute_javabase \
+  $ bazel build \
     --define=ABSOLUTE_JAVABASE=<path-to-java-10> \
-    --define=USE_ABSOLUTE_JAVABASE=true \
-    --host_java_toolchain=//:toolchain_vanilla \
-    --java_toolchain=//:toolchain_vanilla \
+    --host_javabase=@bazel_tools//tools/jdk:absolute_javabase \
+    --host_java_toolchain=@bazel_tools//tools/jdk:toolchain_vanilla \
+    --java_toolchain=@bazel_tools//tools/jdk:toolchain_vanilla \
     :release
 ```
 
-Note that the following options must be added to `container.javaOptions`
-in `$gerrit_site/etc/gerrit.config` to run Gerrit with Java 10:
+To run the tests, `--javabase` option must be passed as well, because
+bazel test runs the test using the target javabase:
+
+```
+  $ bazel test \
+    --define=ABSOLUTE_JAVABASE=<path-to-java-10> \
+    --javabase=@bazel_tools//tools/jdk:absolute_javabase \
+    --host_javabase=@bazel_tools//tools/jdk:absolute_javabase \
+    --host_java_toolchain=@bazel_tools//tools/jdk:toolchain_vanilla \
+    --java_toolchain=@bazel_tools//tools/jdk:toolchain_vanilla \
+    //...
+```
+
+To avoid passing all those options on every Bazel build invocation,
+they could be added to ~/.bazelrc resource file:
+
+```
+$ cat << EOF > ~/.bazelrc
+> build --define=ABSOLUTE_JAVABASE=<path-to-java-10>
+> build --javabase=@bazel_tools//tools/jdk:absolute_javabase
+> build --host_javabase=@bazel_tools//tools/jdk:absolute_javabase
+> build --host_java_toolchain=@bazel_tools//tools/jdk:toolchain_vanilla
+> build --java_toolchain=@bazel_tools//tools/jdk:toolchain_vanilla
+> EOF
+```
+
+Now, invoking Bazel with just `bazel build :release` would include
+all those options.
+
+Note that the follow option must be added to `container.javaOptions`
+in `$gerrit_site/etc/gerrit.config` to run Gerrit with Java 10|11|...:
 
 ```
 [container]
-  javaOptions = --add-modules java.activation
   javaOptions = --add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED
 ```
 
@@ -51,13 +79,12 @@
       :release
 ```
 
-Note that the following option must be added to `container.javaOptions`
+Note that the follow option must be added to `container.javaOptions`
 in `$gerrit_site/etc/gerrit.config` to run Gerrit with Java 9:
 
 ```
 [container]
-  javaOptions = --add-modules java.activation \
-      --add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED
+  javaOptions = --add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED
 ```
 
 [[build]]
@@ -65,7 +92,7 @@
 
 === Gerrit Development WAR File
 
-To build the Gerrit web application that includes the PolyGerrit UI:
+To build the Gerrit web application:
 
 ----
   bazel build gerrit
@@ -84,8 +111,8 @@
 [[release]]
 === Gerrit Release WAR File
 
-To build the Gerrit web application that includes the GWT UI, the
-PolyGerrit UI, core plugins and documentation:
+To build the Gerrit web application that includes the PolyGerrit UI,
+core plugins and documentation:
 
 ----
   bazel build release
@@ -99,7 +126,7 @@
 
 === Headless Mode
 
-To build Gerrit in headless mode, i.e. without the PolyGerrit and GWT
+To build Gerrit in headless mode, i.e. without the PolyGerrit UI:
 Web UI:
 
 ----
@@ -114,7 +141,7 @@
 
 === Extension and Plugin API JAR Files
 
-To build the extension, plugin and GWT API JAR files:
+To build the extension, plugin and acceptance-framework JAR files:
 
 ----
   bazel build api
@@ -127,7 +154,8 @@
   bazel-genfiles/api.zip
 ----
 
-Install {extension,plugin,gwt}-api to the local maven repository:
+Install {extension,plugin,acceptance-framework}-api to the local
+maven repository:
 
 ----
   tools/maven/api.sh install
@@ -258,8 +286,10 @@
   bazel test //javatests/com/google/gerrit/acceptance/rest/account:rest_account
 ----
 
-To run the tests against NoteDb backend with write
-to NoteDb, but not read from it:
+The tests run with NoteDb fully enabled by default.
+
+To run the tests against NoteDb backend with write to NoteDb, but not read from
+it:
 
 ----
   bazel test --test_env=GERRIT_NOTEDB=WRITE //...
@@ -277,10 +307,10 @@
   bazel test --test_env=GERRIT_NOTEDB=PRIMARY //...
 ----
 
-Primary storage NoteDb and ReviewDb disabled:
+NoteDb entirely disabled:
 
 ----
-  bazel test --test_env=GERRIT_NOTEDB=ON //...
+  bazel test --test_env=GERRIT_NOTEDB=OFF //...
 ----
 
 To run only tests that do not use SSH:
diff --git a/Documentation/dev-contributing.txt b/Documentation/dev-contributing.txt
index 8710a2b..a1342d3 100644
--- a/Documentation/dev-contributing.txt
+++ b/Documentation/dev-contributing.txt
@@ -273,7 +273,6 @@
     people from submitting actions more than once when operating
     on slow links.  If the action buttons are disabled, they cannot
     be resubmitted and the user can see that Gerrit is still busy.
-  * GWT EventBus is the new way forward.
   * ...and so is Guava (previously known as Google Collections).
 
 
@@ -333,21 +332,6 @@
 for review on that release's stable branch.  It will then be included in
 the master branch when the stable branch is merged back.
 
-=== Updating to new version of GWT
-
-When updating to a new version of GWT, there are several things that also need
-to be updated or at least checked.
-
-* Update common and plugin dependencies in `tools/gwt-constants.defs`.
-* Update to the same GWT version in the cookbook plugin and optionally in other
-plugins that have a dependency on GWT.
-* Update the GWT version in the archetype metadata in the
-`gerrit-plugin-gwt-archetype`.
-* Update the version of `gwt-maven-plugin` in the example pom.xml file in
-link:dev-plugins.html[dev-plugins].
-* Update to the same GWT version in the `gwtjsonrpc` project, and release a
-new version.
-
 === Finding starter projects to work on
 
 We have created a
diff --git a/Documentation/dev-design.txt b/Documentation/dev-design.txt
index bdd2a68..2d6e24c 100644
--- a/Documentation/dev-design.txt
+++ b/Documentation/dev-design.txt
@@ -121,9 +121,9 @@
 
 End-user web browsers make HTTP requests directly to Gerrit's
 HTTP server.  As nearly all of the user interface is implemented
-through Google Web Toolkit (GWT), the majority of these requests
-are transmitting compressed JSON payloads, with all HTML being
-generated within the browser.  Most responses are under 1 KB.
+through PolyGerrit, the majority of these requests are transmitting
+compressed JSON payloads, with all HTML being generated within the
+browser.  Most responses are under 1 KB.
 
 Gerrit's HTTP server side component is implemented as a standard
 Java servlet, and thus runs within any J2EE servlet container.
@@ -166,7 +166,6 @@
 requires that the OpenID provider selected by a user must be
 online and operating in order to authenticate that user.
 
-* link:http://www.gwtproject.org/[Google Web Toolkit (GWT)]
 * link:http://www.kernel.org/pub/software/scm/git/docs/gitrepository-layout.html[Git Repository Format]
 * link:http://www.postgresql.org/about/[About PostgreSQL]
 * link:http://openid.net/developers/specs/[OpenID Specifications]
@@ -200,11 +199,6 @@
 and comments in English, and therefore an English user interface
 is usable by the target user base.
 
-Gerrit uses GWT's i18n support to externalize all constant strings
-and messages shown to the user, so that in the future someone who
-really needed a translated version of the UI could contribute new
-string files for their locale(s).
-
 Right-to-left (RTL) support is only barely considered within the
 Gerrit code base.  Some portions of the code have tried to take
 RTL into consideration, while others probably need to be modified
@@ -235,20 +229,11 @@
 
 Supporting non-JavaScript enabled browsers is a non-goal for Gerrit.
 
-As Gerrit is a pure-GWT application with no server side rendering
-fallbacks, the browser must support modern JavaScript semantics in
-order to access the Gerrit web application.  Dumb clients such as
-`lynx`, `wget`, `curl`, or even many search engine spiders are not
-able to access Gerrit content.
-
-As Google Web Toolkit (GWT) is used to generate the browser
-specific versions of the client-side JavaScript code, Gerrit works
-on any JavaScript enabled browser which GWT can produce code for.
-This covers the majority of the popular browsers.
-
-The Gerrit project does not have the development resources necessary
-to support two parallel UI implementations (GWT based JavaScript
-and server-side rendering).  Consequently only one is implemented.
+As Gerrit is a pure JavaScript application on the client side, with
+no server side rendering fallbacks, the browser must support modern
+JavaScript semantics in order to access the Gerrit web application.
+Dumb clients such as `lynx`, `wget`, `curl`, or even many search engine
+spiders are not able to access Gerrit content.
 
 There are number of web browsers available with full JavaScript
 support, and nearly every operating system (including any PDA-like
@@ -323,7 +308,7 @@
 Gerrit uses an XSRF protected variant of JSON-RPC 1.1 to communicate
 between the browser client and the server.
 
-As the protocol is not the GWT-RPC protocol, but is instead a
+As the protocol is not the proprietry protocol, but is instead a
 self-describing standard JSON format it is easily implemented by
 any 3rd party client application, provided the client has a JSON
 parser and HTTP client library available.
diff --git a/Documentation/dev-eclipse.txt b/Documentation/dev-eclipse.txt
index 0f23db5..35073d6 100644
--- a/Documentation/dev-eclipse.txt
+++ b/Documentation/dev-eclipse.txt
@@ -1,11 +1,9 @@
 = Gerrit Code Review - Eclipse Setup
 
 This document is about configuring Gerrit Code Review into an
-Eclipse workspace for development and debugging with GWT.
+Eclipse workspace for development.
 
-Java 8 or later SDK is also required to run GWT's compiler and
-runtime debugging environment.
-
+Java 8 or later SDK is require
 
 [[setup]]
 == Project Setup
@@ -104,61 +102,6 @@
 * Change Save as to be Local file.
 * Close the Debug Configurations dialog and save the changes when prompted.
 
-
-=== Running GWT Debug Mode
-
-The `gerrit_gwt_debug` launch configuration uses GWT's
-link:http://www.gwtproject.org/articles/superdevmode.html[Super Dev Mode].
-
-* Make a local copy of the `gerrit_gwt_debug` configuration, using the
-process described for `gerrit_daemon` above.
-* Launch the local copy of `gerrit_gwt_debug` from the Eclipse debug menu.
-* If debugging GWT for the first time:
-
-** Open the link:http://localhost:9876/[codeserver URL] and add the `Dev Mode On`
-and `Dev Mode Off` bookmarklet to your bookmark bar.
-
-** Activate the source maps feature in your browser. Refer to the
-link:https://developer.chrome.com/devtools/docs/javascript-debugging#source-maps[
-Chrome] and
-link:https://developer.mozilla.org/en-US/docs/Tools/Debugger#Use_a_source_map[
-Firefox] developer documentation.
-
-* Load the link:http://localhost:8080[Gerrit page].
-* Open the source tab in developer tools.
-* Click the `Dev Mode On` bookmark to incrementally recompile changed files.
-* Select the `gerrit_ui` module to compile (the `Compile` button can also be used
-as a bookmarklet).
-* In the developer tools source tab, open a file and set a breakpoint.
-* Navigate to the UI and confirm that the breakpoint is hit.
-* To end the debugging session, click the `Dev Mode Off` bookmark.
-
-.After changing the client side code:
-
-* Hitting `F5` in the browser only reloads the last compile output, without
-recompiling.
-* To reflect your changes in the debug session, click `Dev Mode On` then `Compile`.
-
-
-=== Running GWT Debug Mode for Gerrit plugins
-
-A Gerrit plugin can expose GWT module and its implementation can be inspected
-in the SDM debug session.
-
-`codeserver` needs two additional inputs to expose the plugin module in the SDM
-debug session: the module name and the source folder location. For example the
-module name and source folder of `cookbook-plugin` should be added in the local
-copy of the `gerrit_gwt_debug` configuration:
-
-----
-  com.googlesource.gerrit.plugins.cookbook.HelloForm \
-  -src ${resource_loc:/gerrit}/plugins/cookbook-plugin/src/main/java \
-  -- --console-log [...]
-----
-
-After doing that, both the Gerrit core and plugin GWT modules can be activated
-during SDM (debug session)[http://imgur.com/HFXZ5No].
-
 GERRIT
 ------
 Part of link:index.html[Gerrit Code Review]
diff --git a/Documentation/dev-intellij.txt b/Documentation/dev-intellij.txt
index 8bedd08..5ec6ae8 100644
--- a/Documentation/dev-intellij.txt
+++ b/Documentation/dev-intellij.txt
@@ -177,9 +177,9 @@
 plugin manages a project, it intercepts the creation and creates a Bazel test
 run configuration instead, which can be used just like the standard ones.
 
-TIP: If you would like to execute a test in NoteDb mode, add
-`--test_env=GERRIT_NOTEDB=READ_WRITE` to the *Bazel flags* of your run
-configuration.
+TIP: Tests run with NoteDb enabled by default. If you would like to execute a
+test with NoteDb turned off, add `--test_env=GERRIT_NOTEDB=OFF` to the *Bazel
+flags* of your run configuration.
 
 [[remote-debug]]
 === Debugging a remote Gerrit server
diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt
index fd29bf7..d5ffda2 100644
--- a/Documentation/dev-plugins.txt
+++ b/Documentation/dev-plugins.txt
@@ -1302,7 +1302,7 @@
 [[panels]]
 === Panels
 
-GWT plugins can contribute panels to Gerrit screens.
+UI plugins can contribute panels to Gerrit screens.
 
 Gerrit screens define extension points where plugins can add GWT
 panels with custom controls:
@@ -1878,317 +1878,6 @@
 ----
 
 
-[[gwt_ui_extension]]
-== GWT UI Extension
-Plugins can extend the Gerrit UI with own GWT code.
-
-A GWT plugin must contain a GWT module file, e.g. `HelloPlugin.gwt.xml`,
-that bundles together all the configuration settings of the GWT plugin:
-
-[source,xml]
-----
-<?xml version="1.0" encoding="UTF-8"?>
-<module rename-to="hello_gwt_plugin">
-  <!-- Inherit the core Web Toolkit stuff. -->
-  <inherits name="com.google.gwt.user.User"/>
-  <!-- Other module inherits -->
-  <inherits name="com.google.gerrit.Plugin"/>
-  <inherits name="com.google.gwt.http.HTTP"/>
-  <!-- Using GWT built-in themes adds a number of static -->
-  <!-- resources to the plugin. No theme inherits lines were -->
-  <!-- added in order to make this plugin as simple as possible -->
-  <!-- Specify the app entry point class. -->
-  <entry-point class="${package}.client.HelloPlugin"/>
-  <stylesheet src="hello.css"/>
-</module>
-----
-
-The GWT module must inherit `com.google.gerrit.Plugin` and
-`com.google.gwt.http.HTTP`.
-
-To register the GWT module a `GwtPlugin` needs to be bound.
-
-If no Guice modules are declared in the manifest, the GWT plugin may
-use auto-registration by using the `@Listen` annotation:
-
-[source,java]
-----
-@Listen
-public class MyExtension extends GwtPlugin {
-  public MyExtension() {
-    super("hello_gwt_plugin");
-  }
-}
-----
-
-Otherwise the binding must be done in an `HttpModule`:
-
-[source,java]
-----
-public class HttpModule extends HttpPluginModule {
-
-  @Override
-  protected void configureServlets() {
-    DynamicSet.bind(binder(), WebUiPlugin.class)
-        .toInstance(new GwtPlugin("hello_gwt_plugin"));
-  }
-}
-----
-
-The HTTP module above must be declared in the `pom.xml` for Maven
-driven plugins:
-
-[source,xml]
-----
-<manifestEntries>
-  <Gerrit-HttpModule>com.googlesource.gerrit.plugins.myplugin.HttpModule</Gerrit-HttpModule>
-</manifestEntries>
-----
-
-The name that is provided to the `GwtPlugin` must match the GWT
-module name compiled into the plugin. The name of the GWT module
-can be explicitly set in the GWT module XML file by specifying
-the `rename-to` attribute on the module. It is important that the
-module name be unique across all plugins installed on the server,
-as the module name determines the JavaScript namespace used by the
-compiled plugin code.
-
-[source,xml]
-----
-<module rename-to="hello_gwt_plugin">
-----
-
-The actual GWT code must be implemented in a class that extends
-`com.google.gerrit.plugin.client.PluginEntryPoint`:
-
-[source,java]
-----
-public class HelloPlugin extends PluginEntryPoint {
-
-  @Override
-  public void onPluginLoad() {
-    // Create the dialog box
-    final DialogBox dialogBox = new DialogBox();
-
-    // The content of the dialog comes from a User specified Preference
-    dialogBox.setText("Hello from GWT Gerrit UI plugin");
-    dialogBox.setAnimationEnabled(true);
-    Button closeButton = new Button("Close");
-    VerticalPanel dialogVPanel = new VerticalPanel();
-    dialogVPanel.setWidth("100%");
-    dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
-    dialogVPanel.add(closeButton);
-
-    closeButton.addClickHandler(new ClickHandler() {
-      public void onClick(ClickEvent event) {
-        dialogBox.hide();
-      }
-    });
-
-    // Set the contents of the Widget
-    dialogBox.setWidget(dialogVPanel);
-
-    RootPanel rootPanel = RootPanel.get(HelloMenu.MENU_ID);
-    rootPanel.getElement().removeAttribute("href");
-    rootPanel.addDomHandler(new ClickHandler() {
-        @Override
-        public void onClick(ClickEvent event) {
-          dialogBox.center();
-          dialogBox.show();
-        }
-    }, ClickEvent.getType());
-  }
-}
-----
-
-This class must be set as entry point in the GWT module:
-
-[source,xml]
-----
-<entry-point class="${package}.client.HelloPlugin"/>
-----
-
-In addition this class must be defined as module in the `pom.xml` for the
-`gwt-maven-plugin` and the `webappDirectory` option of `gwt-maven-plugin`
-must be set to `${project.build.directory}/classes/static`:
-
-[source,xml]
-----
-<plugin>
-  <groupId>org.codehaus.mojo</groupId>
-  <artifactId>gwt-maven-plugin</artifactId>
-  <version>2.7.0</version>
-  <configuration>
-    <module>com.googlesource.gerrit.plugins.myplugin.HelloPlugin</module>
-    <disableClassMetadata>true</disableClassMetadata>
-    <disableCastChecking>true</disableCastChecking>
-    <webappDirectory>${project.build.directory}/classes/static</webappDirectory>
-  </configuration>
-  <executions>
-    <execution>
-      <goals>
-        <goal>compile</goal>
-      </goals>
-    </execution>
-  </executions>
-</plugin>
-----
-
-To attach a GWT widget defined by the plugin to the Gerrit core UI
-`com.google.gwt.user.client.ui.RootPanel` can be used to manipulate the
-Gerrit core widgets:
-
-[source,java]
-----
-RootPanel rootPanel = RootPanel.get(HelloMenu.MENU_ID);
-rootPanel.getElement().removeAttribute("href");
-rootPanel.addDomHandler(new ClickHandler() {
-  @Override
-  public void onClick(ClickEvent event) {
-    dialogBox.center();
-    dialogBox.show();
-  }
-}, ClickEvent.getType());
-----
-
-GWT plugins can come with their own css file. This css file must have a
-unique name and must be registered in the GWT module:
-
-[source,xml]
-----
-<stylesheet src="hello.css"/>
-----
-
-If a GWT plugin wants to invoke the Gerrit REST API it can use
-`com.google.gerrit.plugin.client.rpc.RestApi` to construct the URL
-path and to trigger the REST calls.
-
-Example for invoking a Gerrit core REST endpoint:
-
-[source,java]
-----
-new RestApi("projects").id(projectName).view("description")
-    .put("new description", new AsyncCallback<JavaScriptObject>() {
-
-  @Override
-  public void onSuccess(JavaScriptObject result) {
-    // TODO
-  }
-
-  @Override
-  public void onFailure(Throwable caught) {
-    // never invoked
-  }
-});
-----
-
-Example for invoking a REST endpoint defined by a plugin:
-
-[source,java]
-----
-new RestApi("projects").id(projectName).view("myplugin", "myview")
-    .get(new AsyncCallback<JavaScriptObject>() {
-
-  @Override
-  public void onSuccess(JavaScriptObject result) {
-    // TODO
-  }
-
-  @Override
-  public void onFailure(Throwable caught) {
-    // never invoked
-  }
-});
-----
-
-The `onFailure(Throwable)` of the provided callback is never invoked.
-If an error occurs, it is shown in an error dialog.
-
-In order to be able to do REST calls the GWT module must inherit
-`com.google.gwt.json.JSON`:
-
-[source,xml]
-----
-<inherits name="com.google.gwt.json.JSON"/>
-----
-
-[[screen]]
-== Add Screen
-A link:#gwt_ui_extension[GWT plugin] can link:#top-menu-extensions[add
-a menu item] that opens a screen that is implemented by the plugin.
-This way plugin screens can be fully integrated into the Gerrit UI.
-
-Example menu item:
-[source,java]
-----
-public class MyMenu implements TopMenu {
-  private final List<MenuEntry> menuEntries;
-
-  @Inject
-  public MyMenu(@PluginName String name) {
-    menuEntries = new ArrayList<>();
-    menuEntries.add(new MenuEntry("My Menu", Collections.singletonList(
-      new MenuItem("My Screen", "#/x/" + name + "/my-screen", ""))));
-  }
-
-  @Override
-  public List<MenuEntry> getEntries() {
-    return menuEntries;
-  }
-}
-----
-
-Example screen:
-[source,java]
-----
-public class MyPlugin extends PluginEntryPoint {
-  @Override
-  public void onPluginLoad() {
-    Plugin.get().screen("my-screen", new Screen.EntryPoint() {
-      @Override
-      public void onLoad(Screen screen) {
-        screen.add(new InlineLabel("My Screen");
-        screen.show();
-      }
-    });
-  }
-}
-----
-
-[[user-settings-screen]]
-== Add User Settings Screen
-
-A link:#gwt_ui_extension[GWT plugin] can implement a user settings
-screen that is integrated into the Gerrit user settings menu.
-
-Example settings screen:
-[source,java]
-----
-public class MyPlugin extends PluginEntryPoint {
-  @Override
-  public void onPluginLoad() {
-    Plugin.get().settingsScreen("my-preferences", "My Preferences",
-        new Screen.EntryPoint() {
-          @Override
-          public void onLoad(Screen screen) {
-            screen.setPageTitle("Settings");
-            screen.add(new InlineLabel("My Preferences"));
-            screen.show();
-          }
-    });
-  }
-}
-----
-
-By defining an link:config-gerrit.html#urlAlias[urlAlias] Gerrit
-administrators can map plugin screens into the Gerrit URL namespace or
-even replace Gerrit screens by plugin screens.
-
-Plugins may also programatically add URL aliases in the preferences of
-of a user. This way certain screens can be replaced for certain users.
-E.g. the plugin may offer a user preferences setting for choosing a
-screen that then sets/unsets a URL alias for the user.
-
 [[settings-screen]]
 == Plugin Settings Screen
 
diff --git a/Documentation/metrics.txt b/Documentation/metrics.txt
index 37d6d01..db6f883 100644
--- a/Documentation/metrics.txt
+++ b/Documentation/metrics.txt
@@ -177,6 +177,10 @@
 * `plugin/latency`: Latency for plugin invocation.
 * `plugin/error_count`: Number of plugin errors.
 
+=== Group
+
+* `group/guess_relevant_groups_latency`: Latency for guessing relevant groups.
+
 === Replication Plugin
 
 * `plugins/replication/replication_latency`: Time spent pushing to remote
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index 1829c6b..b1c9a88 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -5769,8 +5769,12 @@
 Number of inserted lines.
 |`deletions`          ||
 Number of deleted lines.
+|`total_comment_count`  |optional|
+Total number of inline comments across all patch sets. Not set if the current
+change index doesn't have the data.
 |`unresolved_comment_count`  |optional|
-Number of unresolved comments. Not set if the current change index doesn't have the data.
+Number of unresolved inline comment threads across all patch sets. Not set if
+the current change index doesn't have the data.
 |`_number`            ||The legacy numeric ID of the change.
 |`owner`              ||
 The owner of the change as an link:rest-api-accounts.html#account-info[
diff --git a/Documentation/rest-api-config.txt b/Documentation/rest-api-config.txt
index 3ec989e..3ea3ba1 100644
--- a/Documentation/rest-api-config.txt
+++ b/Documentation/rest-api-config.txt
@@ -126,10 +126,7 @@
     "gerrit": {
       "all_projects": "All-Projects",
       "all_users": "All-Users"
-      "doc_search": true,
-      "web_uis": [
-        "gwt"
-      ]
+      "doc_search": true
     },
     "sshd": {},
     "suggest": {
@@ -1805,9 +1802,6 @@
 |`report_bug_text`   |optional, not set if default|
 link:config-gerrit.html#gerrit.reportBugText[Display text for report
 bugs link].
-|`web_uis`           ||
-List of web UIs supported by the HTTP server. Possible values are `GWT`
-and `POLYGERRIT`.
 |=================================
 
 [[hit-ration-info]]
diff --git a/Documentation/rest-api-projects.txt b/Documentation/rest-api-projects.txt
index 3214761..49ab36f 100644
--- a/Documentation/rest-api-projects.txt
+++ b/Documentation/rest-api-projects.txt
@@ -1358,25 +1358,6 @@
 Ref(ref)::
 The branch for which to check access. This must be given if `perm` is specified.
 
-[[check-access-post]]
-=== Check Access (POST)
-
-This endpoint can also be accessed as a POST request (deprecated). In
-this case, the input for the access checks must be provided in the
-request body inside a link:#access-check-input[AccessCheckInput]
-entity.
-
-.Request
-----
-  POST /projects/MyProject/check.access HTTP/1.0
-  Content-Type: application/json; charset=UTF-8
-
-  {
-    "account": "Kristen.Burns@gerritcodereview.com",
-    "ref": "refs/heads/secret/bla"
-  }
-----
-
 [[index]]
 === Index project
 
@@ -2936,21 +2917,6 @@
 |`message`                   |optional|A clarifying message if `status` is not 200.
 |=========================================
 
-[[access-check-input]]
-=== AccessCheckInput
-The `AccessCheckInput` entity is either an account or
-(account, ref) tuple for which we want to check access.
-
-[options="header",cols="1,^1,5"]
-|=========================================
-|Field Name                  ||Description
-|`account`                   ||The account for which to check access
-|`ref`                       |optional|The refname for which to check
-access
-|`permission`                |optional|The ref permission for which to
-check. This defaults to `read`. If given, it `ref` must be given too.
-|=========================================
-
 [[auto_closeable_changes_check_input]]
 === AutoCloseableChangesCheckInput
 The `AutoCloseableChangesCheckInput` entity contains options for running
diff --git a/WORKSPACE b/WORKSPACE
index 8ea46e3..8c8102b 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -3,7 +3,6 @@
 load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file")
 load("//tools/bzl:maven_jar.bzl", "GERRIT", "MAVEN_LOCAL", "maven_jar")
-load("//lib/codemirror:cm.bzl", "CM_VERSION", "DIFF_MATCH_PATCH_VERSION")
 load("//plugins:external_plugin_deps.bzl", "external_plugin_deps")
 
 http_archive(
@@ -15,9 +14,9 @@
 
 http_archive(
     name = "io_bazel_rules_closure",
-    sha256 = "4dd84dd2bdd6c9f56cb5a475d504ea31d199c34309e202e9379501d01c3067e5",
-    strip_prefix = "rules_closure-3103a773820b59b76345f94c231cb213e0d404e2",
-    urls = ["https://github.com/bazelbuild/rules_closure/archive/3103a773820b59b76345f94c231cb213e0d404e2.tar.gz"],
+    sha256 = "5b4b610ea4892116b6126fa689218535629305590c43fbd68034d831953a9989",
+    strip_prefix = "rules_closure-409a86250c457ca15cafde35eb169e4c2601570e",
+    urls = ["https://github.com/bazelbuild/rules_closure/archive/409a86250c457ca15cafde35eb169e4c2601570e.zip"],
 )
 
 # File is specific to Polymer and copied from the Closure Github -- should be
@@ -48,8 +47,8 @@
 # Golang support for PolyGerrit local dev server.
 http_archive(
     name = "io_bazel_rules_go",
-    sha256 = "97cf62bdef33519412167fd1e4b0810a318a7c234f5f8dc4f53e2da86241c492",
-    urls = ["https://github.com/bazelbuild/rules_go/releases/download/0.15.3/rules_go-0.15.3.tar.gz"],
+    sha256 = "ee5fe78fe417c685ecb77a0a725dc9f6040ae5beb44a0ba4ddb55453aad23a8a",
+    url = "https://github.com/bazelbuild/rules_go/releases/download/0.16.0/rules_go-0.16.0.tar.gz",
 )
 
 load("@io_bazel_rules_go//go:def.bzl", "go_register_toolchains", "go_rules_dependencies")
@@ -108,24 +107,24 @@
     sha1 = "83cd2cd674a217ade95a4bb83a8a14f351f48bd0",
 )
 
-GUICE_VERS = "4.2.1"
+GUICE_VERS = "4.2.2"
 
 maven_jar(
     name = "guice-library",
     artifact = "com.google.inject:guice:" + GUICE_VERS,
-    sha1 = "f77dfd89318fe3ff293bafceaa75fbf66e4e4b10",
+    sha1 = "6dacbe18e5eaa7f6c9c36db33b42e7985e94ce77",
 )
 
 maven_jar(
     name = "guice-assistedinject",
     artifact = "com.google.inject.extensions:guice-assistedinject:" + GUICE_VERS,
-    sha1 = "d327e4aee7c96f08cd657c17da231a1f4a8999ac",
+    sha1 = "c33fb10080d58446f752b4fcfff8a5fabb80a449",
 )
 
 maven_jar(
     name = "guice-servlet",
     artifact = "com.google.inject.extensions:guice-servlet:" + GUICE_VERS,
-    sha1 = "3927e462f923b0c672fdb045c5645bca4beab5c0",
+    sha1 = "0d0054bdd812224078357a9b11409e43d182a046",
 )
 
 maven_jar(
@@ -146,61 +145,6 @@
     sha1 = "021a212688ec94fe77aff74ab34cc74f6f940e60",
 )
 
-GWT_VERS = "2.8.2"
-
-maven_jar(
-    name = "user",
-    artifact = "com.google.gwt:gwt-user:" + GWT_VERS,
-    sha1 = "a2b9be2c996a658c4e009ba652a9c6a81c88a797",
-)
-
-maven_jar(
-    name = "dev",
-    artifact = "com.google.gwt:gwt-dev:" + GWT_VERS,
-    sha1 = "7a87e060bbf129386b7ae772459fb9f87297c332",
-)
-
-maven_jar(
-    name = "javax-validation",
-    artifact = "javax.validation:validation-api:1.0.0.GA",
-    sha1 = "b6bd7f9d78f6fdaa3c37dae18a4bd298915f328e",
-    src_sha1 = "7a561191db2203550fbfa40d534d4997624cd369",
-)
-
-maven_jar(
-    name = "jsinterop-annotations",
-    artifact = "com.google.jsinterop:jsinterop-annotations:1.0.2",
-    sha1 = "abd7319f53d018e11108a88f599bd16492448dd2",
-    src_sha1 = "33716f8aef043f2f02b78ab4a1acda6cd90a7602",
-)
-
-maven_jar(
-    name = "ant",
-    artifact = "ant:ant:1.6.5",
-    attach_source = False,
-    sha1 = "7d18faf23df1a5c3a43613952e0e8a182664564b",
-)
-
-maven_jar(
-    name = "colt",
-    artifact = "colt:colt:1.2.0",
-    attach_source = False,
-    sha1 = "0abc984f3adc760684d49e0f11ddf167ba516d4f",
-)
-
-maven_jar(
-    name = "tapestry",
-    artifact = "tapestry:tapestry:4.0.2",
-    attach_source = False,
-    sha1 = "e855a807425d522e958cbce8697f21e9d679b1f7",
-)
-
-maven_jar(
-    name = "w3c-css-sac",
-    artifact = "org.w3c.css:sac:1.3",
-    sha1 = "cdb2dcb4e22b83d6b32b93095f644c3462739e82",
-)
-
 load("//lib/jgit:jgit.bzl", "jgit_repos")
 
 jgit_repos()
@@ -586,36 +530,36 @@
     sha1 = "5e3bda828a80c7a21dfbe2308d1755759c2fd7b4",
 )
 
-OW2_VERS = "6.2.1"
+OW2_VERS = "7.0"
 
 maven_jar(
     name = "ow2-asm",
     artifact = "org.ow2.asm:asm:" + OW2_VERS,
-    sha1 = "c01b6798f81b0fc2c5faa70cbe468c275d4b50c7",
+    sha1 = "d74d4ba0dee443f68fb2dcb7fcdb945a2cd89912",
 )
 
 maven_jar(
     name = "ow2-asm-analysis",
     artifact = "org.ow2.asm:asm-analysis:" + OW2_VERS,
-    sha1 = "e8b876c5ccf226cae2f44ed2c436ad3407d0ec1d",
+    sha1 = "4b310d20d6f1c6b7197a75f1b5d69f169bc8ac1f",
 )
 
 maven_jar(
     name = "ow2-asm-commons",
     artifact = "org.ow2.asm:asm-commons:" + OW2_VERS,
-    sha1 = "eaf31376d741a3e2017248a4c759209fe25c77d3",
+    sha1 = "478006d07b7c561ae3a92ddc1829bca81ae0cdd1",
 )
 
 maven_jar(
     name = "ow2-asm-tree",
     artifact = "org.ow2.asm:asm-tree:" + OW2_VERS,
-    sha1 = "332b022092ecec53cdb6272dc436884b2d940615",
+    sha1 = "29bc62dcb85573af6e62e5b2d735ef65966c4180",
 )
 
 maven_jar(
     name = "ow2-asm-util",
     artifact = "org.ow2.asm:asm-util:" + OW2_VERS,
-    sha1 = "400d664d7c92a659d988c00cb65150d1b30cf339",
+    sha1 = "18d4d07010c24405129a6dbb0e92057f8779fb9d",
 )
 
 AUTO_VALUE_VERSION = "1.6.2"
@@ -1051,25 +995,6 @@
 )
 
 maven_jar(
-    name = "codemirror-minified-gwt",
-    artifact = "org.webjars.npm:codemirror-minified:" + CM_VERSION,
-    sha1 = "36558ea3b8e30782e1e09c0e7bd781e09614f139",
-)
-
-maven_jar(
-    name = "codemirror-original-gwt",
-    artifact = "org.webjars.npm:codemirror:" + CM_VERSION,
-    sha1 = "f1f8fbbc3e2d224fdccc43d2f4180658a92320f9",
-)
-
-maven_jar(
-    name = "diff-match-patch",
-    artifact = "org.webjars:google-diff-match-patch:" + DIFF_MATCH_PATCH_VERSION,
-    attach_source = False,
-    sha1 = "0cf1782dbcb8359d95070da9176059a5a9d37709",
-)
-
-maven_jar(
     name = "commons-io",
     artifact = "commons-io:commons-io:2.2",
     sha1 = "83b5b8a7ba1c08f9e8c8ff2373724e33d3c1e22a",
@@ -1127,6 +1052,12 @@
     sha1 = "65bd0cacc9c79a21c6ed8e9f588577cd3c2f85b9",
 )
 
+maven_jar(
+    name = "javax-activation",
+    artifact = "javax.activation:activation:1.1.1",
+    sha1 = "485de3a253e23f645037828c07f1d7f1af40763a",
+)
+
 load("//tools/bzl:js.bzl", "bower_archive", "npm_binary")
 
 # NPM binaries bundled along with their dependencies.
diff --git a/gerrit-gwtdebug/BUILD b/gerrit-gwtdebug/BUILD
deleted file mode 100644
index f564745..0000000
--- a/gerrit-gwtdebug/BUILD
+++ /dev/null
@@ -1,16 +0,0 @@
-java_library(
-    name = "gwtdebug",
-    srcs = glob(["src/main/java/**/*.java"]),
-    visibility = ["//visibility:public"],
-    deps = [
-        "//java/com/google/gerrit/pgm",
-        "//java/com/google/gerrit/pgm/util",
-        "//java/com/google/gerrit/util/cli",
-        "//lib/flogger:api",
-        "//lib/gwt:dev",
-        "//lib/jetty:server",
-        "//lib/jetty:servlet",
-        "//lib/jetty:servlets",
-        "//lib/log:log4j",
-    ],
-)
diff --git a/gerrit-gwtdebug/src/main/java/com/google/gerrit/gwtdebug/GerritGwtDebugLauncher.java b/gerrit-gwtdebug/src/main/java/com/google/gerrit/gwtdebug/GerritGwtDebugLauncher.java
deleted file mode 100644
index cf84919..0000000
--- a/gerrit-gwtdebug/src/main/java/com/google/gerrit/gwtdebug/GerritGwtDebugLauncher.java
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.gwtdebug;
-
-import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.pgm.Daemon;
-import com.google.gwt.dev.codeserver.CodeServer;
-import com.google.gwt.dev.codeserver.Options;
-import java.util.ArrayList;
-import java.util.List;
-
-class GerritGwtDebugLauncher {
-  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
-  public static void main(String[] argv) throws Exception {
-    GerritGwtDebugLauncher launcher = new GerritGwtDebugLauncher();
-    launcher.mainImpl(argv);
-  }
-
-  private int mainImpl(String[] argv) {
-    List<String> sdmLauncherOptions = new ArrayList<>();
-    List<String> daemonLauncherOptions = new ArrayList<>();
-
-    // Separator between Daemon and Codeserver parameters is "--"
-    boolean daemonArgumentSeparator = false;
-    int i = 0;
-    for (; i < argv.length; i++) {
-      if (!argv[i].equals("--")) {
-        sdmLauncherOptions.add(argv[i]);
-      } else {
-        daemonArgumentSeparator = true;
-        break;
-      }
-    }
-    if (daemonArgumentSeparator) {
-      ++i;
-      for (; i < argv.length; i++) {
-        daemonLauncherOptions.add(argv[i]);
-      }
-    }
-
-    Options options = new Options();
-    if (!options.parseArgs(sdmLauncherOptions.toArray(new String[sdmLauncherOptions.size()]))) {
-      logger.atSevere().log("Failed to parse codeserver arguments");
-      return 1;
-    }
-
-    CodeServer.main(options);
-
-    try {
-      int r =
-          new Daemon()
-              .main(daemonLauncherOptions.toArray(new String[daemonLauncherOptions.size()]));
-      if (r != 0) {
-        logger.atSevere().log("Daemon exited with return code: %d", r);
-        return 1;
-      }
-    } catch (Exception e) {
-      logger.atSevere().withCause(e).log("Cannot start daemon");
-      return 1;
-    }
-
-    return 0;
-  }
-}
diff --git a/gerrit-gwtui-common/BUILD b/gerrit-gwtui-common/BUILD
deleted file mode 100644
index 46019ab..0000000
--- a/gerrit-gwtui-common/BUILD
+++ /dev/null
@@ -1,62 +0,0 @@
-load("//tools/bzl:java.bzl", "java_library2")
-load("//tools/bzl:junit.bzl", "junit_tests")
-load("//tools/bzl:gwt.bzl", "gwt_module")
-
-EXPORTED_DEPS = [
-    "//java/com/google/gerrit/common:client",
-    "//java/com/google/gwtexpui/clippy",
-    "//java/com/google/gwtexpui/globalkey",
-    "//java/com/google/gwtexpui/progress",
-    "//java/com/google/gwtexpui/safehtml",
-    "//java/com/google/gwtexpui/user:agent",
-]
-
-DEPS = ["//lib/gwt:user-neverlink"]
-
-SRC = "src/main/java/com/google/gerrit/"
-
-gwt_module(
-    name = "client",
-    srcs = glob(["src/main/**/*.java"]),
-    exported_deps = EXPORTED_DEPS,
-    gwt_xml = SRC + "GerritGwtUICommon.gwt.xml",
-    resources = glob(
-        ["src/main/**/*"],
-        exclude = [SRC + "client/**/*.java"] + [
-            SRC + "GerritGwtUICommon.gwt.xml",
-        ],
-    ),
-    visibility = ["//visibility:public"],
-    deps = DEPS,
-)
-
-java_library2(
-    name = "client-lib",
-    srcs = glob(["src/main/**/*.java"]),
-    exported_deps = EXPORTED_DEPS,
-    resources = glob(["src/main/**/*"]),
-    visibility = ["//visibility:public"],
-    deps = DEPS,
-)
-
-java_library(
-    name = "diffy_logo",
-    data = [
-        "//lib:LICENSE-CC-BY3.0-unported",
-        "//lib:LICENSE-diffy",
-    ],
-    resources = glob(["src/main/resources/com/google/gerrit/client/diffy*.png"]),
-    visibility = ["//visibility:public"],
-)
-
-junit_tests(
-    name = "client_tests",
-    srcs = glob(["src/test/java/**/*.java"]),
-    visibility = ["//visibility:public"],
-    deps = [
-        ":client",
-        "//lib:junit",
-        "//lib/gwt:dev",
-        "//lib/jgit/org.eclipse.jgit:jgit",
-    ],
-)
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/GerritGwtUICommon.gwt.xml b/gerrit-gwtui-common/src/main/java/com/google/gerrit/GerritGwtUICommon.gwt.xml
deleted file mode 100644
index dc478fc..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/GerritGwtUICommon.gwt.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<!--
- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the 'License');
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an 'AS IS' BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<module>
-  <inherits name='org.eclipse.jgit.JGit'/>
-  <inherits name='com.google.gerrit.common.Common'/>
-  <inherits name='com.google.gerrit.extensions.Extensions'/>
-  <inherits name='com.google.gerrit.prettify.PrettyFormatter'/>
-  <inherits name='com.google.gwtexpui.clippy.Clippy'/>
-  <inherits name='com.google.gwtexpui.globalkey.GlobalKey'/>
-  <inherits name='com.google.gwtexpui.progress.Progress'/>
-  <inherits name='com.google.gwtexpui.safehtml.SafeHtml'/>
-  <source path='client'>
-    <include name='AccountFormatter.java'/>
-    <include name='CommonConstants.java'/>
-    <include name='CommonMessages.java'/>
-    <include name='DateFormatter.java'/>
-    <include name='GerritUiExtensionPoint.java'/>
-    <include name='RelativeDateFormatter.java'/>
-    <include name='Resources.java'/>
-    <include name='CommonConstants.properties'/>
-    <include name='CommonMessages.properties'/>
-    <include name='info/*.java'/>
-    <include name='rpc/NativeMap.java'/>
-    <include name='rpc/Natives.java'/>
-    <include name='rpc/NativeString.java'/>
-    <include name='rpc/TransformCallback.java'/>
-    <include name='ui/HighlightSuggestion.java'/>
-    <include name='ui/RemoteSuggestOracle.java'/>
-  </source>
-</module>
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/AccountFormatter.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/AccountFormatter.java
deleted file mode 100644
index 3058971..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/AccountFormatter.java
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gerrit.client.info.AccountInfo;
-
-public class AccountFormatter {
-  private final String anonymousCowardName;
-
-  public AccountFormatter(String anonymousCowardName) {
-    this.anonymousCowardName = anonymousCowardName;
-  }
-
-  /**
-   * Formats an account as a name and an email address.
-   *
-   * <p>Example output:
-   *
-   * <ul>
-   *   <li>{@code A U. Thor &lt;author@example.com&gt;}: full populated
-   *   <li>{@code A U. Thor (12)}: missing email address
-   *   <li>{@code Anonymous Coward &lt;author@example.com&gt;}: missing name
-   *   <li>{@code Anonymous Coward (12)}: missing name and email address
-   * </ul>
-   */
-  public String nameEmail(AccountInfo info) {
-    String name = info.name();
-    if (name == null || name.trim().isEmpty()) {
-      name = anonymousCowardName;
-    }
-
-    StringBuilder b = new StringBuilder().append(name);
-    if (info.email() != null) {
-      b.append(" <").append(info.email()).append(">");
-    } else if (info._accountId() > 0) {
-      b.append(" (").append(info._accountId()).append(")");
-    }
-    return b.toString();
-  }
-
-  /**
-   * Formats an account name.
-   *
-   * <p>If the account has a full name, it returns only the full name. Otherwise it returns a longer
-   * form that includes the email address.
-   */
-  public String name(AccountInfo ai) {
-    if (ai.name() != null && !ai.name().trim().isEmpty()) {
-      return ai.name();
-    }
-    String email = ai.email();
-    if (email != null) {
-      int at = email.indexOf('@');
-      return 0 < at ? email.substring(0, at) : email;
-    }
-    return nameEmail(ai);
-  }
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/CommonConstants.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/CommonConstants.java
deleted file mode 100644
index e769730..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/CommonConstants.java
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.i18n.client.Constants;
-
-public interface CommonConstants extends Constants {
-  CommonConstants C = GWT.create(CommonConstants.class);
-
-  String inTheFuture();
-
-  String month();
-
-  String months();
-
-  String year();
-
-  String years();
-
-  String oneSecondAgo();
-
-  String oneMinuteAgo();
-
-  String oneHourAgo();
-
-  String oneDayAgo();
-
-  String oneWeekAgo();
-
-  String oneMonthAgo();
-
-  String oneYearAgo();
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/CommonConstants.properties b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/CommonConstants.properties
deleted file mode 100644
index 3202bfc..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/CommonConstants.properties
+++ /dev/null
@@ -1,13 +0,0 @@
-inTheFuture = in the future
-month = month
-months = months
-years = years
-year = year
-
-oneSecondAgo = 1 second ago
-oneMinuteAgo = 1 minute ago
-oneHourAgo = 1 hour ago
-oneDayAgo = 1 day ago
-oneWeekAgo = 1 week ago
-oneMonthAgo = 1 month ago
-oneYearAgo = 1 year ago
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/CommonMessages.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/CommonMessages.java
deleted file mode 100644
index 5314254..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/CommonMessages.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.i18n.client.Messages;
-
-public interface CommonMessages extends Messages {
-  CommonMessages M = GWT.create(CommonMessages.class);
-
-  String secondsAgo(long seconds);
-
-  String minutesAgo(long minutes);
-
-  String hoursAgo(long hours);
-
-  String daysAgo(long days);
-
-  String weeksAgo(long weeks);
-
-  String monthsAgo(long months);
-
-  String yearsAgo(long years);
-
-  String years0MonthsAgo(long years, String yearLabel);
-
-  String yearsMonthsAgo(long years, String yearLabel, long months, String monthLabel);
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/CommonMessages.properties b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/CommonMessages.properties
deleted file mode 100644
index 738602e..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/CommonMessages.properties
+++ /dev/null
@@ -1,9 +0,0 @@
-secondsAgo = {0} seconds ago
-minutesAgo = {0} minutes ago
-hoursAgo = {0} hours ago
-daysAgo = {0} days ago
-weeksAgo = {0} weeks ago
-monthsAgo = {0} months ago
-years0MonthsAgo = {0} {1} ago
-yearsMonthsAgo = {0} {1}, {2} {3} ago
-yearsAgo = {0} years ago
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/DateFormatter.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/DateFormatter.java
deleted file mode 100644
index 4df2f5f..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/DateFormatter.java
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gerrit.client.info.GeneralPreferences;
-import com.google.gwt.i18n.client.DateTimeFormat;
-import java.util.Date;
-
-public class DateFormatter {
-  private static final long ONE_YEAR = 182L * 24 * 60 * 60 * 1000;
-
-  private final DateTimeFormat sTime;
-  private final DateTimeFormat sDate;
-  private final DateTimeFormat sdtFmt;
-  private final DateTimeFormat mDate;
-  private final DateTimeFormat dtfmt;
-
-  public DateFormatter(GeneralPreferences prefs) {
-    String fmt_sTime = prefs.timeFormat().getFormat();
-    String fmt_sDate = prefs.dateFormat().getShortFormat();
-    String fmt_mDate = prefs.dateFormat().getLongFormat();
-
-    sTime = DateTimeFormat.getFormat(fmt_sTime);
-    sDate = DateTimeFormat.getFormat(fmt_sDate);
-    sdtFmt = DateTimeFormat.getFormat(fmt_sDate + " " + fmt_sTime);
-    mDate = DateTimeFormat.getFormat(fmt_mDate);
-    dtfmt = DateTimeFormat.getFormat(fmt_mDate + " " + fmt_sTime);
-  }
-
-  /** Format a date using a really short format. */
-  public String shortFormat(Date dt) {
-    if (dt == null) {
-      return "";
-    }
-
-    Date now = new Date();
-    dt = new Date(dt.getTime());
-    if (mDate.format(now).equals(mDate.format(dt))) {
-      // Same day as today, report only the time.
-      //
-      return sTime.format(dt);
-
-    } else if (Math.abs(now.getTime() - dt.getTime()) < ONE_YEAR) {
-      // Within the last year, show a shorter date.
-      //
-      return sDate.format(dt);
-
-    } else {
-      // Report only date and year, its far away from now.
-      //
-      return mDate.format(dt);
-    }
-  }
-
-  /** Format a date using a really short format. */
-  public String shortFormatDayTime(Date dt) {
-    if (dt == null) {
-      return "";
-    }
-
-    Date now = new Date();
-    dt = new Date(dt.getTime());
-    if (mDate.format(now).equals(mDate.format(dt))) {
-      // Same day as today, report only the time.
-      //
-      return sTime.format(dt);
-
-    } else if (Math.abs(now.getTime() - dt.getTime()) < ONE_YEAR) {
-      // Within the last year, show a shorter date.
-      //
-      return sdtFmt.format(dt);
-
-    } else {
-      // Report only date and year, its far away from now.
-      //
-      return mDate.format(dt);
-    }
-  }
-
-  /** Format a date using the locale's medium length format. */
-  public String mediumFormat(Date dt) {
-    if (dt == null) {
-      return "";
-    }
-    return dtfmt.format(new Date(dt.getTime()));
-  }
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/GerritUiExtensionPoint.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/GerritUiExtensionPoint.java
deleted file mode 100644
index 66a3b6b..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/GerritUiExtensionPoint.java
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-public enum GerritUiExtensionPoint {
-  /* ChangeScreen */
-  CHANGE_SCREEN_HEADER,
-  CHANGE_SCREEN_HEADER_RIGHT_OF_BUTTONS,
-  CHANGE_SCREEN_HEADER_RIGHT_OF_POP_DOWNS,
-  CHANGE_SCREEN_BELOW_CHANGE_INFO_BLOCK,
-  CHANGE_SCREEN_BELOW_RELATED_INFO_BLOCK,
-  CHANGE_SCREEN_BELOW_COMMIT_INFO_BLOCK,
-  CHANGE_SCREEN_HISTORY_RIGHT_OF_BUTTONS,
-
-  /* MyPasswordScreen */
-  PASSWORD_SCREEN_BOTTOM,
-
-  /* MyPreferencesScreen */
-  PREFERENCES_SCREEN_BOTTOM,
-
-  /* MyProfileScreen */
-  PROFILE_SCREEN_BOTTOM,
-
-  /* ProjectInfoScreen */
-  PROJECT_INFO_SCREEN_TOP,
-  PROJECT_INFO_SCREEN_BOTTOM;
-
-  public enum Key {
-    ACCOUNT_INFO,
-    CHANGE_INFO,
-    PROJECT_NAME,
-    REVISION_INFO
-  }
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/RelativeDateFormatter.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/RelativeDateFormatter.java
deleted file mode 100644
index e0cc9ca..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/RelativeDateFormatter.java
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import java.util.Date;
-
-/**
- * Formatter to format timestamps relative to the current time using time units in the format
- * defined by {@code git log --relative-date}.
- */
-public class RelativeDateFormatter {
-  private static CommonConstants constants;
-  private static CommonMessages messages;
-
-  static final long SECOND_IN_MILLIS = 1000;
-  static final long MINUTE_IN_MILLIS = 60 * SECOND_IN_MILLIS;
-  static final long HOUR_IN_MILLIS = 60 * MINUTE_IN_MILLIS;
-  static final long DAY_IN_MILLIS = 24 * HOUR_IN_MILLIS;
-  static final long WEEK_IN_MILLIS = 7 * DAY_IN_MILLIS;
-  static final long MONTH_IN_MILLIS = 30 * DAY_IN_MILLIS;
-  static final long YEAR_IN_MILLIS = 365 * DAY_IN_MILLIS;
-
-  static void setConstants(CommonConstants c, CommonMessages m) {
-    constants = c;
-    messages = m;
-  }
-
-  private static CommonConstants c() {
-    return constants != null ? constants : CommonConstants.C;
-  }
-
-  private static CommonMessages m() {
-    return messages != null ? messages : CommonMessages.M;
-  }
-
-  /**
-   * @param when {@link Date} to format
-   * @return age of given {@link Date} compared to now formatted in the same relative format as
-   *     returned by {@code git log --relative-date}
-   */
-  public static String format(Date when) {
-    long ageMillis = (new Date()).getTime() - when.getTime();
-
-    // shouldn't happen in a perfect world
-    if (ageMillis < 0) {
-      return c().inTheFuture();
-    }
-
-    // seconds
-    if (ageMillis < upperLimit(MINUTE_IN_MILLIS)) {
-      long seconds = round(ageMillis, SECOND_IN_MILLIS);
-      if (seconds == 1) {
-        return c().oneSecondAgo();
-      }
-      return m().secondsAgo(seconds);
-    }
-
-    // minutes
-    if (ageMillis < upperLimit(HOUR_IN_MILLIS)) {
-      long minutes = round(ageMillis, MINUTE_IN_MILLIS);
-      if (minutes == 1) {
-        return c().oneMinuteAgo();
-      }
-      return m().minutesAgo(minutes);
-    }
-
-    // hours
-    if (ageMillis < upperLimit(DAY_IN_MILLIS)) {
-      long hours = round(ageMillis, HOUR_IN_MILLIS);
-      if (hours == 1) {
-        return c().oneHourAgo();
-      }
-      return m().hoursAgo(hours);
-    }
-
-    // up to 14 days use days
-    if (ageMillis < 14 * DAY_IN_MILLIS) {
-      long days = round(ageMillis, DAY_IN_MILLIS);
-      if (days == 1) {
-        return c().oneDayAgo();
-      }
-      return m().daysAgo(days);
-    }
-
-    // up to 10 weeks use weeks
-    if (ageMillis < 10 * WEEK_IN_MILLIS) {
-      long weeks = round(ageMillis, WEEK_IN_MILLIS);
-      if (weeks == 1) {
-        return c().oneWeekAgo();
-      }
-      return m().weeksAgo(weeks);
-    }
-
-    // months
-    if (ageMillis < YEAR_IN_MILLIS) {
-      long months = round(ageMillis, MONTH_IN_MILLIS);
-      if (months == 1) {
-        return c().oneMonthAgo();
-      }
-      return m().monthsAgo(months);
-    }
-
-    // up to 5 years use "year, months" rounded to months
-    if (ageMillis < 5 * YEAR_IN_MILLIS) {
-      long years = round(ageMillis, MONTH_IN_MILLIS) / 12;
-      String yearLabel = (years > 1) ? c().years() : c().year();
-      long months = round(ageMillis - years * YEAR_IN_MILLIS, MONTH_IN_MILLIS);
-      String monthLabel = (months > 1) ? c().months() : (months == 1 ? c().month() : "");
-      if (months == 0) {
-        return m().years0MonthsAgo(years, yearLabel);
-      }
-      return m().yearsMonthsAgo(years, yearLabel, months, monthLabel);
-    }
-
-    // years
-    long years = round(ageMillis, YEAR_IN_MILLIS);
-    if (years == 1) {
-      return c().oneYearAgo();
-    }
-    return m().yearsAgo(years);
-  }
-
-  private static long upperLimit(long unit) {
-    return unit + unit / 2;
-  }
-
-  private static long round(long n, long unit) {
-    return (n + unit / 2) / unit;
-  }
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/Resources.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/Resources.java
deleted file mode 100644
index 67627c3..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/Resources.java
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gwt.resources.client.ClientBundle;
-import com.google.gwt.resources.client.ImageResource;
-
-public interface Resources extends ClientBundle {
-  /** silk icons (CC-BY3.0): http://famfamfam.com/lab/icons/silk/ */
-  @Source("note_add.png")
-  ImageResource addFileComment();
-
-  @Source("tag_blue_add.png")
-  ImageResource addHashtag();
-
-  @Source("user_add.png")
-  ImageResource addUser();
-
-  @Source("user_edit.png")
-  ImageResource editUser();
-
-  // derived from resultset_next.png
-  @Source("resultset_down_gray.png")
-  ImageResource arrowDown();
-
-  // derived from resultset_next.png
-  @Source("resultset_next_gray.png")
-  ImageResource arrowRight();
-
-  // derived from resultset_next.png
-  @Source("resultset_up_gray.png")
-  ImageResource arrowUp();
-
-  @Source("lightbulb.png")
-  ImageResource blame();
-
-  @Source("page_white_put.png")
-  ImageResource downloadIcon();
-
-  // derived from comment.png
-  @Source("comment_draft.png")
-  ImageResource draftComments();
-
-  @Source("page_edit.png")
-  ImageResource edit();
-
-  @Source("arrow_undo.png")
-  ImageResource editUndo();
-
-  @Source("cog.png")
-  ImageResource gear();
-
-  @Source("tick.png")
-  ImageResource greenCheck();
-
-  @Source("tag_blue.png")
-  ImageResource hashtag();
-
-  @Source("lightbulb.png")
-  ImageResource info();
-
-  @Source("find.png")
-  ImageResource queryIcon();
-
-  @Source("lock.png")
-  ImageResource readOnly();
-
-  @Source("cross.png")
-  ImageResource redNot();
-
-  @Source("disk.png")
-  ImageResource save();
-
-  @Source("star.png")
-  ImageResource starFilled();
-
-  // derived from star.png
-  @Source("star-open.png")
-  ImageResource starOpen();
-
-  @Source("exclamation.png")
-  ImageResource warning();
-
-  @Source("help.png")
-  ImageResource question();
-
-  /** tango icon library (public domain): http://tango.freedesktop.org/Tango_Icon_Library */
-  @Source("goNext.png")
-  ImageResource goNext();
-
-  @Source("goPrev.png")
-  ImageResource goPrev();
-
-  @Source("goUp.png")
-  ImageResource goUp();
-
-  @Source("listAdd.png")
-  ImageResource listAdd();
-
-  // derived from important.png
-  @Source("merge.png")
-  ImageResource merge();
-
-  /** contributed by the artist under Apache2.0 */
-  @Source("sideBySideDiff.png")
-  ImageResource sideBySideDiff();
-
-  @Source("unifiedDiff.png")
-  ImageResource unifiedDiff();
-
-  /** contributed by the artist under CC-BY3.0 */
-  @Source("diffy26.png")
-  ImageResource gerritAvatar26();
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/AccountInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/AccountInfo.java
deleted file mode 100644
index e4c008c..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/AccountInfo.java
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.info;
-
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwtjsonrpc.client.impl.ser.JavaSqlTimestamp_JsonSerializer;
-import java.sql.Timestamp;
-
-public class AccountInfo extends JavaScriptObject {
-  public final native int _accountId() /*-{ return this._account_id || 0; }-*/;
-
-  public final native String name() /*-{ return this.name; }-*/;
-
-  public final native String email() /*-{ return this.email; }-*/;
-
-  public final native JsArrayString secondaryEmails() /*-{ return this.secondary_emails; }-*/;
-
-  public final native String username() /*-{ return this.username; }-*/;
-
-  public final Timestamp registeredOn() {
-    Timestamp ts = _getRegisteredOn();
-    if (ts == null) {
-      ts = JavaSqlTimestamp_JsonSerializer.parseTimestamp(registeredOnRaw());
-      _setRegisteredOn(ts);
-    }
-    return ts;
-  }
-
-  private native String registeredOnRaw() /*-{ return this.registered_on; }-*/;
-
-  private native Timestamp _getRegisteredOn() /*-{ return this._cts; }-*/;
-
-  private native void _setRegisteredOn(Timestamp ts) /*-{ this._cts = ts; }-*/;
-
-  /**
-   * @return true if the server supplied avatar information about this account. The information may
-   *     be an empty list, indicating no avatars are available, such as when no plugin is installed.
-   *     This method returns false if the server did not check on avatars for the account.
-   */
-  public final native boolean hasAvatarInfo() /*-{ return this.hasOwnProperty('avatars') }-*/;
-
-  public final AvatarInfo avatar(int sz) {
-    JsArray<AvatarInfo> a = avatars();
-    for (int i = 0; a != null && i < a.length(); i++) {
-      AvatarInfo r = a.get(i);
-      if (r.height() == sz) {
-        return r;
-      }
-    }
-    return null;
-  }
-
-  private native JsArray<AvatarInfo> avatars() /*-{ return this.avatars }-*/;
-
-  public final native void name(String n) /*-{ this.name = n }-*/;
-
-  public final native void email(String e) /*-{ this.email = e }-*/;
-
-  public final native void username(String n) /*-{ this.username = n }-*/;
-
-  public static native AccountInfo create(int id, String name, String email, String username) /*-{
-    return {'_account_id': id, 'name': name, 'email': email,
-        'username': username};
-  }-*/;
-
-  protected AccountInfo() {}
-
-  public static class AvatarInfo extends JavaScriptObject {
-    public static final int DEFAULT_SIZE = 26;
-
-    public final native String url() /*-{ return this.url }-*/;
-
-    public final native int height() /*-{ return this.height || 0 }-*/;
-
-    public final native int width() /*-{ return this.width || 0 }-*/;
-
-    protected AvatarInfo() {}
-  }
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/ActionInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/ActionInfo.java
deleted file mode 100644
index d09d5b7..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/ActionInfo.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.info;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class ActionInfo extends JavaScriptObject {
-
-  public final native String id() /*-{ return this.id; }-*/;
-
-  public final native String method() /*-{ return this.method; }-*/;
-
-  public final native String label() /*-{ return this.label; }-*/;
-
-  public final native String title() /*-{ return this.title; }-*/;
-
-  public final native boolean enabled() /*-{ return this.enabled || false; }-*/;
-
-  protected ActionInfo() {}
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/AgreementInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/AgreementInfo.java
deleted file mode 100644
index 04fba4f..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/AgreementInfo.java
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.info;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class AgreementInfo extends JavaScriptObject {
-  public final native String name() /*-{ return this.name; }-*/;
-
-  public final native String description() /*-{ return this.description; }-*/;
-
-  public final native String url() /*-{ return this.url; }-*/;
-
-  public final native GroupInfo autoVerifyGroup() /*-{ return this.auto_verify_group; }-*/;
-
-  protected AgreementInfo() {}
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/AuthInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/AuthInfo.java
deleted file mode 100644
index 43281bd..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/AuthInfo.java
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.info;
-
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.extensions.client.AccountFieldName;
-import com.google.gerrit.extensions.client.AuthType;
-import com.google.gerrit.extensions.client.GitBasicAuthPolicy;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.JsArrayString;
-import java.util.ArrayList;
-import java.util.List;
-
-public class AuthInfo extends JavaScriptObject {
-  public final AuthType authType() {
-    return AuthType.valueOf(authTypeRaw());
-  }
-
-  public final boolean isLdap() {
-    return authType() == AuthType.LDAP || authType() == AuthType.LDAP_BIND;
-  }
-
-  public final boolean isOpenId() {
-    return authType() == AuthType.OPENID;
-  }
-
-  public final boolean isOAuth() {
-    return authType() == AuthType.OAUTH;
-  }
-
-  public final boolean isDev() {
-    return authType() == AuthType.DEVELOPMENT_BECOME_ANY_ACCOUNT;
-  }
-
-  public final boolean isClientSslCertLdap() {
-    return authType() == AuthType.CLIENT_SSL_CERT_LDAP;
-  }
-
-  public final boolean isCustomExtension() {
-    return authType() == AuthType.CUSTOM_EXTENSION;
-  }
-
-  public final boolean canEdit(AccountFieldName f) {
-    return editableAccountFields().contains(f);
-  }
-
-  public final List<AccountFieldName> editableAccountFields() {
-    List<AccountFieldName> fields = new ArrayList<>();
-    for (String f : Natives.asList(_editableAccountFields())) {
-      fields.add(AccountFieldName.valueOf(f));
-    }
-    return fields;
-  }
-
-  public final List<AgreementInfo> contributorAgreements() {
-    List<AgreementInfo> agreements = new ArrayList<>();
-    JsArray<AgreementInfo> contributorAgreements = _contributorAgreements();
-    if (contributorAgreements != null) {
-      agreements.addAll(Natives.asList(contributorAgreements));
-    }
-    return agreements;
-  }
-
-  public final boolean siteHasUsernames() {
-    if (isCustomExtension() && httpPasswordUrl() != null && !canEdit(AccountFieldName.USER_NAME)) {
-      return false;
-    }
-    return true;
-  }
-
-  public final boolean isHttpPasswordSettingsEnabled() {
-    return gitBasicAuthPolicy() == GitBasicAuthPolicy.HTTP
-        || gitBasicAuthPolicy() == GitBasicAuthPolicy.HTTP_LDAP;
-  }
-
-  public final GitBasicAuthPolicy gitBasicAuthPolicy() {
-    return GitBasicAuthPolicy.valueOf(gitBasicAuthPolicyRaw());
-  }
-
-  public final native boolean useContributorAgreements()
-      /*-{ return this.use_contributor_agreements || false; }-*/ ;
-
-  public final native String loginUrl() /*-{ return this.login_url; }-*/;
-
-  public final native String loginText() /*-{ return this.login_text; }-*/;
-
-  public final native String switchAccountUrl() /*-{ return this.switch_account_url; }-*/;
-
-  public final native String registerUrl() /*-{ return this.register_url; }-*/;
-
-  public final native String registerText() /*-{ return this.register_text; }-*/;
-
-  public final native String editFullNameUrl() /*-{ return this.edit_full_name_url; }-*/;
-
-  public final native String httpPasswordUrl() /*-{ return this.http_password_url; }-*/;
-
-  private native String gitBasicAuthPolicyRaw() /*-{ return this.git_basic_auth_policy; }-*/;
-
-  private native String authTypeRaw() /*-{ return this.auth_type; }-*/;
-
-  private native JsArrayString _editableAccountFields()
-      /*-{ return this.editable_account_fields; }-*/ ;
-
-  private native JsArray<AgreementInfo> _contributorAgreements()
-      /*-{ return this.contributor_agreements; }-*/ ;
-
-  protected AuthInfo() {}
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/ChangeInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/ChangeInfo.java
deleted file mode 100644
index 0f786a6..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/ChangeInfo.java
+++ /dev/null
@@ -1,575 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.info;
-
-import static java.util.Comparator.comparing;
-
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.NativeString;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.common.data.LabelValue;
-import com.google.gerrit.common.data.SubmitRecord;
-import com.google.gerrit.extensions.client.ReviewerState;
-import com.google.gerrit.extensions.client.SubmitType;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwtjsonrpc.client.impl.ser.JavaSqlTimestamp_JsonSerializer;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-public class ChangeInfo extends JavaScriptObject {
-  public final void init() {
-    if (allLabels() != null) {
-      allLabels().copyKeysIntoChildren("_name");
-    }
-  }
-
-  public final Project.NameKey projectNameKey() {
-    return new Project.NameKey(project());
-  }
-
-  public final Change.Id legacyId() {
-    return new Change.Id(_number());
-  }
-
-  public final Timestamp created() {
-    Timestamp ts = _getCts();
-    if (ts == null) {
-      ts = JavaSqlTimestamp_JsonSerializer.parseTimestamp(createdRaw());
-      _setCts(ts);
-    }
-    return ts;
-  }
-
-  public final boolean hasEditBasedOnCurrentPatchSet() {
-    JsArray<RevisionInfo> revList = revisions().values();
-    RevisionInfo.sortRevisionInfoByNumber(revList);
-    return revList.get(revList.length() - 1).isEdit();
-  }
-
-  private native Timestamp _getCts() /*-{ return this._cts; }-*/;
-
-  private native void _setCts(Timestamp ts) /*-{ this._cts = ts; }-*/;
-
-  public final Timestamp updated() {
-    return JavaSqlTimestamp_JsonSerializer.parseTimestamp(updatedRaw());
-  }
-
-  public final Timestamp submitted() {
-    return JavaSqlTimestamp_JsonSerializer.parseTimestamp(submittedRaw());
-  }
-
-  public final String idAbbreviated() {
-    return new Change.Key(changeId()).abbreviate();
-  }
-
-  public final Change.Status status() {
-    return Change.Status.valueOf(statusRaw());
-  }
-
-  public final Set<String> labels() {
-    return allLabels().keySet();
-  }
-
-  public final Set<Integer> removableReviewerIds() {
-    Set<Integer> removable = new HashSet<>();
-    if (removableReviewers() != null) {
-      for (AccountInfo a : Natives.asList(removableReviewers())) {
-        removable.add(a._accountId());
-      }
-    }
-    return removable;
-  }
-
-  public final native String id() /*-{ return this.id; }-*/;
-
-  public final native String project() /*-{ return this.project; }-*/;
-
-  public final native String branch() /*-{ return this.branch; }-*/;
-
-  public final native String topic() /*-{ return this.topic; }-*/;
-
-  public final native String changeId() /*-{ return this.change_id; }-*/;
-
-  public final native boolean mergeable() /*-{ return this.mergeable ? true : false; }-*/;
-
-  public final native int insertions() /*-{ return this.insertions; }-*/;
-
-  public final native int deletions() /*-{ return this.deletions; }-*/;
-
-  private native String statusRaw() /*-{ return this.status; }-*/;
-
-  public final native String subject() /*-{ return this.subject; }-*/;
-
-  public final native AccountInfo owner() /*-{ return this.owner; }-*/;
-
-  public final native AccountInfo assignee() /*-{ return this.assignee; }-*/;
-
-  private native String createdRaw() /*-{ return this.created; }-*/;
-
-  private native String updatedRaw() /*-{ return this.updated; }-*/;
-
-  private native String submittedRaw() /*-{ return this.submitted; }-*/;
-
-  public final native AccountInfo submitter() /*-{ return this.submitter; }-*/;
-
-  public final native boolean starred() /*-{ return this.starred ? true : false; }-*/;
-
-  public final native boolean reviewed() /*-{ return this.reviewed ? true : false; }-*/;
-
-  public final native boolean isPrivate() /*-{ return this.is_private ? true : false; }-*/;
-
-  public final native boolean
-      isWorkInProgress() /*-{ return this.work_in_progress ? true : false; }-*/;
-
-  public final native NativeMap<LabelInfo> allLabels() /*-{ return this.labels; }-*/;
-
-  public final native LabelInfo label(String n) /*-{ return this.labels[n]; }-*/;
-
-  public final native String currentRevision() /*-{ return this.current_revision; }-*/;
-
-  public final native void setCurrentRevision(String r) /*-{ this.current_revision = r; }-*/;
-
-  public final native NativeMap<RevisionInfo> revisions() /*-{ return this.revisions; }-*/;
-
-  public final native RevisionInfo revision(String n) /*-{ return this.revisions[n]; }-*/;
-
-  public final native JsArray<MessageInfo> messages() /*-{ return this.messages; }-*/;
-
-  public final native void setEdit(EditInfo edit) /*-{ this.edit = edit; }-*/;
-
-  public final native EditInfo edit() /*-{ return this.edit; }-*/;
-
-  public final native boolean hasEdit() /*-{ return this.hasOwnProperty('edit') }-*/;
-
-  public final native JsArrayString hashtags() /*-{ return this.hashtags; }-*/;
-
-  public final native boolean hasPermittedLabels()
-      /*-{ return this.hasOwnProperty('permitted_labels') }-*/ ;
-
-  public final native NativeMap<JsArrayString> permittedLabels()
-      /*-{ return this.permitted_labels; }-*/ ;
-
-  public final native JsArrayString permittedValues(String n)
-      /*-{ return this.permitted_labels[n]; }-*/ ;
-
-  public final native JsArray<AccountInfo> removableReviewers()
-      /*-{ return this.removable_reviewers; }-*/ ;
-
-  private native NativeMap<JsArray<AccountInfo>> _reviewers() /*-{ return this.reviewers; }-*/;
-
-  public final Map<ReviewerState, List<AccountInfo>> reviewers() {
-    NativeMap<JsArray<AccountInfo>> reviewers = _reviewers();
-    Map<ReviewerState, List<AccountInfo>> result = new HashMap<>();
-    for (String k : reviewers.keySet()) {
-      ReviewerState state = ReviewerState.valueOf(k.toUpperCase());
-      List<AccountInfo> accounts = result.get(state);
-      if (accounts == null) {
-        accounts = new ArrayList<>();
-        result.put(state, accounts);
-      }
-      accounts.addAll(Natives.asList(reviewers.get(k)));
-    }
-    return result;
-  }
-
-  public final native boolean hasActions() /*-{ return this.hasOwnProperty('actions') }-*/;
-
-  public final native NativeMap<ActionInfo> actions() /*-{ return this.actions; }-*/;
-
-  public final native int _number() /*-{ return this._number; }-*/;
-
-  public final native boolean _more_changes() /*-{ return this._more_changes ? true : false; }-*/;
-
-  public final SubmitType submitType() {
-    String submitType = _submitType();
-    if (submitType == null) {
-      return null;
-    }
-    return SubmitType.valueOf(submitType);
-  }
-
-  private native String _submitType() /*-{ return this.submit_type; }-*/;
-
-  public final boolean submittable() {
-    init();
-    return _submittable();
-  }
-
-  private native boolean _submittable() /*-{ return this.submittable ? true : false; }-*/;
-
-  /**
-   * @return the index of the missing label or -1 if no label is missing, or if more than one label
-   *     is missing.
-   */
-  public final int getMissingLabelIndex() {
-    int i = -1;
-    int ret = -1;
-    List<LabelInfo> labels = Natives.asList(allLabels().values());
-    for (LabelInfo label : labels) {
-      i++;
-      if (!permittedLabels().containsKey(label.name())) {
-        continue;
-      }
-
-      JsArrayString values = permittedValues(label.name());
-      if (values.length() == 0) {
-        continue;
-      }
-
-      switch (label.status()) {
-        case NEED: // Label is required for submit.
-          if (ret != -1) {
-            // more than one label is missing, so it's unclear which to quick
-            // approve, return -1
-            return -1;
-          }
-          ret = i;
-          continue;
-
-        case OK: // Label already applied.
-        case MAY: // Label is not required.
-          continue;
-
-        case REJECT: // Submit cannot happen, do not quick approve.
-        case IMPOSSIBLE:
-          return -1;
-      }
-    }
-    return ret;
-  }
-
-  protected ChangeInfo() {}
-
-  public static class LabelInfo extends JavaScriptObject {
-    public final SubmitRecord.Label.Status status() {
-      if (approved() != null) {
-        return SubmitRecord.Label.Status.OK;
-      } else if (rejected() != null) {
-        return SubmitRecord.Label.Status.REJECT;
-      } else if (optional()) {
-        return SubmitRecord.Label.Status.MAY;
-      } else {
-        return SubmitRecord.Label.Status.NEED;
-      }
-    }
-
-    public final native String name() /*-{ return this._name; }-*/;
-
-    public final native AccountInfo approved() /*-{ return this.approved; }-*/;
-
-    public final native AccountInfo rejected() /*-{ return this.rejected; }-*/;
-
-    public final native AccountInfo recommended() /*-{ return this.recommended; }-*/;
-
-    public final native AccountInfo disliked() /*-{ return this.disliked; }-*/;
-
-    public final native JsArray<ApprovalInfo> all() /*-{ return this.all; }-*/;
-
-    public final ApprovalInfo forUser(int user) {
-      JsArray<ApprovalInfo> all = all();
-      for (int i = 0; all != null && i < all.length(); i++) {
-        if (all.get(i)._accountId() == user) {
-          return all.get(i);
-        }
-      }
-      return null;
-    }
-
-    private native NativeMap<NativeString> _values() /*-{ return this.values; }-*/;
-
-    public final Set<String> values() {
-      return Natives.keys(_values());
-    }
-
-    public final native String valueText(String n) /*-{ return this.values[n]; }-*/;
-
-    public final native boolean optional() /*-{ return this.optional ? true : false; }-*/;
-
-    public final native boolean blocking() /*-{ return this.blocking ? true : false; }-*/;
-
-    public final native short defaultValue() /*-{ return this.default_value; }-*/;
-
-    public final native short _value() /*-{
-      if (this.value) return this.value;
-      if (this.disliked) return -1;
-      if (this.recommended) return 1;
-      return 0;
-    }-*/;
-
-    public final String maxValue() {
-      return LabelValue.formatValue(valueSet().last());
-    }
-
-    public final SortedSet<Short> valueSet() {
-      SortedSet<Short> values = new TreeSet<>();
-      for (String v : values()) {
-        values.add(parseValue(v));
-      }
-      return values;
-    }
-
-    public static final short parseValue(String formatted) {
-      if (formatted.startsWith("+")) {
-        formatted = formatted.substring(1);
-      } else if (formatted.startsWith(" ")) {
-        formatted = formatted.trim();
-      }
-      return Short.parseShort(formatted);
-    }
-
-    protected LabelInfo() {}
-  }
-
-  public static class ApprovalInfo extends AccountInfo {
-    public final native boolean hasValue() /*-{ return this.hasOwnProperty('value'); }-*/;
-
-    public final native short value() /*-{ return this.value || 0; }-*/;
-
-    public final native VotingRangeInfo
-        permittedVotingRange() /*-{ return this.permitted_voting_range; }-*/;
-
-    protected ApprovalInfo() {}
-  }
-
-  public static class VotingRangeInfo extends AccountInfo {
-    public final native short min() /*-{ return this.min || 0; }-*/;
-
-    public final native short max() /*-{ return this.max || 0; }-*/;
-
-    protected VotingRangeInfo() {}
-  }
-
-  public static class EditInfo extends JavaScriptObject {
-    public final native String name() /*-{ return this.name; }-*/;
-
-    public final native String setName(String n) /*-{ this.name = n; }-*/;
-
-    public final native String baseRevision() /*-{ return this.base_revision; }-*/;
-
-    public final native CommitInfo commit() /*-{ return this.commit; }-*/;
-
-    public final native boolean hasActions() /*-{ return this.hasOwnProperty('actions') }-*/;
-
-    public final native NativeMap<ActionInfo> actions() /*-{ return this.actions; }-*/;
-
-    public final native boolean hasFetch() /*-{ return this.hasOwnProperty('fetch') }-*/;
-
-    public final native NativeMap<FetchInfo> fetch() /*-{ return this.fetch; }-*/;
-
-    public final native boolean hasFiles() /*-{ return this.hasOwnProperty('files') }-*/;
-
-    public final native NativeMap<FileInfo> files() /*-{ return this.files; }-*/;
-
-    protected EditInfo() {}
-  }
-
-  public static class RevisionInfo extends JavaScriptObject {
-    public static RevisionInfo fromEdit(EditInfo edit) {
-      RevisionInfo revisionInfo = createObject().cast();
-      revisionInfo.takeFromEdit(edit);
-      return revisionInfo;
-    }
-
-    public static RevisionInfo forParent(int number, CommitInfo commit) {
-      RevisionInfo revisionInfo = createObject().cast();
-      revisionInfo.takeFromParent(number, commit);
-      return revisionInfo;
-    }
-
-    private native void takeFromEdit(EditInfo edit) /*-{
-      this._number = 0;
-      this.name = edit.name;
-      this.commit = edit.commit;
-      this.edit_base = edit.base_revision;
-    }-*/;
-
-    private native void takeFromParent(int number, CommitInfo commit) /*-{
-      this._number = number;
-      this.commit = commit;
-      this.name = this._number;
-    }-*/;
-
-    public final native int _number() /*-{ return this._number; }-*/;
-
-    public final native String name() /*-{ return this.name; }-*/;
-
-    public final native AccountInfo uploader() /*-{ return this.uploader; }-*/;
-
-    public final native boolean isEdit() /*-{ return this._number == 0; }-*/;
-
-    public final native CommitInfo commit() /*-{ return this.commit; }-*/;
-
-    public final native void setCommit(CommitInfo c) /*-{ this.commit = c; }-*/;
-
-    public final native String editBase() /*-{ return this.edit_base; }-*/;
-
-    public final native boolean hasFiles() /*-{ return this.hasOwnProperty('files') }-*/;
-
-    public final native NativeMap<FileInfo> files() /*-{ return this.files; }-*/;
-
-    public final native boolean hasActions() /*-{ return this.hasOwnProperty('actions') }-*/;
-
-    public final native NativeMap<ActionInfo> actions() /*-{ return this.actions; }-*/;
-
-    public final native boolean hasFetch() /*-{ return this.hasOwnProperty('fetch') }-*/;
-
-    public final native NativeMap<FetchInfo> fetch() /*-{ return this.fetch; }-*/;
-
-    public final native boolean
-        hasPushCertificate() /*-{ return this.hasOwnProperty('push_certificate'); }-*/;
-
-    public final native PushCertificateInfo
-        pushCertificate() /*-{ return this.push_certificate; }-*/;
-
-    public static void sortRevisionInfoByNumber(JsArray<RevisionInfo> list) {
-      final int editParent = findEditParent(list);
-      Natives.asList(list)
-          .sort(comparing(r -> !r.isEdit() ? 2 * (r._number() - 1) + 1 : 2 * editParent));
-    }
-
-    public static int findEditParent(JsArray<RevisionInfo> list) {
-      RevisionInfo r = findEditParentRevision(list);
-      return r == null ? -1 : r._number();
-    }
-
-    public static RevisionInfo findEditParentRevision(JsArray<RevisionInfo> list) {
-      for (int i = 0; i < list.length(); i++) {
-        // edit under revisions?
-        RevisionInfo editInfo = list.get(i);
-        if (editInfo.isEdit()) {
-          String parentRevision = editInfo.editBase();
-          // find parent
-          for (int j = 0; j < list.length(); j++) {
-            RevisionInfo parentInfo = list.get(j);
-            String name = parentInfo.name();
-            if (name.equals(parentRevision)) {
-              // found parent pacth set number
-              return parentInfo;
-            }
-          }
-        }
-      }
-      return null;
-    }
-
-    public final String id() {
-      return PatchSet.Id.toId(_number());
-    }
-
-    public final boolean isMerge() {
-      return commit().parents().length() > 1;
-    }
-
-    protected RevisionInfo() {}
-  }
-
-  public static class FetchInfo extends JavaScriptObject {
-    public final native String url() /*-{ return this.url }-*/;
-
-    public final native String ref() /*-{ return this.ref }-*/;
-
-    public final native NativeMap<NativeString> commands() /*-{ return this.commands }-*/;
-
-    public final native String command(String n) /*-{ return this.commands[n]; }-*/;
-
-    protected FetchInfo() {}
-  }
-
-  public static class CommitInfo extends JavaScriptObject {
-    public final native String commit() /*-{ return this.commit; }-*/;
-
-    public final native JsArray<CommitInfo> parents() /*-{ return this.parents; }-*/;
-
-    public final native GitPerson author() /*-{ return this.author; }-*/;
-
-    public final native GitPerson committer() /*-{ return this.committer; }-*/;
-
-    public final native String subject() /*-{ return this.subject; }-*/;
-
-    public final native String message() /*-{ return this.message; }-*/;
-
-    public final native JsArray<WebLinkInfo> webLinks() /*-{ return this.web_links; }-*/;
-
-    protected CommitInfo() {}
-  }
-
-  public static class GitPerson extends JavaScriptObject {
-    public final native String name() /*-{ return this.name; }-*/;
-
-    public final native String email() /*-{ return this.email; }-*/;
-
-    private native String dateRaw() /*-{ return this.date; }-*/;
-
-    public final Timestamp date() {
-      return JavaSqlTimestamp_JsonSerializer.parseTimestamp(dateRaw());
-    }
-
-    protected GitPerson() {}
-  }
-
-  public static class MessageInfo extends JavaScriptObject {
-    public final native AccountInfo author() /*-{ return this.author; }-*/;
-
-    public final native String message() /*-{ return this.message; }-*/;
-
-    public final native int _revisionNumber() /*-{ return this._revision_number || 0; }-*/;
-
-    public final native String tag() /*-{ return this.tag; }-*/;
-
-    private native String dateRaw() /*-{ return this.date; }-*/;
-
-    public final Timestamp date() {
-      return JavaSqlTimestamp_JsonSerializer.parseTimestamp(dateRaw());
-    }
-
-    protected MessageInfo() {}
-  }
-
-  public static class MergeableInfo extends JavaScriptObject {
-    public final native String submitType() /*-{ return this.submit_type }-*/;
-
-    public final native boolean mergeable() /*-{ return this.mergeable }-*/;
-
-    protected MergeableInfo() {}
-  }
-
-  public static class IncludedInInfo extends JavaScriptObject {
-    public final Set<String> externalNames() {
-      return Natives.keys(external());
-    }
-
-    public final native JsArrayString branches() /*-{ return this.branches; }-*/;
-
-    public final native JsArrayString tags() /*-{ return this.tags; }-*/;
-
-    public final native JsArrayString external(String n) /*-{ return this.external[n]; }-*/;
-
-    private native NativeMap<JsArrayString> external() /*-{ return this.external; }-*/;
-
-    protected IncludedInInfo() {}
-  }
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/DownloadInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/DownloadInfo.java
deleted file mode 100644
index a22a1e8..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/DownloadInfo.java
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.info;
-
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.NativeString;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArrayString;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-public class DownloadInfo extends JavaScriptObject {
-  public final List<String> schemes() {
-    return _schemes().sortedKeys();
-  }
-
-  public final List<String> archives() {
-    List<String> archives = new ArrayList<>();
-    archives.addAll(Natives.asList(_archives()));
-    return archives;
-  }
-
-  public final native DownloadSchemeInfo scheme(String n) /*-{ return this.schemes[n]; }-*/;
-
-  private native NativeMap<DownloadSchemeInfo> _schemes() /*-{ return this.schemes; }-*/;
-
-  private native JsArrayString _archives() /*-{ return this.archives; }-*/;
-
-  protected DownloadInfo() {}
-
-  public static class DownloadSchemeInfo extends JavaScriptObject {
-    public final List<String> commandNames() {
-      return _commands().sortedKeys();
-    }
-
-    public final Set<DownloadCommandInfo> commands(String project) {
-      Set<DownloadCommandInfo> commands = new HashSet<>();
-      for (String commandName : commandNames()) {
-        commands.add(new DownloadCommandInfo(commandName, command(commandName, project)));
-      }
-      return commands;
-    }
-
-    public final String command(String commandName, String project) {
-      return command(commandName).replaceAll("\\$\\{project\\}", project);
-    }
-
-    private static String projectBaseName(String project) {
-      return project.substring(project.lastIndexOf('/') + 1);
-    }
-
-    public final List<String> cloneCommandNames() {
-      return _cloneCommands().sortedKeys();
-    }
-
-    public final List<DownloadCommandInfo> cloneCommands(String project) {
-      List<String> commandNames = cloneCommandNames();
-      List<DownloadCommandInfo> commands = new ArrayList<>(commandNames.size());
-      for (String commandName : commandNames) {
-        commands.add(new DownloadCommandInfo(commandName, cloneCommand(commandName, project)));
-      }
-      return commands;
-    }
-
-    public final String cloneCommand(String commandName, String project) {
-      return cloneCommand(commandName)
-          .replaceAll("\\$\\{project\\}", project)
-          .replaceAll("\\$\\{project-base-name\\}", projectBaseName(project));
-    }
-
-    public final String getUrl(String project) {
-      return url().replaceAll("\\$\\{project\\}", project);
-    }
-
-    public final native String name() /*-{ return this.name; }-*/;
-
-    public final native String url() /*-{ return this.url; }-*/;
-
-    public final native boolean isAuthRequired() /*-{ return this.is_auth_required || false; }-*/;
-
-    public final native boolean isAuthSupported() /*-{ return this.is_auth_supported || false; }-*/;
-
-    public final native String command(String n) /*-{ return this.commands[n]; }-*/;
-
-    public final native String cloneCommand(String n) /*-{ return this.clone_commands[n]; }-*/;
-
-    private native NativeMap<NativeString> _commands() /*-{ return this.commands; }-*/;
-
-    private native NativeMap<NativeString> _cloneCommands() /*-{ return this.clone_commands; }-*/;
-
-    protected DownloadSchemeInfo() {}
-  }
-
-  public static class DownloadCommandInfo {
-    private final String name;
-    private final String command;
-
-    DownloadCommandInfo(String name, String command) {
-      this.name = name;
-      this.command = command;
-    }
-
-    public String name() {
-      return name;
-    }
-
-    public String command() {
-      return command;
-    }
-  }
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/FileInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/FileInfo.java
deleted file mode 100644
index fc3dbf1..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/FileInfo.java
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.info;
-
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.common.data.FilenameComparator;
-import com.google.gerrit.reviewdb.client.Patch;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import java.util.Comparator;
-
-public class FileInfo extends JavaScriptObject {
-  public final native String path() /*-{ return this.path; }-*/;
-
-  public final native String oldPath() /*-{ return this.old_path; }-*/;
-
-  public final native int linesInserted() /*-{ return this.lines_inserted || 0; }-*/;
-
-  public final native int linesDeleted() /*-{ return this.lines_deleted || 0; }-*/;
-
-  public final native boolean binary() /*-{ return this.binary || false; }-*/;
-
-  public final native String status() /*-{ return this.status; }-*/;
-
-  // JSNI methods cannot have 'long' as a parameter type or a return type and
-  // it's suggested to use double in this case:
-  // http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsJSNI.html#important
-  public final long size() {
-    return (long) _size();
-  }
-
-  private native double _size() /*-{ return this.size || 0; }-*/;
-
-  public final long sizeDelta() {
-    return (long) _sizeDelta();
-  }
-
-  private native double _sizeDelta() /*-{ return this.size_delta || 0; }-*/;
-
-  public final native int _row() /*-{ return this._row }-*/;
-
-  public final native void _row(int r) /*-{ this._row = r }-*/;
-
-  public static void sortFileInfoByPath(JsArray<FileInfo> list) {
-    Natives.asList(list).sort(Comparator.comparing(FileInfo::path, FilenameComparator.INSTANCE));
-  }
-
-  public static String getFileName(String path) {
-    String fileName;
-    if (Patch.COMMIT_MSG.equals(path)) {
-      fileName = "Commit Message";
-    } else if (Patch.MERGE_LIST.equals(path)) {
-      fileName = "Merge List";
-    } else {
-      fileName = path;
-    }
-
-    int s = fileName.lastIndexOf('/');
-    return s >= 0 ? fileName.substring(s + 1) : fileName;
-  }
-
-  protected FileInfo() {}
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GeneralPreferences.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GeneralPreferences.java
deleted file mode 100644
index fbdf52c..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GeneralPreferences.java
+++ /dev/null
@@ -1,274 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.info;
-
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.NativeString;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DateFormat;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DefaultBase;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DiffView;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DownloadCommand;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.EmailFormat;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.EmailStrategy;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.ReviewCategoryStrategy;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.TimeFormat;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class GeneralPreferences extends JavaScriptObject {
-  public static GeneralPreferences create() {
-    return createObject().cast();
-  }
-
-  public static GeneralPreferences createDefault() {
-    GeneralPreferencesInfo d = GeneralPreferencesInfo.defaults();
-    GeneralPreferences p = createObject().cast();
-    p.changesPerPage(d.changesPerPage);
-    p.showSiteHeader(d.showSiteHeader);
-    p.useFlashClipboard(d.useFlashClipboard);
-    p.downloadScheme(d.downloadScheme);
-    p.downloadCommand(d.downloadCommand);
-    p.dateFormat(d.getDateFormat());
-    p.timeFormat(d.getTimeFormat());
-    p.highlightAssigneeInChangeTable(d.highlightAssigneeInChangeTable);
-    p.relativeDateInChangeTable(d.relativeDateInChangeTable);
-    p.sizeBarInChangeTable(d.sizeBarInChangeTable);
-    p.legacycidInChangeTable(d.legacycidInChangeTable);
-    p.muteCommonPathPrefixes(d.muteCommonPathPrefixes);
-    p.signedOffBy(d.signedOffBy);
-    p.emailFormat(d.emailFormat);
-    p.reviewCategoryStrategy(d.getReviewCategoryStrategy());
-    p.diffView(d.getDiffView());
-    p.emailStrategy(d.emailStrategy);
-    p.defaultBaseForMerges(d.defaultBaseForMerges);
-    return p;
-  }
-
-  public final int changesPerPage() {
-    int changesPerPage = get("changes_per_page", GeneralPreferencesInfo.DEFAULT_PAGESIZE);
-    return 0 < changesPerPage ? changesPerPage : GeneralPreferencesInfo.DEFAULT_PAGESIZE;
-  }
-
-  private native short get(String n, int d) /*-{ return this.hasOwnProperty(n) ? this[n] : d }-*/;
-
-  public final native boolean showSiteHeader() /*-{ return this.show_site_header || false }-*/;
-
-  public final native boolean useFlashClipboard()
-      /*-{ return this.use_flash_clipboard || false }-*/ ;
-
-  public final native String downloadScheme() /*-{ return this.download_scheme }-*/;
-
-  public final DownloadCommand downloadCommand() {
-    String s = downloadCommandRaw();
-    return s != null ? DownloadCommand.valueOf(s) : null;
-  }
-
-  private native String downloadCommandRaw() /*-{ return this.download_command }-*/;
-
-  public final DateFormat dateFormat() {
-    String s = dateFormatRaw();
-    return s != null ? DateFormat.valueOf(s) : null;
-  }
-
-  private native String dateFormatRaw() /*-{ return this.date_format }-*/;
-
-  public final TimeFormat timeFormat() {
-    String s = timeFormatRaw();
-    return s != null ? TimeFormat.valueOf(s) : null;
-  }
-
-  private native String timeFormatRaw() /*-{ return this.time_format }-*/;
-
-  public final native boolean highlightAssigneeInChangeTable()
-      /*-{ return this.highlight_assignee_in_change_table || false }-*/ ;
-
-  public final native boolean relativeDateInChangeTable()
-      /*-{ return this.relative_date_in_change_table || false }-*/ ;
-
-  public final native boolean sizeBarInChangeTable()
-      /*-{ return this.size_bar_in_change_table || false }-*/ ;
-
-  public final native boolean legacycidInChangeTable()
-      /*-{ return this.legacycid_in_change_table || false }-*/ ;
-
-  public final native boolean muteCommonPathPrefixes()
-      /*-{ return this.mute_common_path_prefixes || false }-*/ ;
-
-  public final native boolean signedOffBy() /*-{ return this.signed_off_by || false }-*/;
-
-  public final ReviewCategoryStrategy reviewCategoryStrategy() {
-    String s = reviewCategeoryStrategyRaw();
-    return s != null ? ReviewCategoryStrategy.valueOf(s) : ReviewCategoryStrategy.NONE;
-  }
-
-  private native String reviewCategeoryStrategyRaw() /*-{ return this.review_category_strategy }-*/;
-
-  public final DiffView diffView() {
-    String s = diffViewRaw();
-    return s != null ? DiffView.valueOf(s) : null;
-  }
-
-  private native String diffViewRaw() /*-{ return this.diff_view }-*/;
-
-  public final EmailStrategy emailStrategy() {
-    String s = emailStrategyRaw();
-    return s != null ? EmailStrategy.valueOf(s) : null;
-  }
-
-  private native String emailStrategyRaw() /*-{ return this.email_strategy }-*/;
-
-  public final EmailFormat emailFormat() {
-    String s = emailFormatRaw();
-    return s != null ? EmailFormat.valueOf(s) : null;
-  }
-
-  private native String emailFormatRaw() /*-{ return this.email_format }-*/;
-
-  public final DefaultBase defaultBaseForMerges() {
-    String s = defaultBaseForMergesRaw();
-    return s != null ? DefaultBase.valueOf(s) : null;
-  }
-
-  private native String defaultBaseForMergesRaw() /*-{ return this.default_base_for_merges }-*/;
-
-  public final native boolean
-      publishCommentsOnPush() /*-{ return this.publish_comments_on_push || false }-*/;
-
-  public final native boolean
-      workInProgressByDefault() /*-{ return this.work_in_progress_by_default || false }-*/;
-
-  public final native JsArray<TopMenuItem> my() /*-{ return this.my; }-*/;
-
-  public final native void changesPerPage(int n) /*-{ this.changes_per_page = n }-*/;
-
-  public final native void showSiteHeader(boolean s) /*-{ this.show_site_header = s }-*/;
-
-  public final native void useFlashClipboard(boolean u) /*-{ this.use_flash_clipboard = u }-*/;
-
-  public final native void downloadScheme(String d) /*-{ this.download_scheme = d }-*/;
-
-  public final void downloadCommand(DownloadCommand d) {
-    downloadCommandRaw(d != null ? d.toString() : null);
-  }
-
-  public final native void downloadCommandRaw(String d) /*-{ this.download_command = d }-*/;
-
-  public final void dateFormat(DateFormat f) {
-    dateFormatRaw(f != null ? f.toString() : null);
-  }
-
-  private native void dateFormatRaw(String f) /*-{ this.date_format = f }-*/;
-
-  public final void timeFormat(TimeFormat f) {
-    timeFormatRaw(f != null ? f.toString() : null);
-  }
-
-  private native void timeFormatRaw(String f) /*-{ this.time_format = f }-*/;
-
-  public final native void highlightAssigneeInChangeTable(boolean d)
-      /*-{ this.highlight_assignee_in_change_table = d }-*/ ;
-
-  public final native void relativeDateInChangeTable(boolean d)
-      /*-{ this.relative_date_in_change_table = d }-*/ ;
-
-  public final native void sizeBarInChangeTable(boolean s)
-      /*-{ this.size_bar_in_change_table = s }-*/ ;
-
-  public final native void legacycidInChangeTable(boolean s)
-      /*-{ this.legacycid_in_change_table = s }-*/ ;
-
-  public final native void muteCommonPathPrefixes(boolean s)
-      /*-{ this.mute_common_path_prefixes = s }-*/ ;
-
-  public final native void signedOffBy(boolean s) /*-{ this.signed_off_by = s }-*/;
-
-  public final void reviewCategoryStrategy(ReviewCategoryStrategy s) {
-    reviewCategoryStrategyRaw(s != null ? s.toString() : null);
-  }
-
-  private native void reviewCategoryStrategyRaw(String s)
-      /*-{ this.review_category_strategy = s }-*/ ;
-
-  public final void diffView(DiffView d) {
-    diffViewRaw(d != null ? d.toString() : null);
-  }
-
-  private native void diffViewRaw(String d) /*-{ this.diff_view = d }-*/;
-
-  public final void emailStrategy(EmailStrategy s) {
-    emailStrategyRaw(s != null ? s.toString() : null);
-  }
-
-  private native void emailStrategyRaw(String s) /*-{ this.email_strategy = s }-*/;
-
-  public final void emailFormat(EmailFormat f) {
-    emailFormatRaw(f != null ? f.toString() : null);
-  }
-
-  private native void emailFormatRaw(String s) /*-{ this.email_format = s }-*/;
-
-  public final void defaultBaseForMerges(DefaultBase b) {
-    defaultBaseForMergesRaw(b != null ? b.toString() : null);
-  }
-
-  private native void defaultBaseForMergesRaw(String b) /*-{ this.default_base_for_merges = b }-*/;
-
-  public final native void publishCommentsOnPush(
-      boolean p) /*-{ this.publish_comments_on_push = p }-*/;
-
-  public final native void workInProgressByDefault(
-      boolean p) /*-{ this.work_in_progress_by_default = p }-*/;
-
-  public final void setMyMenus(List<TopMenuItem> myMenus) {
-    initMy();
-    for (TopMenuItem n : myMenus) {
-      addMy(n);
-    }
-  }
-
-  final native void initMy() /*-{ this.my = []; }-*/;
-
-  final native void addMy(TopMenuItem m) /*-{ this.my.push(m); }-*/;
-
-  public final Map<String, String> urlAliases() {
-    Map<String, String> urlAliases = new HashMap<>();
-    for (String k : Natives.keys(_urlAliases())) {
-      urlAliases.put(k, urlAliasToken(k));
-    }
-    return urlAliases;
-  }
-
-  private native String urlAliasToken(String m) /*-{ return this.url_aliases[m]; }-*/;
-
-  private native NativeMap<NativeString> _urlAliases() /*-{ return this.url_aliases; }-*/;
-
-  public final void setUrlAliases(Map<String, String> urlAliases) {
-    initUrlAliases();
-    for (Map.Entry<String, String> e : urlAliases.entrySet()) {
-      putUrlAlias(e.getKey(), e.getValue());
-    }
-  }
-
-  private native void putUrlAlias(String m, String t) /*-{ this.url_aliases[m] = t; }-*/;
-
-  private native void initUrlAliases() /*-{ this.url_aliases = {}; }-*/;
-
-  protected GeneralPreferences() {}
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GerritInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GerritInfo.java
deleted file mode 100644
index 78ca417..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GerritInfo.java
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.info;
-
-import com.google.gerrit.extensions.client.UiType;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArrayString;
-import java.util.ArrayList;
-import java.util.List;
-
-public class GerritInfo extends JavaScriptObject {
-  public final Project.NameKey allProjectsNameKey() {
-    return new Project.NameKey(allProjects());
-  }
-
-  public final boolean isAllProjects(Project.NameKey p) {
-    return allProjectsNameKey().equals(p);
-  }
-
-  public final Project.NameKey allUsersNameKey() {
-    return new Project.NameKey(allUsers());
-  }
-
-  public final boolean isAllUsers(Project.NameKey p) {
-    return allUsersNameKey().equals(p);
-  }
-
-  public final native String allProjects() /*-{ return this.all_projects; }-*/;
-
-  public final native String allUsers() /*-{ return this.all_users; }-*/;
-
-  public final native boolean docSearch() /*-{ return this.doc_search; }-*/;
-
-  public final native String docUrl() /*-{ return this.doc_url; }-*/;
-
-  public final native boolean editGpgKeys() /*-{ return this.edit_gpg_keys || false; }-*/;
-
-  public final native String reportBugUrl() /*-{ return this.report_bug_url; }-*/;
-
-  public final native String reportBugText() /*-{ return this.report_bug_text; }-*/;
-
-  private native JsArrayString _webUis() /*-{ return this.web_uis; }-*/;
-
-  public final List<UiType> webUis() {
-    JsArrayString webUis = _webUis();
-    List<UiType> result = new ArrayList<>(webUis.length());
-    for (int i = 0; i < webUis.length(); i++) {
-      UiType t = UiType.parse(webUis.get(i));
-      if (t != null) {
-        result.add(t);
-      }
-    }
-    return result;
-  }
-
-  protected GerritInfo() {}
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GpgKeyInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GpgKeyInfo.java
deleted file mode 100644
index fd4fde7..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GpgKeyInfo.java
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.info;
-
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArrayString;
-
-public class GpgKeyInfo extends JavaScriptObject {
-  public enum Status {
-    BAD,
-    OK,
-    TRUSTED;
-  }
-
-  public final native String id() /*-{ return this.id; }-*/;
-
-  public final native String fingerprint() /*-{ return this.fingerprint; }-*/;
-
-  public final native JsArrayString userIds() /*-{ return this.user_ids; }-*/;
-
-  public final native String key() /*-{ return this.key; }-*/;
-
-  private native String statusRaw() /*-{ return this.status; }-*/;
-
-  public final Status status() {
-    String s = statusRaw();
-    if (s == null) {
-      return null;
-    }
-    return Status.valueOf(s);
-  }
-
-  public final native boolean hasProblems() /*-{ return this.hasOwnProperty('problems'); }-*/;
-
-  public final native JsArrayString problems() /*-{ return this.problems; }-*/;
-
-  protected GpgKeyInfo() {}
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GroupBaseInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GroupBaseInfo.java
deleted file mode 100644
index 94905c0..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GroupBaseInfo.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.info;
-
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.http.client.URL;
-
-public class GroupBaseInfo extends JavaScriptObject {
-  public final AccountGroup.UUID getGroupUUID() {
-    return new AccountGroup.UUID(URL.decodeQueryString(id()));
-  }
-
-  public final native String id() /*-{ return this.id; }-*/;
-
-  public final native String name() /*-{ return this.name; }-*/;
-
-  protected GroupBaseInfo() {}
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GroupInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GroupInfo.java
deleted file mode 100644
index 9bf3411a..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GroupInfo.java
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.info;
-
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.http.client.URL;
-
-public class GroupInfo extends GroupBaseInfo {
-  public final AccountGroup.Id getGroupId() {
-    return new AccountGroup.Id(group_id());
-  }
-
-  public final native GroupOptionsInfo options() /*-{ return this.options; }-*/;
-
-  public final native String description() /*-{ return this.description; }-*/;
-
-  public final native String url() /*-{ return this.url; }-*/;
-
-  public final native String owner() /*-{ return this.owner; }-*/;
-
-  public final native void owner(String o) /*-{ if(o)this.owner=o; }-*/;
-
-  public final native JsArray<AccountInfo> members() /*-{ return this.members; }-*/;
-
-  public final native JsArray<GroupInfo> includes() /*-{ return this.includes; }-*/;
-
-  private native int group_id() /*-{ return this.group_id; }-*/;
-
-  private native String owner_id() /*-{ return this.owner_id; }-*/;
-
-  private native void owner_id(String o) /*-{ if(o)this.owner_id=o; }-*/;
-
-  public final AccountGroup.UUID getOwnerUUID() {
-    String owner = owner_id();
-    if (owner != null) {
-      return new AccountGroup.UUID(URL.decodeQueryString(owner));
-    }
-    return null;
-  }
-
-  public final void setOwnerUUID(AccountGroup.UUID uuid) {
-    owner_id(URL.encodeQueryString(uuid.get()));
-  }
-
-  protected GroupInfo() {}
-
-  public static class GroupOptionsInfo extends JavaScriptObject {
-    public final native boolean
-        isVisibleToAll() /*-{ return this['visible_to_all'] ? true : false; }-*/;
-
-    protected GroupOptionsInfo() {}
-  }
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/OAuthTokenInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/OAuthTokenInfo.java
deleted file mode 100644
index d96adaa..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/OAuthTokenInfo.java
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.info;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class OAuthTokenInfo extends JavaScriptObject {
-
-  protected OAuthTokenInfo() {}
-
-  public final native String username() /*-{ return this.username; }-*/;
-
-  public final native String resourceHost() /*-{ return this.resource_host; }-*/;
-
-  public final native String accessToken() /*-{ return this.access_token; }-*/;
-
-  public final native String providerId() /*-{ return this.provider_id; }-*/;
-
-  public final native String expiresAt() /*-{ return this.expires_at; }-*/;
-
-  public final native String type() /*-{ return this.type; }-*/;
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/PushCertificateInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/PushCertificateInfo.java
deleted file mode 100644
index fb5d932..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/PushCertificateInfo.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.info;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class PushCertificateInfo extends JavaScriptObject {
-  public final native String certificate() /*-{ return this.certificate; }-*/;
-
-  public final native GpgKeyInfo key() /*-{ return this.key; }-*/;
-
-  protected PushCertificateInfo() {}
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/ServerInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/ServerInfo.java
deleted file mode 100644
index d3274e6..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/ServerInfo.java
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.info;
-
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.NativeString;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArrayString;
-import java.util.HashMap;
-import java.util.Map;
-
-public class ServerInfo extends JavaScriptObject {
-  public final native AuthInfo auth() /*-{ return this.auth; }-*/;
-
-  public final native ChangeConfigInfo change() /*-{ return this.change; }-*/;
-
-  public final native DownloadInfo download() /*-{ return this.download; }-*/;
-
-  public final native GerritInfo gerrit() /*-{ return this.gerrit; }-*/;
-
-  public final native PluginConfigInfo plugin() /*-{ return this.plugin; }-*/;
-
-  public final native SshdInfo sshd() /*-{ return this.sshd; }-*/;
-
-  public final native SuggestInfo suggest() /*-{ return this.suggest; }-*/;
-
-  public final native UserConfigInfo user() /*-{ return this.user; }-*/;
-
-  public final native ReceiveInfo receive() /*-{ return this.receive; }-*/;
-
-  public final Map<String, String> urlAliases() {
-    Map<String, String> urlAliases = new HashMap<>();
-    for (String k : Natives.keys(_urlAliases())) {
-      urlAliases.put(k, urlAliasToken(k));
-    }
-    return urlAliases;
-  }
-
-  public final native String urlAliasToken(String n) /*-{ return this.url_aliases[n]; }-*/;
-
-  private native NativeMap<NativeString> _urlAliases() /*-{ return this.url_aliases; }-*/;
-
-  public final boolean hasSshd() {
-    return sshd() != null;
-  }
-
-  protected ServerInfo() {}
-
-  public static class ChangeConfigInfo extends JavaScriptObject {
-    public final native boolean allowBlame() /*-{ return this.allow_blame || false; }-*/;
-
-    public final native int largeChange() /*-{ return this.large_change || 0; }-*/;
-
-    public final native String replyLabel() /*-{ return this.reply_label; }-*/;
-
-    public final native String replyTooltip() /*-{ return this.reply_tooltip; }-*/;
-
-    public final native boolean
-        showAssigneeInChangesTable() /*-{ return this.show_assignee_in_changes_table || false; }-*/;
-
-    public final native int updateDelay() /*-{ return this.update_delay || 0; }-*/;
-
-    public final native boolean isSubmitWholeTopicEnabled() /*-{
-        return this.submit_whole_topic; }-*/;
-
-    protected ChangeConfigInfo() {}
-  }
-
-  public static class PluginConfigInfo extends JavaScriptObject {
-    public final native boolean hasAvatars() /*-{ return this.has_avatars || false; }-*/;
-
-    public final native JsArrayString jsResourcePaths() /*-{
-        return this.js_resource_paths || []; }-*/;
-
-    protected PluginConfigInfo() {}
-  }
-
-  public static class SshdInfo extends JavaScriptObject {
-    protected SshdInfo() {}
-  }
-
-  public static class SuggestInfo extends JavaScriptObject {
-    public final native int from() /*-{ return this.from || 0; }-*/;
-
-    protected SuggestInfo() {}
-  }
-
-  public static class UserConfigInfo extends JavaScriptObject {
-    public final native String anonymousCowardName() /*-{ return this.anonymous_coward_name; }-*/;
-
-    protected UserConfigInfo() {}
-  }
-
-  public static class ReceiveInfo extends JavaScriptObject {
-    public final native boolean enableSignedPush()
-        /*-{ return this.enable_signed_push || false; }-*/ ;
-
-    protected ReceiveInfo() {}
-  }
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/TopMenu.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/TopMenu.java
deleted file mode 100644
index 7e25af2..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/TopMenu.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.info;
-
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-
-public class TopMenu extends JavaScriptObject {
-
-  protected TopMenu() {}
-
-  public final native String getName() /*-{ return this.name; }-*/;
-
-  public final native JsArray<TopMenuItem> getItems() /*-{ return this.items; }-*/;
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/TopMenuItem.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/TopMenuItem.java
deleted file mode 100644
index 3a286a2..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/TopMenuItem.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.info;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class TopMenuItem extends JavaScriptObject {
-  public static TopMenuItem create(String name, String url) {
-    TopMenuItem i = createObject().cast();
-    i.name(name);
-    i.url(url);
-    return i;
-  }
-
-  public final native String getName() /*-{ return this.name; }-*/;
-
-  public final native String getUrl() /*-{ return this.url; }-*/;
-
-  public final native String getTarget() /*-{ return this.target; }-*/;
-
-  public final native String getId() /*-{ return this.id; }-*/;
-
-  public final native void name(String n) /*-{ this.name = n }-*/;
-
-  public final native void url(String u) /*-{ this.url = u }-*/;
-
-  protected TopMenuItem() {}
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/TopMenuList.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/TopMenuList.java
deleted file mode 100644
index d7df1f7..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/TopMenuList.java
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.info;
-
-import com.google.gwt.core.client.JsArray;
-
-public class TopMenuList extends JsArray<TopMenu> {
-
-  protected TopMenuList() {}
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/WebLinkInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/WebLinkInfo.java
deleted file mode 100644
index bcf3dde..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/WebLinkInfo.java
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.info;
-
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Image;
-
-public class WebLinkInfo extends JavaScriptObject {
-
-  public final native String name() /*-{ return this.name; }-*/;
-
-  public final native String imageUrl() /*-{ return this.image_url; }-*/;
-
-  public final native String url() /*-{ return this.url; }-*/;
-
-  public final native String target() /*-{ return this.target; }-*/;
-
-  protected WebLinkInfo() {}
-
-  public final Anchor toAnchor() {
-    Anchor a = new Anchor();
-    a.setHref(url());
-    if (target() != null && !target().isEmpty()) {
-      a.setTarget(target());
-    }
-    if (imageUrl() != null && !imageUrl().isEmpty()) {
-      Image img = new Image();
-      img.setAltText(name());
-      img.setUrl(imageUrl());
-      img.setTitle(name());
-      a.getElement().appendChild(img.getElement());
-    } else {
-      a.setText("(" + name() + ")");
-    }
-    return a;
-  }
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/rpc/NativeMap.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/rpc/NativeMap.java
deleted file mode 100644
index 41306ff..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/rpc/NativeMap.java
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.rpc;
-
-import static java.util.stream.Collectors.toCollection;
-
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-/** A map of native JSON objects, keyed by a string. */
-public class NativeMap<T extends JavaScriptObject> extends JavaScriptObject {
-  public static <T extends JavaScriptObject> NativeMap<T> create() {
-    return createObject().cast();
-  }
-
-  /**
-   * Loop through the result map's entries and copy the key strings into the "name" property of the
-   * corresponding child object. This only runs on the top level map of the result, and requires the
-   * children to be JSON objects and not a JSON primitive (e.g. boolean or string).
-   */
-  public static <T extends JavaScriptObject, M extends NativeMap<T>>
-      AsyncCallback<M> copyKeysIntoChildren(AsyncCallback<M> callback) {
-    return copyKeysIntoChildren("name", callback);
-  }
-
-  /** Loop through the result map and set asProperty on the children. */
-  public static <T extends JavaScriptObject, M extends NativeMap<T>>
-      AsyncCallback<M> copyKeysIntoChildren(String asProperty, AsyncCallback<M> callback) {
-    return new TransformCallback<M, M>(callback) {
-      @Override
-      protected M transform(M result) {
-        result.copyKeysIntoChildren(asProperty);
-        return result;
-      }
-    };
-  }
-
-  protected NativeMap() {}
-
-  public final Set<String> keySet() {
-    return Natives.keys(this);
-  }
-
-  public final List<String> sortedKeys() {
-    return keySet().stream().sorted().collect(toCollection(ArrayList::new));
-  }
-
-  public final native JsArray<T> values() /*-{
-    var s = this;
-    var v = [];
-    var i = 0;
-    for (var k in s) {
-      if (s.hasOwnProperty(k)) {
-        v[i++] = s[k];
-      }
-    }
-    return v;
-  }-*/;
-
-  public final int size() {
-    return keySet().size();
-  }
-
-  public final boolean isEmpty() {
-    return size() == 0;
-  }
-
-  public final boolean containsKey(String n) {
-    return get(n) != null;
-  }
-
-  public final native T get(String n) /*-{ return this[n]; }-*/;
-
-  public final native void put(String n, T v) /*-{ this[n] = v; }-*/;
-
-  public final native void copyKeysIntoChildren(String p) /*-{
-    var s = this;
-    for (var k in s) {
-      if (s.hasOwnProperty(k)) {
-        var c = s[k];
-        c[p] = k;
-      }
-    }
-  }-*/;
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/rpc/NativeString.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/rpc/NativeString.java
deleted file mode 100644
index e0bca0e..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/rpc/NativeString.java
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.rpc;
-
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-/** Wraps a String that was returned from a JSON API. */
-public final class NativeString extends JavaScriptObject {
-  public static final JavaScriptObject TYPE = init();
-
-  // Used from core and plugins
-  private static native JavaScriptObject init() /*-{
-    if ($wnd.Gerrit === undefined || $wnd.Gerrit.JsonString === undefined) {
-      return function(s){this.s=s};
-    } else {
-      return $wnd.Gerrit.JsonString;
-    }
-  }-*/;
-
-  static NativeString wrap(String s) {
-    return wrap0(TYPE, s);
-  }
-
-  private static native NativeString wrap0(JavaScriptObject T, String s) /*-{ return new T(s) }-*/;
-
-  public native String asString() /*-{ return this.s; }-*/;
-
-  public static AsyncCallback<NativeString> unwrap(AsyncCallback<String> cb) {
-    return new AsyncCallback<NativeString>() {
-      @Override
-      public void onSuccess(NativeString result) {
-        cb.onSuccess(result != null ? result.asString() : null);
-      }
-
-      @Override
-      public void onFailure(Throwable caught) {
-        cb.onFailure(caught);
-      }
-    };
-  }
-
-  public static boolean is(JavaScriptObject o) {
-    return is(TYPE, o);
-  }
-
-  private static native boolean is(JavaScriptObject T, JavaScriptObject o)
-      /*-{ return o instanceof T }-*/ ;
-
-  protected NativeString() {}
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/rpc/Natives.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/rpc/Natives.java
deleted file mode 100644
index 1421386..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/rpc/Natives.java
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.rpc;
-
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.json.client.JSONObject;
-import java.util.AbstractList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-
-public class Natives {
-  /**
-   * Get the names of defined properties on the object. The returned set iterates in the native
-   * iteration order, which may match the source order.
-   */
-  public static Set<String> keys(JavaScriptObject obj) {
-    if (obj != null) {
-      return new JSONObject(obj).keySet();
-    }
-    return Collections.emptySet();
-  }
-
-  public static List<String> asList(JsArrayString arr) {
-    if (arr == null) {
-      return null;
-    }
-    return new AbstractList<String>() {
-      @Override
-      public String set(int index, String element) {
-        String old = arr.get(index);
-        arr.set(index, element);
-        return old;
-      }
-
-      @Override
-      public String get(int index) {
-        return arr.get(index);
-      }
-
-      @Override
-      public int size() {
-        return arr.length();
-      }
-    };
-  }
-
-  public static <T extends JavaScriptObject> List<T> asList(JsArray<T> arr) {
-    if (arr == null) {
-      return null;
-    }
-    return new AbstractList<T>() {
-      @Override
-      public T set(int index, T element) {
-        T old = arr.get(index);
-        arr.set(index, element);
-        return old;
-      }
-
-      @Override
-      public T get(int index) {
-        return arr.get(index);
-      }
-
-      @Override
-      public int size() {
-        return arr.length();
-      }
-    };
-  }
-
-  public static <T extends JavaScriptObject> JsArray<T> arrayOf(T element) {
-    JsArray<T> arr = JavaScriptObject.createArray().cast();
-    arr.push(element);
-    return arr;
-  }
-
-  public static JsArrayString arrayOf(Iterable<String> elements) {
-    JsArrayString arr = JavaScriptObject.createArray().cast();
-    for (String elem : elements) {
-      arr.push(elem);
-    }
-    return arr;
-  }
-
-  public static JsArrayString arrayOf(String element) {
-    JsArrayString arr = JavaScriptObject.createArray().cast();
-    arr.push(element);
-    return arr;
-  }
-
-  private Natives() {}
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/rpc/TransformCallback.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/rpc/TransformCallback.java
deleted file mode 100644
index 00e6bb1..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/rpc/TransformCallback.java
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.rpc;
-
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-/** Transforms a value and passes it on to another callback. */
-public abstract class TransformCallback<I, O> implements AsyncCallback<I> {
-  private final AsyncCallback<O> callback;
-
-  protected TransformCallback(AsyncCallback<O> callback) {
-    this.callback = callback;
-  }
-
-  @Override
-  public void onSuccess(I result) {
-    callback.onSuccess(transform(result));
-  }
-
-  @Override
-  public void onFailure(Throwable caught) {
-    callback.onFailure(caught);
-  }
-
-  protected abstract O transform(I result);
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/ui/HighlightSuggestion.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/ui/HighlightSuggestion.java
deleted file mode 100644
index 513f570..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/ui/HighlightSuggestion.java
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
-import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
-
-/** A {@code Suggestion} with highlights. */
-public class HighlightSuggestion implements Suggestion {
-
-  private final String keyword;
-  private final String value;
-
-  public HighlightSuggestion(String keyword, String value) {
-    this.keyword = keyword;
-    this.value = value;
-  }
-
-  @Override
-  public String getDisplayString() {
-    int start = 0;
-    int keyLen = keyword.length();
-    SafeHtmlBuilder builder = new SafeHtmlBuilder();
-    for (; ; ) {
-      int index = value.indexOf(keyword, start);
-      if (index == -1) {
-        builder.appendEscaped(value.substring(start));
-        break;
-      }
-      builder.appendEscaped(value.substring(start, index));
-      builder.appendHtmlConstant("<strong>");
-      start = index + keyLen;
-      builder.appendEscaped(value.substring(index, start));
-      builder.appendHtmlConstant("</strong>");
-    }
-    return builder.toSafeHtml().asString();
-  }
-
-  @Override
-  public String getReplacementString() {
-    return value;
-  }
-}
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/ui/RemoteSuggestOracle.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/ui/RemoteSuggestOracle.java
deleted file mode 100644
index d66d6a6..0000000
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/ui/RemoteSuggestOracle.java
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.ui.SuggestOracle;
-
-/**
- * Delegates to a slow SuggestOracle, such as a remote server API.
- *
- * <p>A response is only supplied to the UI if no requests were made after the oracle begin that
- * request.
- *
- * <p>When a request is made while the delegate is still processing a prior request all intermediate
- * requests are discarded and the most recent request is queued. The pending request's response is
- * discarded and the most recent request is started.
- */
-public class RemoteSuggestOracle extends SuggestOracle {
-  private final SuggestOracle oracle;
-  private Query query;
-  private String last;
-  private Timer requestRetentionTimer;
-  private boolean cancelOutstandingRequest;
-
-  private boolean serveSuggestions;
-
-  public RemoteSuggestOracle(SuggestOracle src) {
-    oracle = src;
-  }
-
-  public String getLast() {
-    return last;
-  }
-
-  @Override
-  public void requestSuggestions(Request req, Callback cb) {
-    if (!serveSuggestions) {
-      return;
-    }
-
-    // Use a timer for key stroke retention, such that we don't query the
-    // backend for each and every keystroke we receive.
-    if (requestRetentionTimer != null) {
-      requestRetentionTimer.cancel();
-    }
-    requestRetentionTimer =
-        new Timer() {
-          @Override
-          public void run() {
-            Query q = new Query(req, cb);
-            if (query == null) {
-              query = q;
-              q.start();
-            } else {
-              query = q;
-            }
-          }
-        };
-    requestRetentionTimer.schedule(200);
-  }
-
-  @Override
-  public void requestDefaultSuggestions(Request req, Callback cb) {
-    requestSuggestions(req, cb);
-  }
-
-  @Override
-  public boolean isDisplayStringHTML() {
-    return oracle.isDisplayStringHTML();
-  }
-
-  public void cancelOutstandingRequest() {
-    if (requestRetentionTimer != null) {
-      requestRetentionTimer.cancel();
-    }
-    if (query != null) {
-      cancelOutstandingRequest = true;
-    }
-  }
-
-  public void setServeSuggestions(boolean serveSuggestions) {
-    this.serveSuggestions = serveSuggestions;
-  }
-
-  private class Query implements Callback {
-    final Request request;
-    final Callback callback;
-
-    Query(Request req, Callback cb) {
-      request = req;
-      callback = cb;
-    }
-
-    void start() {
-      oracle.requestSuggestions(request, this);
-    }
-
-    @Override
-    public void onSuggestionsReady(Request req, Response res) {
-      if (cancelOutstandingRequest || !serveSuggestions) {
-        // If cancelOutstandingRequest() was called, we ignore this response
-        cancelOutstandingRequest = false;
-        query = null;
-      } else if (query == this) {
-        // No new request was started while this query was running.
-        // Propose this request's response as the suggestions.
-        query = null;
-        last = request.getQuery();
-        callback.onSuggestionsReady(req, res);
-      } else {
-        // Another query came in while this one was running. Skip
-        // this response and start the most recent query.
-        query.start();
-      }
-    }
-  }
-}
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/arrow_undo.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/arrow_undo.png
deleted file mode 100644
index 6972c5e..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/arrow_undo.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/cog.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/cog.png
deleted file mode 100644
index 67de2c6..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/cog.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/comment_draft.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/comment_draft.png
deleted file mode 100644
index 3408ddf..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/comment_draft.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/cross.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/cross.png
deleted file mode 100644
index 1514d51..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/cross.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/diffy26.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/diffy26.png
deleted file mode 100644
index 88b59d8..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/diffy26.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/disk.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/disk.png
deleted file mode 100644
index 99d532e..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/disk.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/exclamation.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/exclamation.png
deleted file mode 100644
index c37bd06..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/exclamation.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/find.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/find.png
deleted file mode 100644
index 1547479..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/find.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/goDown.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/goDown.png
deleted file mode 100644
index 5d87e45..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/goDown.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/goNext.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/goNext.png
deleted file mode 100644
index 872c197..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/goNext.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/goPrev.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/goPrev.png
deleted file mode 100644
index d68f29b..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/goPrev.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/goUp.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/goUp.png
deleted file mode 100644
index f75bed4..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/goUp.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/help.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/help.png
deleted file mode 100644
index 5c87017..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/help.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/lightbulb.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/lightbulb.png
deleted file mode 100644
index d22fde8..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/lightbulb.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/listAdd.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/listAdd.png
deleted file mode 100644
index 1aa7f09..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/listAdd.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/lock.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/lock.png
deleted file mode 100644
index 2ebc4f6..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/lock.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/merge.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/merge.png
deleted file mode 100644
index 9c892db..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/merge.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/note_add.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/note_add.png
deleted file mode 100644
index abdad91..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/note_add.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/page_edit.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/page_edit.png
deleted file mode 100644
index 046811e..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/page_edit.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/page_white_put.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/page_white_put.png
deleted file mode 100644
index 884ffd6..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/page_white_put.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/resultset_down_gray.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/resultset_down_gray.png
deleted file mode 100644
index 7bdd8ea..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/resultset_down_gray.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/resultset_next_gray.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/resultset_next_gray.png
deleted file mode 100644
index 3049ef4..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/resultset_next_gray.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/resultset_up_gray.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/resultset_up_gray.png
deleted file mode 100644
index 966a25e..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/resultset_up_gray.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/sideBySideDiff.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/sideBySideDiff.png
deleted file mode 100755
index ee70080..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/sideBySideDiff.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/star-open.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/star-open.png
deleted file mode 100644
index edd577c..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/star-open.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/star.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/star.png
deleted file mode 100644
index b88c857..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/star.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/tag_blue.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/tag_blue.png
deleted file mode 100644
index 9757fc6..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/tag_blue.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/tag_blue_add.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/tag_blue_add.png
deleted file mode 100644
index f135248..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/tag_blue_add.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/tick.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/tick.png
deleted file mode 100644
index a9925a0..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/tick.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/unifiedDiff.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/unifiedDiff.png
deleted file mode 100755
index ec5f97a..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/unifiedDiff.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/user_add.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/user_add.png
deleted file mode 100644
index deae99b..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/user_add.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/user_edit.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/user_edit.png
deleted file mode 100644
index c1974cd..0000000
--- a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/user_edit.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui-common/src/test/java/com/google/gerrit/client/RelativeDateFormatterTest.java b/gerrit-gwtui-common/src/test/java/com/google/gerrit/client/RelativeDateFormatterTest.java
deleted file mode 100644
index 6915ba7..0000000
--- a/gerrit-gwtui-common/src/test/java/com/google/gerrit/client/RelativeDateFormatterTest.java
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import static com.google.gerrit.client.RelativeDateFormatter.DAY_IN_MILLIS;
-import static com.google.gerrit.client.RelativeDateFormatter.HOUR_IN_MILLIS;
-import static com.google.gerrit.client.RelativeDateFormatter.MINUTE_IN_MILLIS;
-import static com.google.gerrit.client.RelativeDateFormatter.SECOND_IN_MILLIS;
-import static com.google.gerrit.client.RelativeDateFormatter.YEAR_IN_MILLIS;
-import static org.junit.Assert.assertEquals;
-
-import java.util.Date;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-public class RelativeDateFormatterTest {
-
-  @BeforeClass
-  public static void setConstants() {
-    Constants c = new Constants();
-    RelativeDateFormatter.setConstants(c, c);
-  }
-
-  @AfterClass
-  public static void unsetConstants() {
-    RelativeDateFormatter.setConstants(null, null);
-  }
-
-  private static void assertFormat(long ageFromNow, long timeUnit, String expectedFormat) {
-    Date d = new Date(System.currentTimeMillis() - ageFromNow * timeUnit);
-    String s = RelativeDateFormatter.format(d);
-    assertEquals(expectedFormat, s);
-  }
-
-  @Test
-  public void future() {
-    assertFormat(-100, YEAR_IN_MILLIS, "in the future");
-    assertFormat(-1, SECOND_IN_MILLIS, "in the future");
-  }
-
-  @Test
-  public void formatSeconds() {
-    assertFormat(1, SECOND_IN_MILLIS, "1 second ago");
-    assertFormat(89, SECOND_IN_MILLIS, "89 seconds ago");
-  }
-
-  @Test
-  public void formatMinutes() {
-    assertFormat(90, SECOND_IN_MILLIS, "2 minutes ago");
-    assertFormat(3, MINUTE_IN_MILLIS, "3 minutes ago");
-    assertFormat(60, MINUTE_IN_MILLIS, "60 minutes ago");
-    assertFormat(89, MINUTE_IN_MILLIS, "89 minutes ago");
-  }
-
-  @Test
-  public void formatHours() {
-    assertFormat(90, MINUTE_IN_MILLIS, "2 hours ago");
-    assertFormat(149, MINUTE_IN_MILLIS, "2 hours ago");
-    assertFormat(35, HOUR_IN_MILLIS, "35 hours ago");
-  }
-
-  @Test
-  public void formatDays() {
-    assertFormat(36, HOUR_IN_MILLIS, "2 days ago");
-    assertFormat(13, DAY_IN_MILLIS, "13 days ago");
-  }
-
-  @Test
-  public void formatWeeks() {
-    assertFormat(14, DAY_IN_MILLIS, "2 weeks ago");
-    assertFormat(69, DAY_IN_MILLIS, "10 weeks ago");
-  }
-
-  @Test
-  public void formatMonths() {
-    assertFormat(70, DAY_IN_MILLIS, "2 months ago");
-    assertFormat(75, DAY_IN_MILLIS, "3 months ago");
-    assertFormat(364, DAY_IN_MILLIS, "12 months ago");
-  }
-
-  @Test
-  public void formatYearsMonths() {
-    assertFormat(366, DAY_IN_MILLIS, "1 year ago");
-    assertFormat(380, DAY_IN_MILLIS, "1 year, 1 month ago");
-    assertFormat(410, DAY_IN_MILLIS, "1 year, 2 months ago");
-    assertFormat(2, YEAR_IN_MILLIS, "2 years ago");
-    assertFormat(1824, DAY_IN_MILLIS, "5 years ago");
-    assertFormat(2 * 365 - 10, DAY_IN_MILLIS, "2 years ago");
-  }
-
-  @Test
-  public void formatYears() {
-    assertFormat(5, YEAR_IN_MILLIS, "5 years ago");
-    assertFormat(60, YEAR_IN_MILLIS, "60 years ago");
-  }
-
-  private static class Constants implements CommonConstants, CommonMessages {
-    @Override
-    public String inTheFuture() {
-      return "in the future";
-    }
-
-    @Override
-    public String month() {
-      return "month";
-    }
-
-    @Override
-    public String months() {
-      return "months";
-    }
-
-    @Override
-    public String year() {
-      return "year";
-    }
-
-    @Override
-    public String years() {
-      return "years";
-    }
-
-    @Override
-    public String oneSecondAgo() {
-      return "1 second ago";
-    }
-
-    @Override
-    public String oneMinuteAgo() {
-      return "1 minute ago";
-    }
-
-    @Override
-    public String oneHourAgo() {
-      return "1 hour ago";
-    }
-
-    @Override
-    public String oneDayAgo() {
-      return "1 day ago";
-    }
-
-    @Override
-    public String oneWeekAgo() {
-      return "1 week ago";
-    }
-
-    @Override
-    public String oneMonthAgo() {
-      return "1 month ago";
-    }
-
-    @Override
-    public String oneYearAgo() {
-      return "1 year ago";
-    }
-
-    @Override
-    public String secondsAgo(long seconds) {
-      return seconds + " seconds ago";
-    }
-
-    @Override
-    public String minutesAgo(long minutes) {
-      return minutes + " minutes ago";
-    }
-
-    @Override
-    public String hoursAgo(long hours) {
-      return hours + " hours ago";
-    }
-
-    @Override
-    public String daysAgo(long days) {
-      return days + " days ago";
-    }
-
-    @Override
-    public String weeksAgo(long weeks) {
-      return weeks + " weeks ago";
-    }
-
-    @Override
-    public String monthsAgo(long months) {
-      return months + " months ago";
-    }
-
-    @Override
-    public String yearsAgo(long years) {
-      return years + " years ago";
-    }
-
-    @Override
-    public String years0MonthsAgo(long years, String yearLabel) {
-      return years + " " + yearLabel + " ago";
-    }
-
-    @Override
-    public String yearsMonthsAgo(long years, String yearLabel, long months, String monthLabel) {
-      return years + " " + yearLabel + ", " + months + " " + monthLabel + " ago";
-    }
-  }
-}
diff --git a/gerrit-gwtui-common/src/test/java/com/google/gerrit/client/ui/HighlightSuggestionTest.java b/gerrit-gwtui-common/src/test/java/com/google/gerrit/client/ui/HighlightSuggestionTest.java
deleted file mode 100644
index 9bf2d95..0000000
--- a/gerrit-gwtui-common/src/test/java/com/google/gerrit/client/ui/HighlightSuggestionTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import static org.junit.Assert.assertEquals;
-
-import org.junit.Test;
-
-public class HighlightSuggestionTest {
-
-  @Test
-  public void singleHighlight() throws Exception {
-    String keyword = "key";
-    String value = "somethingkeysomething";
-    HighlightSuggestion suggestion = new HighlightSuggestion(keyword, value);
-    assertEquals("something<strong>key</strong>something", suggestion.getDisplayString());
-    assertEquals(value, suggestion.getReplacementString());
-  }
-
-  @Test
-  public void noHighlight() throws Exception {
-    String keyword = "key";
-    String value = "something";
-    HighlightSuggestion suggestion = new HighlightSuggestion(keyword, value);
-    assertEquals(value, suggestion.getDisplayString());
-    assertEquals(value, suggestion.getReplacementString());
-  }
-
-  @Test
-  public void doubleHighlight() throws Exception {
-    String keyword = "key";
-    String value = "somethingkeysomethingkeysomething";
-    HighlightSuggestion suggestion = new HighlightSuggestion(keyword, value);
-    assertEquals(
-        "something<strong>key</strong>something<strong>key</strong>something",
-        suggestion.getDisplayString());
-    assertEquals(value, suggestion.getReplacementString());
-  }
-}
diff --git a/gerrit-gwtui/BUILD b/gerrit-gwtui/BUILD
deleted file mode 100644
index 1a772f1..0000000
--- a/gerrit-gwtui/BUILD
+++ /dev/null
@@ -1,41 +0,0 @@
-load(
-    "//tools/bzl:gwt.bzl",
-    "gen_ui_module",
-    "gwt_genrule",
-    "gwt_user_agent_permutations",
-)
-load("//tools/bzl:license.bzl", "license_test")
-load("//tools/bzl:junit.bzl", "junit_tests")
-
-gwt_genrule()
-
-gwt_genrule("_r")
-
-gen_ui_module(name = "ui_module")
-
-gen_ui_module(
-    name = "ui_module",
-    suffix = "_r",
-)
-
-gwt_user_agent_permutations()
-
-license_test(
-    name = "ui_module_license_test",
-    target = ":ui_module",
-)
-
-junit_tests(
-    name = "ui_tests",
-    srcs = glob(["src/test/java/**/*.java"]),
-    visibility = ["//visibility:public"],
-    deps = [
-        ":ui_module",
-        "//java/com/google/gerrit/common:client",
-        "//java/com/google/gerrit/extensions:client",
-        "//lib:junit",
-        "//lib/gwt:dev",
-        "//lib/gwt:user",
-        "//lib/truth",
-    ],
-)
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/GerritGwtUI.gwt.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/GerritGwtUI.gwt.xml
deleted file mode 100644
index 9ac919b..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/GerritGwtUI.gwt.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<!--
- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<module rename-to="gerrit_ui">
-  <inherits name='com.google.gwt.editor.Editor'/>
-  <inherits name='com.google.gwt.user.User'/>
-  <inherits name='com.google.gwt.resources.Resources'/>
-  <inherits name='com.google.gwt.user.theme.chrome.Chrome'/>
-  <inherits name='com.google.gwtexpui.css.CSS'/>
-  <inherits name='com.google.gerrit.GerritGwtUICommon'/>
-  <inherits name='com.google.gerrit.UserAgent'/>
-  <inherits name='net.codemirror.CodeMirror'/>
-
-  <extend-property name='locale' values='en'/>
-  <set-property-fallback name='locale' value='en'/>
-  <set-property name='locale' value='en'/>
-  <set-configuration-property name='UiBinder.useSafeHtmlTemplates' value='true'/>
-  <set-configuration-property name='CssResource.style' value='stable'/>
-  <add-linker name='xsiframe'/>
-
-  <set-property name='gwt.logging.logLevel' value='SEVERE'/>
-
-  <!-- Disable GSS -->
-  <set-configuration-property name='CssResource.enableGss' value='false'/>
-
-  <entry-point class='com.google.gerrit.client.Gerrit'/>
-</module>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/UserAgent.gwt.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/UserAgent.gwt.xml
deleted file mode 100644
index 9644093..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/UserAgent.gwt.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<!--
- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<module>
-  <replace-with class="com.google.gerrit.client.api.PluginName.PluginNameMoz">
-    <when-type-is class="com.google.gerrit.client.api.PluginName" />
-    <when-property-is name="compiler.stackMode" value="native" />
-    <when-property-is name="user.agent" value="safari" />
-    <when-property-is name="user.agent" value="gecko1_8" />
-  </replace-with>
-
-  <replace-with class="com.google.gerrit.client.ui.FancyFlexTableImplIE8">
-    <when-type-is class="com.google.gerrit.client.ui.FancyFlexTableImpl" />
-    <any>
-      <when-property-is name="user.agent" value="ie8"/>
-    </any>
-  </replace-with>
-
-  <replace-with class="com.google.gerrit.client.Themer.ThemerIE">
-    <when-type-is class="com.google.gerrit.client.Themer" />
-    <any>
-      <when-property-is name="user.agent" value="ie8"/>
-      <when-property-is name="user.agent" value="ie9"/>
-      <when-property-is name="user.agent" value="ie10"/>
-      <when-property-is name="user.agent" value="ie11"/>
-      <when-property-is name="user.agent" value="edge"/>
-    </any>
-  </replace-with>
-</module>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/AvatarImage.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/AvatarImage.java
deleted file mode 100644
index 107d663..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/AvatarImage.java
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gerrit.client.changes.Util;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.info.AccountInfo.AvatarInfo;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gwt.event.dom.client.LoadEvent;
-import com.google.gwt.event.dom.client.LoadHandler;
-import com.google.gwt.event.dom.client.MouseOutEvent;
-import com.google.gwt.event.dom.client.MouseOutHandler;
-import com.google.gwt.event.dom.client.MouseOverEvent;
-import com.google.gwt.event.dom.client.MouseOverHandler;
-import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.UIObject;
-
-public class AvatarImage extends Image implements LoadHandler {
-  public AvatarImage() {
-    setVisible(false);
-    addLoadHandler(this);
-  }
-
-  /** A default sized avatar image. */
-  public AvatarImage(AccountInfo account) {
-    this(account, AccountInfo.AvatarInfo.DEFAULT_SIZE, true);
-  }
-
-  /**
-   * An avatar image for the given account using the requested size.
-   *
-   * @param account The account in which we are interested
-   * @param size A requested size. Note that the size can be ignored depending on the avatar
-   *     provider. A size <= 0 indicates to let the provider decide a default size.
-   * @param addPopup show avatar popup with user info on hovering over the avatar image
-   */
-  public AvatarImage(AccountInfo account, int size, boolean addPopup) {
-    addLoadHandler(this);
-    setAccount(account, size, addPopup);
-  }
-
-  public void setAccount(AccountInfo account, int size, boolean addPopup) {
-    if (account == null) {
-      setVisible(false);
-    } else if (isGerritServer(account)) {
-      setVisible(true);
-      setResource(Gerrit.RESOURCES.gerritAvatar26());
-    } else if (account.hasAvatarInfo()) {
-      setVisible(false);
-      AvatarInfo info = account.avatar(size);
-      if (info != null) {
-        setWidth(info.width() > 0 ? info.width() + "px" : "");
-        setHeight(info.height() > 0 ? info.height() + "px" : "");
-        setUrl(info.url());
-        popup(account, addPopup);
-      } else if (account.email() != null) {
-        loadAvatar(account, size, addPopup);
-      }
-    } else if (account.email() != null) {
-      loadAvatar(account, size, addPopup);
-    } else {
-      setVisible(false);
-    }
-  }
-
-  private void loadAvatar(AccountInfo account, int size, boolean addPopup) {
-    if (!Gerrit.info().plugin().hasAvatars()) {
-      setVisible(false);
-      return;
-    }
-
-    // TODO Kill /accounts/*/avatar URL.
-    String u = account.email();
-    if (Gerrit.isSignedIn() && u.equals(Gerrit.getUserAccount().email())) {
-      u = "self";
-    }
-    RestApi api = new RestApi("/accounts/").id(u).view("avatar");
-    if (size > 0) {
-      api.addParameter("s", size);
-      setSize("", size + "px");
-    }
-    setVisible(false);
-    setUrl(api.url());
-    popup(account, addPopup);
-  }
-
-  private void popup(AccountInfo account, boolean addPopup) {
-    if (addPopup) {
-      PopupHandler popupHandler = new PopupHandler(account, this);
-      addMouseOverHandler(popupHandler);
-      addMouseOutHandler(popupHandler);
-    }
-  }
-
-  @Override
-  public void onLoad(LoadEvent event) {
-    setVisible(true);
-  }
-
-  private static boolean isGerritServer(AccountInfo account) {
-    return account._accountId() == 0 && Util.C.messageNoAuthor().equals(account.name());
-  }
-
-  private static class PopupHandler implements MouseOverHandler, MouseOutHandler {
-    private final AccountInfo account;
-    private final UIObject target;
-
-    private UserPopupPanel popup;
-    private Timer showTimer;
-    private Timer hideTimer;
-
-    PopupHandler(AccountInfo account, UIObject target) {
-      this.account = account;
-      this.target = target;
-    }
-
-    private UserPopupPanel createPopupPanel(AccountInfo account) {
-      UserPopupPanel popup = new UserPopupPanel(account, false, false);
-      popup.addDomHandler(
-          new MouseOverHandler() {
-            @Override
-            public void onMouseOver(MouseOverEvent event) {
-              scheduleShow();
-            }
-          },
-          MouseOverEvent.getType());
-      popup.addDomHandler(
-          new MouseOutHandler() {
-            @Override
-            public void onMouseOut(MouseOutEvent event) {
-              scheduleHide();
-            }
-          },
-          MouseOutEvent.getType());
-      return popup;
-    }
-
-    @Override
-    public void onMouseOver(MouseOverEvent event) {
-      scheduleShow();
-    }
-
-    @Override
-    public void onMouseOut(MouseOutEvent event) {
-      scheduleHide();
-    }
-
-    private void scheduleShow() {
-      if (hideTimer != null) {
-        hideTimer.cancel();
-        hideTimer = null;
-      }
-      if ((popup != null && popup.isShowing() && popup.isVisible()) || showTimer != null) {
-        return;
-      }
-      showTimer =
-          new Timer() {
-            @Override
-            public void run() {
-              if (popup == null) {
-                popup = createPopupPanel(account);
-              }
-              if (!popup.isShowing() || !popup.isVisible()) {
-                popup.showRelativeTo(target);
-              }
-            }
-          };
-      showTimer.schedule(600);
-    }
-
-    private void scheduleHide() {
-      if (showTimer != null) {
-        showTimer.cancel();
-        showTimer = null;
-      }
-      if (popup == null || !popup.isShowing() || !popup.isVisible() || hideTimer != null) {
-        return;
-      }
-      hideTimer =
-          new Timer() {
-            @Override
-            public void run() {
-              popup.hide();
-            }
-          };
-      hideTimer.schedule(50);
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ConfirmationCallback.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ConfirmationCallback.java
deleted file mode 100644
index cc30873..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ConfirmationCallback.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-/**
- * Interface that a caller must implement to react on the result of a {@link ConfirmationDialog}.
- */
-public abstract class ConfirmationCallback {
-
-  /**
-   * Called when the {@link ConfirmationDialog} is finished with OK. To be overwritten by
-   * subclasses.
-   */
-  public abstract void onOk();
-
-  /**
-   * Called when the {@link ConfirmationDialog} is finished with Cancel. To be overwritten by
-   * subclasses.
-   */
-  public void onCancel() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ConfirmationDialog.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ConfirmationDialog.java
deleted file mode 100644
index 438df34..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ConfirmationDialog.java
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-import com.google.gwtexpui.safehtml.client.SafeHtml;
-import com.google.gwtexpui.user.client.AutoCenterDialogBox;
-
-public class ConfirmationDialog extends AutoCenterDialogBox {
-
-  private Button cancelButton;
-  private Button okButton;
-
-  public ConfirmationDialog(
-      final String dialogTitle, SafeHtml message, ConfirmationCallback callback) {
-    super(/* auto hide */ false, /* modal */ true);
-    setGlassEnabled(true);
-    setText(dialogTitle);
-
-    final FlowPanel buttons = new FlowPanel();
-
-    okButton = new Button();
-    okButton.setText(Gerrit.C.confirmationDialogOk());
-    okButton.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            hide();
-            callback.onOk();
-          }
-        });
-    buttons.add(okButton);
-
-    cancelButton = new Button();
-    cancelButton.getElement().getStyle().setProperty("marginLeft", "300px");
-    cancelButton.setText(Gerrit.C.confirmationDialogCancel());
-    cancelButton.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            hide();
-            callback.onCancel();
-          }
-        });
-    buttons.add(cancelButton);
-
-    final FlowPanel center = new FlowPanel();
-    final Widget msgWidget = message.toBlockWidget();
-    center.add(msgWidget);
-    center.add(buttons);
-    add(center);
-
-    msgWidget.setWidth("400px");
-
-    setWidget(center);
-  }
-
-  @Override
-  public void center() {
-    super.center();
-    GlobalKey.dialog(this);
-    cancelButton.setFocus(true);
-  }
-
-  public void setCancelVisible(boolean visible) {
-    cancelButton.setVisible(visible);
-    if (!visible) {
-      okButton.setFocus(true);
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/DiffObject.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/DiffObject.java
deleted file mode 100644
index 21ced4c..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/DiffObject.java
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DefaultBase;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
-
-/**
- * Represent an object that can be diffed. This can be either a regular patch set, the base of a
- * patch set, the parent of a merge, the auto-merge of a merge or an edit patch set.
- */
-public class DiffObject {
-  public static final String AUTO_MERGE = "AutoMerge";
-
-  /**
-   * Parses a string that represents a diff object.
-   *
-   * <p>The following string representations are supported:
-   *
-   * <ul>
-   *   <li>a positive integer: represents a patch set
-   *   <li>a negative integer: represents a parent of a merge patch set
-   *   <li>'0': represents the edit patch set
-   *   <li>empty string or null: represents the parent of a 1-parent patch set, also called base
-   *   <li>'AutoMerge': represents the auto-merge of a merge patch set
-   * </ul>
-   *
-   * @param changeId the ID of the change to which the diff object belongs
-   * @param str the string representation of the diff object
-   * @return the parsed diff object, {@code null} if str cannot be parsed as diff object
-   */
-  public static DiffObject parse(Change.Id changeId, String str) {
-    if (str == null || str.isEmpty()) {
-      return new DiffObject(false);
-    }
-
-    if (AUTO_MERGE.equals(str)) {
-      return new DiffObject(true);
-    }
-
-    return new DiffObject(Dispatcher.toPsId(changeId, str));
-  }
-
-  /** Create a DiffObject that represents the parent of a 1-parent patch set. */
-  public static DiffObject base() {
-    return new DiffObject(false);
-  }
-
-  /** Create a DiffObject that represents the auto-merge for a merge patch set. */
-  public static DiffObject autoMerge() {
-    return new DiffObject(true);
-  }
-
-  /** Create a DiffObject that represents a patch set. */
-  public static DiffObject patchSet(PatchSet.Id psId) {
-    return new DiffObject(psId);
-  }
-
-  private final PatchSet.Id psId;
-  private final boolean autoMerge;
-
-  private DiffObject(PatchSet.Id psId) {
-    this.psId = psId;
-    this.autoMerge = false;
-  }
-
-  private DiffObject(boolean autoMerge) {
-    this.psId = null;
-    this.autoMerge = autoMerge;
-  }
-
-  public boolean isBase() {
-    return psId == null && !autoMerge;
-  }
-
-  public boolean isAutoMerge() {
-    return psId == null && autoMerge;
-  }
-
-  public boolean isBaseOrAutoMerge() {
-    return psId == null;
-  }
-
-  public boolean isPatchSet() {
-    return psId != null && psId.get() > 0;
-  }
-
-  public boolean isParent() {
-    return psId != null && psId.get() < 0;
-  }
-
-  public boolean isEdit() {
-    return psId != null && psId.get() == 0;
-  }
-
-  /**
-   * Returns the DiffObject as PatchSet.Id.
-   *
-   * @return PatchSet.Id with an id > 0 for a regular patch set; PatchSet.Id with an id < 0 for a
-   *     parent of a merge; PatchSet.Id with id == 0 for an edit patch set; {@code null} for the
-   *     base of a 1-parent patch set and for the auto-merge of a merge patch set
-   */
-  public PatchSet.Id asPatchSetId() {
-    return psId;
-  }
-
-  /**
-   * Returns the parent number for a parent of a merge.
-   *
-   * @return 1-based parent number, 0 if this DiffObject is not a parent of a merge
-   */
-  public int getParentNum() {
-    if (!isParent()) {
-      return 0;
-    }
-
-    return -psId.get();
-  }
-
-  /**
-   * Returns a string representation of this DiffObject that can be used in URLs.
-   *
-   * <p>The following string representations are returned:
-   *
-   * <ul>
-   *   <li>a positive integer for a patch set
-   *   <li>a negative integer for a parent of a merge patch set
-   *   <li>'0' for the edit patch set
-   *   <li>{@code null} for the parent of a 1-parent patch set, also called base
-   *   <li>'AutoMerge' for the auto-merge of a merge patch set
-   * </ul>
-   *
-   * @return string representation of this DiffObject
-   */
-  public String asString() {
-    if (autoMerge) {
-      if (Gerrit.getUserPreferences().defaultBaseForMerges() != DefaultBase.AUTO_MERGE) {
-        return AUTO_MERGE;
-      }
-      return null;
-    }
-
-    if (psId != null) {
-      return psId.getId();
-    }
-
-    return null;
-  }
-
-  @Override
-  public String toString() {
-    if (isPatchSet()) {
-      return "Patch Set " + psId.getId();
-    }
-
-    if (isParent()) {
-      return "Parent " + psId.getId();
-    }
-
-    if (isEdit()) {
-      return "Edit Patch Set";
-    }
-
-    if (isAutoMerge()) {
-      return "Auto Merge";
-    }
-
-    return "Base";
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/DiffWebLinkInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/DiffWebLinkInfo.java
deleted file mode 100644
index fe7016f..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/DiffWebLinkInfo.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gerrit.client.info.WebLinkInfo;
-
-public class DiffWebLinkInfo extends WebLinkInfo {
-  public final native boolean showOnSideBySideDiffView()
-      /*-{ return this.show_on_side_by_side_diff_view || false; }-*/ ;
-
-  public final native boolean showOnUnifiedDiffView()
-      /*-{ return this.show_on_unified_diff_view || false; }-*/ ;
-
-  protected DiffWebLinkInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java
deleted file mode 100644
index 4b84864..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java
+++ /dev/null
@@ -1,879 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import static com.google.gerrit.common.PageLinks.ADMIN_CREATE_GROUP;
-import static com.google.gerrit.common.PageLinks.ADMIN_CREATE_PROJECT;
-import static com.google.gerrit.common.PageLinks.ADMIN_GROUPS;
-import static com.google.gerrit.common.PageLinks.ADMIN_PLUGINS;
-import static com.google.gerrit.common.PageLinks.ADMIN_PROJECTS;
-import static com.google.gerrit.common.PageLinks.DASHBOARDS;
-import static com.google.gerrit.common.PageLinks.MINE;
-import static com.google.gerrit.common.PageLinks.MY_GROUPS;
-import static com.google.gerrit.common.PageLinks.PROJECTS;
-import static com.google.gerrit.common.PageLinks.QUERY;
-import static com.google.gerrit.common.PageLinks.REGISTER;
-import static com.google.gerrit.common.PageLinks.SETTINGS;
-import static com.google.gerrit.common.PageLinks.SETTINGS_AGREEMENTS;
-import static com.google.gerrit.common.PageLinks.SETTINGS_CONTACT;
-import static com.google.gerrit.common.PageLinks.SETTINGS_DIFF_PREFERENCES;
-import static com.google.gerrit.common.PageLinks.SETTINGS_EDIT_PREFERENCES;
-import static com.google.gerrit.common.PageLinks.SETTINGS_EXTENSION;
-import static com.google.gerrit.common.PageLinks.SETTINGS_GPGKEYS;
-import static com.google.gerrit.common.PageLinks.SETTINGS_HTTP_PASSWORD;
-import static com.google.gerrit.common.PageLinks.SETTINGS_MYGROUPS;
-import static com.google.gerrit.common.PageLinks.SETTINGS_NEW_AGREEMENT;
-import static com.google.gerrit.common.PageLinks.SETTINGS_OAUTH_TOKEN;
-import static com.google.gerrit.common.PageLinks.SETTINGS_PREFERENCES;
-import static com.google.gerrit.common.PageLinks.SETTINGS_PROJECTS;
-import static com.google.gerrit.common.PageLinks.SETTINGS_SSHKEYS;
-import static com.google.gerrit.common.PageLinks.SETTINGS_WEBIDENT;
-
-import com.google.gerrit.client.account.MyAgreementsScreen;
-import com.google.gerrit.client.account.MyContactInformationScreen;
-import com.google.gerrit.client.account.MyDiffPreferencesScreen;
-import com.google.gerrit.client.account.MyEditPreferencesScreen;
-import com.google.gerrit.client.account.MyGpgKeysScreen;
-import com.google.gerrit.client.account.MyGroupsScreen;
-import com.google.gerrit.client.account.MyIdentitiesScreen;
-import com.google.gerrit.client.account.MyOAuthTokenScreen;
-import com.google.gerrit.client.account.MyPasswordScreen;
-import com.google.gerrit.client.account.MyPreferencesScreen;
-import com.google.gerrit.client.account.MyProfileScreen;
-import com.google.gerrit.client.account.MySshKeysScreen;
-import com.google.gerrit.client.account.MyWatchedProjectsScreen;
-import com.google.gerrit.client.account.NewAgreementScreen;
-import com.google.gerrit.client.account.RegisterScreen;
-import com.google.gerrit.client.account.ValidateEmailScreen;
-import com.google.gerrit.client.admin.AccountGroupAuditLogScreen;
-import com.google.gerrit.client.admin.AccountGroupInfoScreen;
-import com.google.gerrit.client.admin.AccountGroupMembersScreen;
-import com.google.gerrit.client.admin.AccountGroupScreen;
-import com.google.gerrit.client.admin.CreateGroupScreen;
-import com.google.gerrit.client.admin.CreateProjectScreen;
-import com.google.gerrit.client.admin.GroupListScreen;
-import com.google.gerrit.client.admin.PluginListScreen;
-import com.google.gerrit.client.admin.ProjectAccessScreen;
-import com.google.gerrit.client.admin.ProjectBranchesScreen;
-import com.google.gerrit.client.admin.ProjectDashboardsScreen;
-import com.google.gerrit.client.admin.ProjectInfoScreen;
-import com.google.gerrit.client.admin.ProjectListScreen;
-import com.google.gerrit.client.admin.ProjectScreen;
-import com.google.gerrit.client.admin.ProjectTagsScreen;
-import com.google.gerrit.client.api.ExtensionScreen;
-import com.google.gerrit.client.api.ExtensionSettingsScreen;
-import com.google.gerrit.client.change.ChangeScreen;
-import com.google.gerrit.client.change.FileTable;
-import com.google.gerrit.client.change.ProjectChangeId;
-import com.google.gerrit.client.changes.AccountDashboardScreen;
-import com.google.gerrit.client.changes.CustomDashboardScreen;
-import com.google.gerrit.client.changes.ProjectDashboardScreen;
-import com.google.gerrit.client.changes.QueryScreen;
-import com.google.gerrit.client.dashboards.DashboardInfo;
-import com.google.gerrit.client.dashboards.DashboardList;
-import com.google.gerrit.client.diff.DisplaySide;
-import com.google.gerrit.client.diff.SideBySide;
-import com.google.gerrit.client.diff.Unified;
-import com.google.gerrit.client.documentation.DocScreen;
-import com.google.gerrit.client.editor.EditScreen;
-import com.google.gerrit.client.groups.GroupApi;
-import com.google.gerrit.client.info.GroupInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.client.ui.Screen;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DiffView;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Patch;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.RunAsyncCallback;
-import com.google.gwt.http.client.URL;
-import com.google.gwtexpui.user.client.UserAgent;
-import com.google.gwtorm.client.KeyUtil;
-
-public class Dispatcher {
-  public static String toPatch(
-      @Nullable Project.NameKey project,
-      DiffObject diffBase,
-      PatchSet.Id revision,
-      String fileName) {
-    return toPatch("", project, diffBase, revision, fileName, null, 0);
-  }
-
-  public static String toPatch(
-      @Nullable Project.NameKey project,
-      DiffObject diffBase,
-      PatchSet.Id revision,
-      String fileName,
-      DisplaySide side,
-      int line) {
-    return toPatch("", project, diffBase, revision, fileName, side, line);
-  }
-
-  public static String toSideBySide(
-      @Nullable Project.NameKey project,
-      DiffObject diffBase,
-      PatchSet.Id revision,
-      String fileName) {
-    return toPatch("sidebyside", project, diffBase, revision, fileName, null, 0);
-  }
-
-  public static String toUnified(
-      @Nullable Project.NameKey project,
-      DiffObject diffBase,
-      PatchSet.Id revision,
-      String fileName) {
-    return toPatch("unified", project, diffBase, revision, fileName, null, 0);
-  }
-
-  public static String toPatch(
-      @Nullable Project.NameKey project, String type, DiffObject diffBase, Patch.Key id) {
-    return toPatch(type, project, diffBase, id.getParentKey(), id.get(), null, 0);
-  }
-
-  public static String toEditScreen(
-      @Nullable Project.NameKey project, PatchSet.Id revision, String fileName) {
-    return toEditScreen(project, revision, fileName, 0);
-  }
-
-  public static String toEditScreen(
-      @Nullable Project.NameKey project, PatchSet.Id revision, String fileName, int line) {
-    return toPatch("edit", project, DiffObject.base(), revision, fileName, null, line);
-  }
-
-  private static String toPatch(
-      String type,
-      @Nullable Project.NameKey project,
-      DiffObject diffBase,
-      PatchSet.Id revision,
-      String fileName,
-      DisplaySide side,
-      int line) {
-    Change.Id c = revision.getParentKey();
-    StringBuilder p = new StringBuilder(PageLinks.toChange(project, c));
-    if (diffBase != null && diffBase.asString() != null) {
-      p.append(diffBase.asString()).append("..");
-    }
-    p.append(revision.getId()).append("/").append(KeyUtil.encode(fileName));
-    if (type != null && !type.isEmpty() && (!"sidebyside".equals(type) || preferUnified())) {
-      p.append(",").append(type);
-    }
-    if (side == DisplaySide.A && line > 0) {
-      p.append("@a").append(line);
-    } else if (line > 0) {
-      p.append("@").append(line);
-    }
-    return p.toString();
-  }
-
-  public static String toGroup(AccountGroup.Id id) {
-    return ADMIN_GROUPS + id.toString();
-  }
-
-  public static String toGroup(AccountGroup.Id id, String panel) {
-    return ADMIN_GROUPS + id.toString() + "," + panel;
-  }
-
-  public static String toGroup(AccountGroup.UUID uuid) {
-    return PageLinks.toGroup(uuid);
-  }
-
-  public static String toGroup(AccountGroup.UUID uuid, String panel) {
-    return toGroup(uuid) + "," + panel;
-  }
-
-  public static String toProject(Project.NameKey n) {
-    return toProjectAdmin(n, ProjectScreen.getSavedPanel());
-  }
-
-  public static String toProjectAdmin(Project.NameKey n, String panel) {
-    if (panel == null || ProjectScreen.INFO.equals(panel)) {
-      return ADMIN_PROJECTS + n.toString();
-    }
-    return ADMIN_PROJECTS + n.toString() + "," + panel;
-  }
-
-  static final String RELOAD_UI = "/reload-ui/";
-  private static boolean wasStartedByReloadUI;
-
-  void display(String token) {
-    assert token != null;
-    try {
-      try {
-        if (matchPrefix(RELOAD_UI, token)) {
-          wasStartedByReloadUI = true;
-          token = skip(token);
-        }
-        select(token);
-      } finally {
-        wasStartedByReloadUI = false;
-      }
-    } catch (RuntimeException err) {
-      GWT.log("Error parsing history token: " + token, err);
-      Gerrit.display(token, new NotFoundScreen());
-    }
-  }
-
-  private static void select(String token) {
-    token = Gerrit.getUrlAliasMatcher().replace(token);
-
-    if (matchPrefix(QUERY, token)) {
-      query(token);
-
-    } else if (matchPrefix("/Documentation/q/", token)) {
-      docSearch(token);
-
-    } else if (matchPrefix("/c/", token)) {
-      change(token);
-
-    } else if (matchPrefix("/x/", token)) {
-      extension(token);
-
-    } else if (matchExact(MINE, token)) {
-      String defaultScreenToken = Gerrit.getDefaultScreenToken();
-      if (defaultScreenToken != null && !MINE.equals(defaultScreenToken)) {
-        select(defaultScreenToken);
-      } else {
-        Gerrit.display(token, mine());
-      }
-
-    } else if (matchPrefix("/dashboard/", token)) {
-      dashboard(token);
-
-    } else if (matchPrefix(PROJECTS, token)) {
-      projects(token);
-
-    } else if (matchExact(SETTINGS, token)
-        || matchPrefix("/settings/", token)
-        || matchExact(MY_GROUPS, token)
-        || matchExact("register", token)
-        || matchExact(REGISTER, token)
-        || matchPrefix("/register/", token)
-        || matchPrefix("/VE/", token)
-        || matchPrefix("VE,", token)
-        || matchPrefix("/SignInFailure,", token)) {
-      settings(token);
-
-    } else if (matchPrefix("/admin/", token)) {
-      admin(token);
-
-    } else {
-      Gerrit.display(token, new NotFoundScreen());
-    }
-  }
-
-  private static void query(String token) {
-    String s = skip(token);
-    int c = s.indexOf(',');
-    Screen screen;
-    if (c >= 0) {
-      String prefix = s.substring(0, c);
-      if (s.substring(c).equals(",n,z")) {
-        // Respect legacy token with max sortkey.
-        screen = new QueryScreen(prefix, 0);
-      } else {
-        screen = new QueryScreen(prefix, Integer.parseInt(s.substring(c + 1)));
-      }
-    } else {
-      screen = new QueryScreen(s, 0);
-    }
-    Gerrit.display(token, screen);
-  }
-
-  private static Screen mine() {
-    if (Gerrit.isSignedIn()) {
-      return new AccountDashboardScreen(Gerrit.getUserAccount()._accountId());
-    }
-    Screen r = new AccountDashboardScreen(null);
-    r.setRequiresSignIn(true);
-    return r;
-  }
-
-  private static void dashboard(String token) {
-    String rest = skip(token);
-    if (rest.matches("[0-9]+")) {
-      int accountId = Integer.parseInt(rest);
-      Gerrit.display(token, new AccountDashboardScreen(accountId));
-      return;
-    }
-
-    if (rest.equals("self")) {
-      if (Gerrit.isSignedIn()) {
-        Gerrit.display(token, new AccountDashboardScreen(Gerrit.getUserAccount()._accountId()));
-      } else {
-        Screen s = new AccountDashboardScreen(null);
-        s.setRequiresSignIn(true);
-        Gerrit.display(token, s);
-      }
-      return;
-    }
-
-    if (rest.startsWith("?")) {
-      Gerrit.display(token, new CustomDashboardScreen(rest.substring(1)));
-      return;
-    }
-
-    Gerrit.display(token, new NotFoundScreen());
-  }
-
-  private static void projects(String token) {
-    String rest = skip(token);
-    int c = rest.indexOf(DASHBOARDS);
-    if (0 <= c) {
-      final String project = URL.decodePathSegment(rest.substring(0, c));
-      rest = rest.substring(c);
-      if (matchPrefix(DASHBOARDS, rest)) {
-        final String dashboardId = skip(rest);
-        GerritCallback<DashboardInfo> cb =
-            new GerritCallback<DashboardInfo>() {
-              @Override
-              public void onSuccess(DashboardInfo result) {
-                if (matchPrefix("/dashboard/", result.url())) {
-                  String params = skip(result.url()).substring(1);
-                  ProjectDashboardScreen dash =
-                      new ProjectDashboardScreen(new Project.NameKey(project), params);
-                  Gerrit.display(token, dash);
-                }
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {
-                if ("default".equals(dashboardId) && RestApi.isNotFound(caught)) {
-                  Gerrit.display(
-                      PageLinks.toChangeQuery(
-                          PageLinks.projectQuery(new Project.NameKey(project))));
-                } else {
-                  super.onFailure(caught);
-                }
-              }
-            };
-        if ("default".equals(dashboardId)) {
-          DashboardList.getDefault(new Project.NameKey(project), cb);
-          return;
-        }
-        c = dashboardId.indexOf(":");
-        if (0 <= c) {
-          final String ref = URL.decodeQueryString(dashboardId.substring(0, c));
-          final String path = URL.decodeQueryString(dashboardId.substring(c + 1));
-          DashboardList.get(new Project.NameKey(project), ref + ":" + path, cb);
-          return;
-        }
-      }
-    }
-
-    Gerrit.display(token, new NotFoundScreen());
-  }
-
-  private static void change(String token) {
-    String rest = skip(token);
-    int c = rest.lastIndexOf(',');
-    String panel = null;
-    if (0 <= c) {
-      panel = rest.substring(c + 1);
-      rest = rest.substring(0, c);
-      int at = panel.lastIndexOf('@');
-      if (at > 0) {
-        rest += panel.substring(at);
-        panel = panel.substring(0, at);
-      }
-    }
-
-    ProjectChangeId id = ProjectChangeId.create(rest);
-    rest = rest.length() > id.identifierLength() ? rest.substring(id.identifierLength() + 1) : "";
-
-    if (rest.isEmpty()) {
-      FileTable.Mode mode = FileTable.Mode.REVIEW;
-      if (panel != null && (panel.equals("edit") || panel.startsWith("edit/"))) {
-        mode = FileTable.Mode.EDIT;
-        panel = null;
-      }
-      Gerrit.display(
-          token,
-          panel == null
-              ? new ChangeScreen(
-                  id.getProject(), id.getChangeId(), DiffObject.base(), null, false, mode)
-              : new NotFoundScreen());
-      return;
-    }
-
-    String psIdStr;
-    int s = rest.indexOf('/');
-    if (0 <= s) {
-      psIdStr = rest.substring(0, s);
-      rest = rest.substring(s + 1);
-    } else {
-      psIdStr = rest;
-      rest = "";
-    }
-
-    DiffObject base = DiffObject.base();
-    PatchSet.Id ps;
-    int dotdot = psIdStr.indexOf("..");
-    if (1 <= dotdot) {
-      base = DiffObject.parse(id.getChangeId(), psIdStr.substring(0, dotdot));
-      if (base == null) {
-        Gerrit.display(token, new NotFoundScreen());
-      }
-      psIdStr = psIdStr.substring(dotdot + 2);
-    }
-    ps = toPsId(id.getChangeId(), psIdStr);
-
-    if (!rest.isEmpty()) {
-      DisplaySide side = DisplaySide.B;
-      int line = 0;
-      int at = rest.lastIndexOf('@');
-      if (at > 0) {
-        String l = rest.substring(at + 1);
-        if (l.startsWith("a")) {
-          side = DisplaySide.A;
-          l = l.substring(1);
-        }
-        line = Integer.parseInt(l);
-        rest = rest.substring(0, at);
-      }
-      Patch.Key p = new Patch.Key(ps, KeyUtil.decode(rest));
-      patch(token, id.getProject(), base, p, side, line, panel);
-    } else {
-      if (panel == null) {
-        Gerrit.display(
-            token,
-            new ChangeScreen(
-                id.getProject(),
-                id.getChangeId(),
-                base,
-                String.valueOf(ps.get()),
-                false,
-                FileTable.Mode.REVIEW));
-      } else {
-        Gerrit.display(token, new NotFoundScreen());
-      }
-    }
-  }
-
-  public static PatchSet.Id toPsId(Change.Id id, String psIdStr) {
-    return new PatchSet.Id(id, psIdStr.equals("edit") ? 0 : Integer.parseInt(psIdStr));
-  }
-
-  private static void extension(String token) {
-    ExtensionScreen view = new ExtensionScreen(skip(token));
-    if (view.isFound()) {
-      Gerrit.display(token, view);
-    } else {
-      Gerrit.display(token, new NotFoundScreen());
-    }
-  }
-
-  private static void patch(
-      String token,
-      @Nullable Project.NameKey project,
-      DiffObject base,
-      Patch.Key id,
-      DisplaySide side,
-      int line,
-      String panelType) {
-    String panel = panelType;
-    if (panel == null) {
-      int c = token.lastIndexOf(',');
-      panel = 0 <= c ? token.substring(c + 1) : "";
-    }
-
-    if ("".equals(panel) || /* DEPRECATED URL */ "cm".equals(panel)) {
-      if (preferUnified()) {
-        unified(token, project, base, id, side, line);
-      } else {
-        codemirror(token, base, project, id, side, line);
-      }
-    } else if ("sidebyside".equals(panel)) {
-      codemirror(token, base, project, id, side, line);
-    } else if ("unified".equals(panel)) {
-      unified(token, project, base, id, side, line);
-    } else if ("edit".equals(panel)) {
-      if (!Patch.isMagic(id.get()) || Patch.COMMIT_MSG.equals(id.get())) {
-        codemirrorForEdit(token, project, id, line);
-      } else {
-        Gerrit.display(token, new NotFoundScreen());
-      }
-    } else {
-      Gerrit.display(token, new NotFoundScreen());
-    }
-  }
-
-  private static boolean preferUnified() {
-    return DiffView.UNIFIED_DIFF.equals(Gerrit.getUserPreferences().diffView())
-        || (UserAgent.isPortrait() && UserAgent.isMobile());
-  }
-
-  private static void unified(
-      final String token,
-      final Project.NameKey project,
-      final DiffObject base,
-      final Patch.Key id,
-      final DisplaySide side,
-      final int line) {
-    GWT.runAsync(
-        new AsyncSplit(token) {
-          @Override
-          public void onSuccess() {
-            Gerrit.display(
-                token,
-                new Unified(
-                    project, base, DiffObject.patchSet(id.getParentKey()), id.get(), side, line));
-          }
-        });
-  }
-
-  private static void codemirror(
-      final String token,
-      final DiffObject base,
-      @Nullable final Project.NameKey project,
-      final Patch.Key id,
-      final DisplaySide side,
-      final int line) {
-    GWT.runAsync(
-        new AsyncSplit(token) {
-          @Override
-          public void onSuccess() {
-            Gerrit.display(
-                token,
-                new SideBySide(
-                    project, base, DiffObject.patchSet(id.getParentKey()), id.get(), side, line));
-          }
-        });
-  }
-
-  private static void codemirrorForEdit(
-      final String token,
-      @Nullable final Project.NameKey project,
-      final Patch.Key id,
-      final int line) {
-    GWT.runAsync(
-        new AsyncSplit(token) {
-          @Override
-          public void onSuccess() {
-            Gerrit.display(token, new EditScreen(project, id, line));
-          }
-        });
-  }
-
-  private static void settings(String token) {
-    GWT.runAsync(
-        new AsyncSplit(token) {
-          @Override
-          public void onSuccess() {
-            Gerrit.display(token, select());
-          }
-
-          private Screen select() {
-            if (matchExact(SETTINGS, token)) {
-              return new MyProfileScreen();
-            }
-
-            if (matchExact(SETTINGS_PREFERENCES, token)) {
-              return new MyPreferencesScreen();
-            }
-
-            if (matchExact(SETTINGS_DIFF_PREFERENCES, token)) {
-              return new MyDiffPreferencesScreen();
-            }
-
-            if (matchExact(SETTINGS_EDIT_PREFERENCES, token)) {
-              return new MyEditPreferencesScreen();
-            }
-
-            if (matchExact(SETTINGS_PROJECTS, token)) {
-              return new MyWatchedProjectsScreen();
-            }
-
-            if (matchExact(SETTINGS_CONTACT, token)) {
-              return new MyContactInformationScreen();
-            }
-
-            if (matchExact(SETTINGS_SSHKEYS, token)) {
-              return new MySshKeysScreen();
-            }
-
-            if (matchExact(SETTINGS_GPGKEYS, token) && Gerrit.info().gerrit().editGpgKeys()) {
-              return new MyGpgKeysScreen();
-            }
-
-            if (matchExact(SETTINGS_WEBIDENT, token)) {
-              return new MyIdentitiesScreen();
-            }
-
-            if (matchExact(SETTINGS_HTTP_PASSWORD, token)) {
-              return new MyPasswordScreen();
-            }
-
-            if (matchExact(SETTINGS_OAUTH_TOKEN, token) && Gerrit.info().auth().isOAuth()) {
-              return new MyOAuthTokenScreen();
-            }
-
-            if (matchExact(MY_GROUPS, token) || matchExact(SETTINGS_MYGROUPS, token)) {
-              return new MyGroupsScreen();
-            }
-
-            if (matchExact(SETTINGS_AGREEMENTS, token)
-                && Gerrit.info().auth().useContributorAgreements()) {
-              return new MyAgreementsScreen();
-            }
-
-            if (matchExact(REGISTER, token)
-                || matchExact("/register/", token)
-                || matchExact("register", token)) {
-              return new RegisterScreen(MINE);
-            } else if (matchPrefix("/register/", token)) {
-              return new RegisterScreen("/" + skip(token));
-            }
-
-            if (matchPrefix("/VE/", token) || matchPrefix("VE,", token)) {
-              return new ValidateEmailScreen(skip(token));
-            }
-
-            if (matchExact(SETTINGS_NEW_AGREEMENT, token)) {
-              return new NewAgreementScreen();
-            }
-
-            if (matchPrefix(SETTINGS_NEW_AGREEMENT + "/", token)) {
-              return new NewAgreementScreen(skip(token));
-            }
-
-            if (matchPrefix(SETTINGS_EXTENSION, token)) {
-              ExtensionSettingsScreen view = new ExtensionSettingsScreen(skip(token));
-              if (view.isFound()) {
-                return view;
-              }
-              return new NotFoundScreen();
-            }
-
-            return new NotFoundScreen();
-          }
-        });
-  }
-
-  private static void admin(String token) {
-    GWT.runAsync(
-        new AsyncSplit(token) {
-          @Override
-          public void onSuccess() {
-            if (matchExact(ADMIN_GROUPS, token) || matchExact("/admin/groups", token)) {
-              Gerrit.display(token, new GroupListScreen());
-
-            } else if (matchPrefix(ADMIN_GROUPS, token)) {
-              String rest = skip(token);
-              if (rest.startsWith("?")) {
-                Gerrit.display(token, new GroupListScreen(rest.substring(1)));
-              } else {
-                group();
-              }
-
-            } else if (matchPrefix("/admin/groups", token)) {
-              String rest = skip(token);
-              if (rest.startsWith("?")) {
-                Gerrit.display(token, new GroupListScreen(rest.substring(1)));
-              }
-
-            } else if (matchExact(ADMIN_PROJECTS, token) || matchExact("/admin/projects", token)) {
-              Gerrit.display(token, new ProjectListScreen());
-
-            } else if (matchPrefix(ADMIN_PROJECTS, token)) {
-              String rest = skip(token);
-              if (rest.startsWith("?")) {
-                Gerrit.display(token, new ProjectListScreen(rest.substring(1)));
-              } else {
-                Gerrit.display(token, selectProject());
-              }
-
-            } else if (matchPrefix("/admin/projects", token)) {
-              String rest = skip(token);
-              if (rest.startsWith("?")) {
-                Gerrit.display(token, new ProjectListScreen(rest.substring(1)));
-              }
-
-            } else if (matchPrefix(ADMIN_PLUGINS, token) || matchExact("/admin/plugins", token)) {
-              Gerrit.display(token, new PluginListScreen());
-
-            } else if (matchExact(ADMIN_CREATE_PROJECT, token)
-                || matchExact("/admin/create-project", token)) {
-              Gerrit.display(token, new CreateProjectScreen());
-
-            } else if (matchExact(ADMIN_CREATE_GROUP, token)
-                || matchExact("/admin/create-group", token)) {
-              Gerrit.display(token, new CreateGroupScreen());
-
-            } else {
-              Gerrit.display(token, new NotFoundScreen());
-            }
-          }
-
-          private void group() {
-            final String panel;
-            final String group;
-
-            if (matchPrefix("/admin/groups/uuid-", token)) {
-              String p = skip(token);
-              int c = p.indexOf(',');
-              if (c < 0) {
-                group = p;
-                panel = null;
-              } else {
-                group = p.substring(0, c);
-                panel = p.substring(c + 1);
-              }
-            } else if (matchPrefix(ADMIN_GROUPS, token)) {
-              String p = skip(token);
-              int c = p.indexOf(',');
-              if (c < 0) {
-                group = p;
-                panel = null;
-              } else {
-                group = p.substring(0, c);
-                panel = p.substring(c + 1);
-              }
-            } else {
-              Gerrit.display(token, new NotFoundScreen());
-              return;
-            }
-
-            GroupApi.getGroupDetail(
-                group,
-                new GerritCallback<GroupInfo>() {
-                  @Override
-                  public void onSuccess(GroupInfo group) {
-                    if (panel == null || panel.isEmpty()) {
-                      // The token does not say which group screen should be shown,
-                      // as default for internal groups show the members, as default
-                      // for external and system groups show the info screen (since
-                      // for external and system groups the members cannot be
-                      // shown in the web UI).
-                      //
-                      if (AccountGroup.isInternalGroup(group.getGroupUUID())) {
-                        String newToken = toGroup(group.getGroupId(), AccountGroupScreen.MEMBERS);
-                        Gerrit.display(newToken, new AccountGroupMembersScreen(group, newToken));
-                      } else {
-                        String newToken = toGroup(group.getGroupId(), AccountGroupScreen.INFO);
-                        Gerrit.display(newToken, new AccountGroupInfoScreen(group, newToken));
-                      }
-                    } else if (AccountGroupScreen.INFO.equals(panel)) {
-                      Gerrit.display(token, new AccountGroupInfoScreen(group, token));
-                    } else if (AccountGroupScreen.MEMBERS.equals(panel)) {
-                      Gerrit.display(token, new AccountGroupMembersScreen(group, token));
-                    } else if (AccountGroupScreen.AUDIT_LOG.equals(panel)) {
-                      Gerrit.display(token, new AccountGroupAuditLogScreen(group, token));
-                    } else {
-                      Gerrit.display(token, new NotFoundScreen());
-                    }
-                  }
-                });
-          }
-
-          private Screen selectProject() {
-            if (matchPrefix(ADMIN_PROJECTS, token)) {
-              String rest = skip(token);
-              int c = rest.lastIndexOf(',');
-              if (c < 0) {
-                return new ProjectInfoScreen(Project.NameKey.parse(rest));
-              } else if (c == 0) {
-                return new NotFoundScreen();
-              }
-
-              int q = rest.lastIndexOf('?');
-              if (q > 0 && rest.lastIndexOf(',', q) > 0) {
-                c = rest.substring(0, q - 1).lastIndexOf(',');
-              }
-
-              Project.NameKey k = Project.NameKey.parse(rest.substring(0, c));
-              String panel = rest.substring(c + 1);
-
-              if (ProjectScreen.INFO.equals(panel)) {
-                return new ProjectInfoScreen(k);
-              }
-
-              if (ProjectScreen.BRANCHES.equals(panel)
-                  || matchPrefix(ProjectScreen.BRANCHES, panel)) {
-                return new ProjectBranchesScreen(k);
-              }
-
-              if (ProjectScreen.TAGS.equals(panel) || matchPrefix(ProjectScreen.TAGS, panel)) {
-                return new ProjectTagsScreen(k);
-              }
-
-              if (ProjectScreen.ACCESS.equals(panel)) {
-                return new ProjectAccessScreen(k);
-              }
-
-              if (ProjectScreen.DASHBOARDS.equals(panel)) {
-                return new ProjectDashboardsScreen(k);
-              }
-            }
-            return new NotFoundScreen();
-          }
-        });
-  }
-
-  private static boolean matchExact(String want, String token) {
-    return token.equals(want);
-  }
-
-  private static int prefixlen;
-
-  private static boolean matchPrefix(String want, String token) {
-    if (token.startsWith(want)) {
-      prefixlen = want.length();
-      return true;
-    }
-    return false;
-  }
-
-  private static String skip(String token) {
-    return token.substring(prefixlen);
-  }
-
-  private abstract static class AsyncSplit implements RunAsyncCallback {
-    private final boolean isReloadUi;
-    protected final String token;
-
-    protected AsyncSplit(String token) {
-      this.isReloadUi = wasStartedByReloadUI;
-      this.token = token;
-    }
-
-    @Override
-    public final void onFailure(Throwable reason) {
-      if (!isReloadUi && "HTTP download failed with status 404".equals(reason.getMessage())) {
-        // The server was upgraded since we last download the main script,
-        // so the pointers to the splits aren't valid anymore.  Force the
-        // page to reload itself and pick up the new code.
-        //
-        Gerrit.upgradeUI(token);
-      } else {
-        new ErrorDialog(reason).center();
-      }
-    }
-  }
-
-  private static void docSearch(String token) {
-    GWT.runAsync(
-        new AsyncSplit(token) {
-          @Override
-          public void onSuccess() {
-            Gerrit.display(token, new DocScreen(skip(token)));
-          }
-        });
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ErrorDialog.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ErrorDialog.java
deleted file mode 100644
index c116d76..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ErrorDialog.java
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.client.rpc.RpcConstants;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.http.client.Response;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.rpc.StatusCodeException;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwtexpui.safehtml.client.SafeHtml;
-import com.google.gwtjsonrpc.client.RemoteJsonException;
-
-/** A dialog box showing an error message, when bad things happen. */
-public class ErrorDialog extends PopupPanel {
-  private final Label text;
-  private final FlowPanel body;
-  private final Button closey;
-
-  protected ErrorDialog() {
-    super(/* auto hide */ false, /* modal */ true);
-    setGlassEnabled(true);
-    getGlassElement().addClassName(Gerrit.RESOURCES.css().errorDialogGlass());
-
-    text = new Label();
-    text.setStyleName(Gerrit.RESOURCES.css().errorDialogTitle());
-
-    body = new FlowPanel();
-
-    final FlowPanel buttons = new FlowPanel();
-    buttons.setStyleName(Gerrit.RESOURCES.css().errorDialogButtons());
-
-    closey = new Button();
-    closey.setText(Gerrit.C.errorDialogContinue());
-    closey.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            hide();
-          }
-        });
-    closey.addKeyPressHandler(
-        new KeyPressHandler() {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            // if the close button is triggered by a key we need to consume the key
-            // event, otherwise the key event would be propagated to the parent
-            // screen and eventually trigger some unwanted action there after the
-            // error dialog was closed
-            event.stopPropagation();
-          }
-        });
-    buttons.add(closey);
-
-    final FlowPanel center = new FlowPanel();
-    center.add(text);
-    center.add(body);
-    center.add(buttons);
-
-    setText(Gerrit.C.errorTitle());
-    addStyleName(Gerrit.RESOURCES.css().errorDialog());
-    add(center);
-
-    int l = Window.getScrollLeft() + 20;
-    int t = Window.getScrollTop() + 20;
-    setPopupPosition(l, t);
-  }
-
-  /** Create a dialog box to show a single message string. */
-  public ErrorDialog(String message) {
-    this();
-    body.add(createErrorMsgLabel(message));
-  }
-
-  /** Create a dialog box to show a single message string. */
-  public ErrorDialog(SafeHtml message) {
-    this();
-    body.add(message.toBlockWidget());
-  }
-
-  /** Create a dialog box to nicely format an exception. */
-  public ErrorDialog(Throwable what) {
-    this();
-
-    String hdr;
-    String msg;
-
-    if (what instanceof StatusCodeException) {
-      StatusCodeException sc = (StatusCodeException) what;
-      if (RestApi.isExpected(sc.getStatusCode())) {
-        hdr = null;
-        msg = sc.getEncodedResponse();
-      } else if (sc.getStatusCode() == Response.SC_INTERNAL_SERVER_ERROR) {
-        hdr = null;
-        msg = what.getMessage();
-      } else {
-        hdr = RpcConstants.C.errorServerUnavailable();
-        msg = what.getMessage();
-      }
-
-    } else if (what instanceof RemoteJsonException) {
-      // TODO Remove RemoteJsonException from Gerrit sources.
-      hdr = RpcConstants.C.errorRemoteJsonException();
-      msg = what.getMessage();
-
-    } else {
-      // TODO Fix callers of ErrorDialog to stop passing random types.
-      hdr = what.getClass().getName();
-      if (hdr.startsWith("java.lang.")) {
-        hdr = hdr.substring("java.lang.".length());
-      } else if (hdr.startsWith("com.google.gerrit.")) {
-        hdr = hdr.substring(hdr.lastIndexOf('.') + 1);
-      }
-      if (hdr.endsWith("Exception")) {
-        hdr = hdr.substring(0, hdr.length() - "Exception".length());
-      } else if (hdr.endsWith("Error")) {
-        hdr = hdr.substring(0, hdr.length() - "Error".length());
-      }
-      msg = what.getMessage();
-    }
-
-    if (hdr != null) {
-      final Label r = new Label(hdr);
-      r.setStyleName(Gerrit.RESOURCES.css().errorDialogErrorType());
-      body.add(r);
-    }
-
-    if (msg != null) {
-      body.add(createErrorMsgLabel(msg));
-    }
-  }
-
-  private Label createErrorMsgLabel(String message) {
-    Label m = new Label(message);
-    m.getElement().getStyle().setProperty("white-space", "pre");
-    return m;
-  }
-
-  public ErrorDialog setText(String t) {
-    text.setText(t);
-    return this;
-  }
-
-  @Override
-  public void center() {
-    show();
-    closey.setFocus(true);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/FormatUtil.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/FormatUtil.java
deleted file mode 100644
index c8d052e..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/FormatUtil.java
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gerrit.client.change.Resources;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.info.GeneralPreferences;
-import com.google.gwt.i18n.client.NumberFormat;
-import java.util.Date;
-
-/** Misc. formatting functions. */
-public class FormatUtil {
-  private static DateFormatter dateFormatter;
-
-  public static void setPreferences(GeneralPreferences prefs) {
-    dateFormatter = new DateFormatter(prefs);
-  }
-
-  /** Format a date using a really short format. */
-  public static String shortFormat(Date dt) {
-    ensureInited();
-    return dateFormatter.shortFormat(dt);
-  }
-
-  /** Format a date using a really short format. */
-  public static String shortFormatDayTime(Date dt) {
-    ensureInited();
-    return dateFormatter.shortFormatDayTime(dt);
-  }
-
-  /** Format a date using the locale's medium length format. */
-  public static String mediumFormat(Date dt) {
-    ensureInited();
-    return dateFormatter.mediumFormat(dt);
-  }
-
-  private static void ensureInited() {
-    if (dateFormatter == null) {
-      setPreferences(Gerrit.getUserPreferences());
-    }
-  }
-
-  /** Format a date using git log's relative date format. */
-  public static String relativeFormat(Date dt) {
-    return RelativeDateFormatter.format(dt);
-  }
-
-  /**
-   * Formats an account as a name and an email address.
-   *
-   * <p>Example output:
-   *
-   * <ul>
-   *   <li>{@code A U. Thor &lt;author@example.com&gt;}: full populated
-   *   <li>{@code A U. Thor (12)}: missing email address
-   *   <li>{@code Anonymous Coward &lt;author@example.com&gt;}: missing name
-   *   <li>{@code Anonymous Coward (12)}: missing name and email address
-   * </ul>
-   */
-  public static String nameEmail(AccountInfo info) {
-    return createAccountFormatter().nameEmail(info);
-  }
-
-  /**
-   * Formats an account name.
-   *
-   * <p>If the account has a full name, it returns only the full name. Otherwise it returns a longer
-   * form that includes the email address.
-   */
-  public static String name(AccountInfo info) {
-    return createAccountFormatter().name(info);
-  }
-
-  private static AccountFormatter createAccountFormatter() {
-    return new AccountFormatter(Gerrit.info().user().anonymousCowardName());
-  }
-
-  /** The returned format string doesn't contain any +/- sign. */
-  public static String formatAbsBytes(long bytes) {
-    return formatBytes(bytes, true);
-  }
-
-  public static String formatBytes(long bytes) {
-    return formatBytes(bytes, false);
-  }
-
-  private static String formatBytes(long bytes, boolean abs) {
-    bytes = abs ? Math.abs(bytes) : bytes;
-
-    if (bytes == 0) {
-      return abs ? "0 B" : "+/- 0 B";
-    }
-
-    if (Math.abs(bytes) < 1024) {
-      return (bytes > 0 && !abs ? "+" : "") + bytes + " B";
-    }
-
-    int exp = (int) (Math.log(Math.abs(bytes)) / Math.log(1024));
-    return (bytes > 0 && !abs ? "+" : "")
-        + NumberFormat.getFormat("#.0").format(bytes / Math.pow(1024, exp))
-        + " "
-        + "KMGTPE".charAt(exp - 1)
-        + "iB";
-  }
-
-  public static String formatPercentage(long size, long delta) {
-    if (size == 0) {
-      return Resources.C.notAvailable();
-    }
-    return (delta > 0 ? "+" : "-") + formatAbsPercentage(size, delta);
-  }
-
-  public static String formatAbsPercentage(long size, long delta) {
-    if (size == 0) {
-      return Resources.C.notAvailable();
-    }
-    long percentage = Math.abs(Math.round(delta * 100.0 / size));
-    return percentage + "%";
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
deleted file mode 100644
index afc65c9..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
+++ /dev/null
@@ -1,1134 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import static com.google.gerrit.common.data.GlobalCapability.CREATE_GROUP;
-import static com.google.gerrit.common.data.GlobalCapability.CREATE_PROJECT;
-import static com.google.gerrit.common.data.GlobalCapability.VIEW_PLUGINS;
-import static com.google.gerrit.common.data.HostPageData.XSRF_COOKIE_NAME;
-
-import com.google.gerrit.client.account.AccountApi;
-import com.google.gerrit.client.account.AccountCapabilities;
-import com.google.gerrit.client.account.EditPreferences;
-import com.google.gerrit.client.admin.ProjectScreen;
-import com.google.gerrit.client.api.ApiGlue;
-import com.google.gerrit.client.api.PluginLoader;
-import com.google.gerrit.client.change.LocalComments;
-import com.google.gerrit.client.changes.ChangeListScreen;
-import com.google.gerrit.client.config.ConfigServerApi;
-import com.google.gerrit.client.documentation.DocInfo;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.info.AuthInfo;
-import com.google.gerrit.client.info.GeneralPreferences;
-import com.google.gerrit.client.info.ServerInfo;
-import com.google.gerrit.client.info.TopMenu;
-import com.google.gerrit.client.info.TopMenuItem;
-import com.google.gerrit.client.info.TopMenuList;
-import com.google.gerrit.client.rpc.CallbackGroup;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.LinkMenuBar;
-import com.google.gerrit.client.ui.LinkMenuItem;
-import com.google.gerrit.client.ui.MorphingTabPanel;
-import com.google.gerrit.client.ui.ProjectLinkMenuItem;
-import com.google.gerrit.client.ui.Screen;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.common.data.HostPageData;
-import com.google.gerrit.common.data.SystemInfoService;
-import com.google.gerrit.extensions.client.DiffPreferencesInfo;
-import com.google.gerrit.extensions.client.EditPreferencesInfo;
-import com.google.gerrit.extensions.client.GerritTopMenu;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.aria.client.Roles;
-import com.google.gwt.core.client.EntryPoint;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Document;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyDownEvent;
-import com.google.gwt.event.dom.client.KeyDownHandler;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.logical.shared.ValueChangeHandler;
-import com.google.gwt.event.shared.EventBus;
-import com.google.gwt.event.shared.SimpleEventBus;
-import com.google.gwt.http.client.Request;
-import com.google.gwt.http.client.RequestBuilder;
-import com.google.gwt.http.client.RequestCallback;
-import com.google.gwt.http.client.RequestException;
-import com.google.gwt.http.client.Response;
-import com.google.gwt.http.client.URL;
-import com.google.gwt.http.client.UrlBuilder;
-import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.Cookies;
-import com.google.gwt.user.client.History;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.Window.Location;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.FocusPanel;
-import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
-import com.google.gwt.user.client.ui.InlineHTML;
-import com.google.gwt.user.client.ui.InlineLabel;
-import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwtexpui.clippy.client.CopyableLabel;
-import com.google.gwtexpui.user.client.UserAgent;
-import com.google.gwtexpui.user.client.ViewSite;
-import com.google.gwtjsonrpc.client.JsonDefTarget;
-import com.google.gwtjsonrpc.client.JsonUtil;
-import com.google.gwtjsonrpc.client.XsrfManager;
-import com.google.gwtorm.client.KeyUtil;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class Gerrit implements EntryPoint {
-  public static final GerritConstants C = GWT.create(GerritConstants.class);
-  public static final GerritMessages M = GWT.create(GerritMessages.class);
-  public static final GerritResources RESOURCES = GWT.create(GerritResources.class);
-  public static final SystemInfoService SYSTEM_SVC;
-  public static final EventBus EVENT_BUS = GWT.create(SimpleEventBus.class);
-  public static final Themer THEMER = GWT.create(Themer.class);
-  public static final String PROJECT_NAME_MENU_VAR = "${projectName}";
-  public static final String INDEX = "Documentation/index.html";
-
-  private static String myHost;
-  private static ServerInfo myServerInfo;
-  private static AccountInfo myAccount;
-  private static GeneralPreferences myPrefs;
-  private static UrlAliasMatcher urlAliasMatcher;
-  private static boolean hasDocumentation;
-  private static boolean docSearch;
-  private static String docUrl;
-  private static HostPageData.Theme myTheme;
-  private static String defaultScreenToken;
-  private static DiffPreferencesInfo myAccountDiffPref;
-  private static EditPreferencesInfo editPrefs;
-  private static String xGerritAuth;
-  private static boolean isNoteDbEnabled;
-
-  private static Map<String, LinkMenuBar> menuBars;
-
-  private static MorphingTabPanel menuLeft;
-  private static LinkMenuBar menuRight;
-  private static RootPanel topMenu;
-  private static RootPanel siteHeader;
-  private static RootPanel siteFooter;
-  private static RootPanel bottomMenu;
-  private static SearchPanel searchPanel;
-  private static final Dispatcher dispatcher = new Dispatcher();
-  private static ViewSite<Screen> body;
-  private static String lastChangeListToken;
-  private static String lastViewToken;
-  private static Anchor uiSwitcherLink;
-
-  static {
-    SYSTEM_SVC = GWT.create(SystemInfoService.class);
-    JsonUtil.bind(SYSTEM_SVC, "rpc/SystemInfoService");
-  }
-
-  static void upgradeUI(String token) {
-    History.newItem(Dispatcher.RELOAD_UI + token, false);
-    Window.Location.reload();
-  }
-
-  public static void displayLastChangeList() {
-    if (lastChangeListToken != null) {
-      display(lastChangeListToken);
-    } else if (isSignedIn()) {
-      display(PageLinks.MINE);
-    } else {
-      display(PageLinks.toChangeQuery("status:open"));
-    }
-  }
-
-  public static String getPriorView() {
-    return lastViewToken;
-  }
-
-  /**
-   * Load the screen at the given location, displaying when ready.
-   *
-   * <p>If the URL is not already pointing at this location, a new item will be added to the
-   * browser's history when the screen is fully loaded and displayed on the UI.
-   *
-   * @param token location to parse, load, and render.
-   */
-  public static void display(String token) {
-    if (body.getView() == null || !body.getView().displayToken(token)) {
-      dispatcher.display(token);
-      updateUiLink(token);
-    }
-  }
-
-  /**
-   * Load the screen passed, assuming token can be used to locate it.
-   *
-   * <p>The screen is loaded in the background. When it is ready to be visible a new item will be
-   * added to the browser's history, the screen will be made visible, and the window title may be
-   * updated.
-   *
-   * <p>If {@link Screen#isRequiresSignIn()} is true and the user is not signed in yet the screen
-   * instance will be discarded, sign-in will take place, and will redirect to this location upon
-   * success.
-   *
-   * @param token location that refers to {@code view}.
-   * @param view the view to load.
-   */
-  public static void display(String token, Screen view) {
-    if (view.isRequiresSignIn() && !isSignedIn()) {
-      doSignIn(token);
-    } else {
-      view.setToken(token);
-      if (isSignedIn()) {
-        LocalComments.saveInlineComments();
-      }
-      body.setView(view);
-      updateUiLink(token);
-    }
-  }
-
-  public static void selectMenu(LinkMenuBar bar) {
-    menuLeft.selectTab(menuLeft.getWidgetIndex(bar));
-  }
-
-  /**
-   * Update the current history token after a screen change.
-   *
-   * <p>The caller has already updated the UI, but wants to publish a different history token for
-   * the current browser state. This really only makes sense if the caller is a {@code TabPanel} and
-   * is firing an event when the tab changed to a different part.
-   *
-   * @param token new location that is already visible.
-   */
-  public static void updateImpl(String token) {
-    History.newItem(token, false);
-    dispatchHistoryHooks(token);
-  }
-
-  public static void setQueryString(String query) {
-    searchPanel.setText(query);
-  }
-
-  public static void setWindowTitle(Screen screen, String text) {
-    if (screen == body.getView()) {
-      if (text == null || text.length() == 0) {
-        Window.setTitle(M.windowTitle1(myHost));
-      } else {
-        Window.setTitle(M.windowTitle2(text, myHost));
-      }
-    }
-  }
-
-  public static int getHeaderFooterHeight() {
-    int h = bottomMenu.getOffsetHeight();
-    if (topMenu.isVisible()) {
-      h += topMenu.getOffsetHeight();
-    }
-    if (siteHeader.isVisible()) {
-      h += siteHeader.getOffsetHeight();
-    }
-    if (siteFooter.isVisible()) {
-      h += siteFooter.getOffsetHeight();
-    }
-    return h;
-  }
-
-  public static void setHeaderVisible(boolean visible) {
-    topMenu.setVisible(visible);
-    siteHeader.setVisible(visible && getUserPreferences().showSiteHeader());
-  }
-
-  public static boolean isHeaderVisible() {
-    return topMenu.isVisible();
-  }
-
-  public static String getDefaultScreenToken() {
-    return defaultScreenToken;
-  }
-
-  public static RootPanel getBottomMenu() {
-    return bottomMenu;
-  }
-
-  /** Get the public configuration data used by this Gerrit instance. */
-  public static ServerInfo info() {
-    return myServerInfo;
-  }
-
-  public static UrlAliasMatcher getUrlAliasMatcher() {
-    return urlAliasMatcher;
-  }
-
-  /** Site theme information (site specific colors)/ */
-  public static HostPageData.Theme getTheme() {
-    return myTheme;
-  }
-
-  /** @return the currently signed in user's account data; empty account data if no account */
-  public static AccountInfo getUserAccount() {
-    return myAccount;
-  }
-
-  /** @return access token to prove user identity during REST API calls. */
-  @Nullable
-  public static String getXGerritAuth() {
-    return xGerritAuth;
-  }
-
-  /**
-   * @return the preferences of the currently signed in user, the default preferences if not signed
-   *     in
-   */
-  public static GeneralPreferences getUserPreferences() {
-    return myPrefs;
-  }
-
-  /** @return the currently signed in users's diff preferences, or default values */
-  public static DiffPreferencesInfo getDiffPreferences() {
-    return myAccountDiffPref;
-  }
-
-  public static void setDiffPreferences(DiffPreferencesInfo accountDiffPref) {
-    myAccountDiffPref = accountDiffPref;
-  }
-
-  /** @return the edit preferences of the current user, null if not signed-in */
-  public static EditPreferencesInfo getEditPreferences() {
-    return editPrefs;
-  }
-
-  public static void setEditPreferences(EditPreferencesInfo p) {
-    editPrefs = p;
-  }
-
-  /** @return true if the user is currently authenticated */
-  public static boolean isSignedIn() {
-    return xGerritAuth != null;
-  }
-
-  /** Sign the user into the application. */
-  public static void doSignIn(String token) {
-    Location.assign(loginRedirect(token));
-  }
-
-  public static boolean isNoteDbEnabled() {
-    return isNoteDbEnabled;
-  }
-
-  public static String loginRedirect(String token) {
-    if (token == null) {
-      token = "";
-    } else if (token.startsWith("/")) {
-      token = token.substring(1);
-    }
-
-    return selfRedirect("login/") + URL.encodePathSegment("#/" + token);
-  }
-
-  public static String selfRedirect(String suffix) {
-    // Clean up the path. Users seem to like putting extra slashes into the URL
-    // which can break redirections by misinterpreting at either client or server.
-    String path = Location.getPath();
-    if (path == null || path.isEmpty()) {
-      path = "/";
-    } else {
-      while (path.startsWith("//")) {
-        path = path.substring(1);
-      }
-      while (path.endsWith("//")) {
-        path = path.substring(0, path.length() - 1);
-      }
-      if (!path.endsWith("/")) {
-        path = path + "/";
-      }
-    }
-
-    if (suffix != null) {
-      while (suffix.startsWith("/")) {
-        suffix = suffix.substring(1);
-      }
-      path += suffix;
-    }
-
-    UrlBuilder builder = new UrlBuilder();
-    builder.setProtocol(Location.getProtocol());
-    builder.setHost(Location.getHost());
-    String port = Location.getPort();
-    if (port != null && !port.isEmpty()) {
-      builder.setPort(Integer.parseInt(port));
-    }
-    builder.setPath(path);
-    return builder.buildString();
-  }
-
-  static void deleteSessionCookie() {
-    myAccount = AccountInfo.create(0, null, null, null);
-    myAccountDiffPref = null;
-    editPrefs = null;
-    myPrefs = GeneralPreferences.createDefault();
-    urlAliasMatcher.clearUserAliases();
-    xGerritAuth = null;
-    refreshMenuBar();
-
-    // If the cookie was HttpOnly, this request to delete it will
-    // most likely not be successful.  We can try anyway though.
-    //
-    Cookies.removeCookie("GerritAccount");
-  }
-
-  private void setXsrfToken() {
-    xGerritAuth = Cookies.getCookie(XSRF_COOKIE_NAME);
-    JsonUtil.setDefaultXsrfManager(
-        new XsrfManager() {
-          @Override
-          public String getToken(JsonDefTarget proxy) {
-            return xGerritAuth;
-          }
-
-          @Override
-          public void setToken(JsonDefTarget proxy, String token) {
-            // Ignore the request, we always rely upon the cookie.
-          }
-        });
-  }
-
-  @Override
-  public void onModuleLoad() {
-    if (!canLoadInIFrame()) {
-      UserAgent.assertNotInIFrame();
-    }
-    setXsrfToken();
-
-    KeyUtil.setEncoderImpl(
-        new KeyUtil.Encoder() {
-          @Override
-          public String encode(String e) {
-            e = URL.encodeQueryString(e);
-            e = fixPathImpl(e);
-            e = fixColonImpl(e);
-            e = fixDoubleQuote(e);
-            return e;
-          }
-
-          @Override
-          public String decode(String e) {
-            return URL.decodeQueryString(e);
-          }
-
-          private native String fixPathImpl(String path)
-              /*-{ return path.replace(/%2F/g, "/"); }-*/ ;
-
-          private native String fixColonImpl(String path)
-              /*-{ return path.replace(/%3A/g, ":"); }-*/ ;
-
-          private native String fixDoubleQuote(String path)
-              /*-{ return path.replace(/%22/g, '"'); }-*/ ;
-        });
-
-    initHostname();
-    Window.setTitle(M.windowTitle1(myHost));
-
-    RpcStatus.INSTANCE = new RpcStatus();
-    CallbackGroup cbg = new CallbackGroup();
-    getDocIndex(
-        cbg.add(
-            new GerritCallback<DocInfo>() {
-              @Override
-              public void onSuccess(DocInfo indexInfo) {
-                hasDocumentation = indexInfo != null;
-                docUrl = selfRedirect("/Documentation/");
-              }
-            }));
-    ConfigServerApi.serverInfo(
-        cbg.add(
-            new GerritCallback<ServerInfo>() {
-              @Override
-              public void onSuccess(ServerInfo info) {
-                myServerInfo = info;
-                urlAliasMatcher = new UrlAliasMatcher(info.urlAliases());
-                String du = info.gerrit().docUrl();
-                if (du != null && !du.isEmpty()) {
-                  hasDocumentation = true;
-                  docUrl = du;
-                }
-                docSearch = info.gerrit().docSearch();
-              }
-            }));
-    HostPageDataService hpd = GWT.create(HostPageDataService.class);
-    hpd.load(
-        cbg.addFinal(
-            new GerritCallback<HostPageData>() {
-              @Override
-              public void onSuccess(HostPageData result) {
-                Document.get().getElementById("gerrit_hostpagedata").removeFromParent();
-                myTheme = result.theme;
-                isNoteDbEnabled = result.isNoteDbEnabled;
-                if (result.accountDiffPref != null) {
-                  myAccountDiffPref = result.accountDiffPref;
-                }
-                if (result.accountDiffPref != null) {
-                  // TODO: Support options on the GetDetail REST endpoint so that it can
-                  // also return the preferences. Then we can fetch everything with a
-                  // single request and we don't need the callback group anymore.
-                  CallbackGroup cbg = new CallbackGroup();
-                  AccountApi.self()
-                      .view("detail")
-                      .get(
-                          cbg.add(
-                              new GerritCallback<AccountInfo>() {
-                                @Override
-                                public void onSuccess(AccountInfo result) {
-                                  myAccount = result;
-                                }
-                              }));
-                  AccountApi.self()
-                      .view("preferences")
-                      .get(
-                          cbg.add(
-                              new GerritCallback<GeneralPreferences>() {
-                                @Override
-                                public void onSuccess(GeneralPreferences prefs) {
-                                  myPrefs = prefs;
-                                  onModuleLoad2(result);
-                                }
-                              }));
-                  AccountApi.getEditPreferences(
-                      cbg.addFinal(
-                          new GerritCallback<EditPreferences>() {
-                            @Override
-                            public void onSuccess(EditPreferences prefs) {
-                              EditPreferencesInfo prefsInfo = new EditPreferencesInfo();
-                              prefs.copyTo(prefsInfo);
-                              editPrefs = prefsInfo;
-                            }
-                          }));
-                } else {
-                  myAccount = AccountInfo.create(0, null, null, null);
-                  myPrefs = GeneralPreferences.createDefault();
-                  editPrefs = null;
-                  onModuleLoad2(result);
-                }
-              }
-            }));
-  }
-
-  private native boolean canLoadInIFrame() /*-{
-    return $wnd.gerrit_hostpagedata.canLoadInIFrame || false;
-  }-*/;
-
-  private static void initHostname() {
-    myHost = Location.getHostName();
-    final int d1 = myHost.indexOf('.');
-    if (d1 < 0) {
-      return;
-    }
-    final int d2 = myHost.indexOf('.', d1 + 1);
-    if (d2 >= 0) {
-      myHost = myHost.substring(0, d2);
-    }
-  }
-
-  private static void dispatchHistoryHooks(String token) {
-    ApiGlue.fireEvent("history", token);
-  }
-
-  private static String getUiSwitcherUrl(String token) {
-    UrlBuilder builder = new UrlBuilder();
-    builder.setProtocol(Location.getProtocol());
-    builder.setHost(Location.getHost());
-    String port = Location.getPort();
-    if (port != null && !port.isEmpty()) {
-      builder.setPort(Integer.parseInt(port));
-    }
-    String[] tokens = token.split("@", 2);
-    if (Location.getPath().endsWith("/") && tokens[0].startsWith("/")) {
-      tokens[0] = tokens[0].substring(1);
-    }
-    if (tokens[0].startsWith("projects/") && tokens[0].contains(",dashboards/")) {
-      // Rewrite project dashboard URIs to a new format, because otherwise
-      // "/projects/..." would be served as an API request.
-      tokens[0] = "p/" + tokens[0].substring("projects/".length());
-      tokens[0] = tokens[0].replace(",dashboards/", "/+/dashboard/");
-    }
-    builder.setPath(Location.getPath() + tokens[0]);
-    if (tokens.length == 2) {
-      builder.setHash(tokens[1]);
-    }
-    builder.setParameter("polygerrit", "1");
-    return builder.buildString();
-  }
-
-  private static void populateBottomMenu(RootPanel btmmenu, HostPageData hpd) {
-    String vs = hpd.version;
-    if (vs == null || vs.isEmpty()) {
-      vs = "dev";
-    }
-
-    btmmenu.add(new InlineHTML(M.poweredBy(vs)));
-
-    btmmenu.add(new InlineLabel(" | "));
-    uiSwitcherLink = new Anchor(C.newUi(), getUiSwitcherUrl(History.getToken()));
-    uiSwitcherLink.setStyleName("");
-    btmmenu.add(uiSwitcherLink);
-
-    String reportBugUrl = info().gerrit().reportBugUrl();
-    if (reportBugUrl != null) {
-      String reportBugText = info().gerrit().reportBugText();
-      Anchor a = new Anchor(reportBugText == null ? C.reportBug() : reportBugText, reportBugUrl);
-      a.setTarget("_blank");
-      a.setStyleName("");
-      btmmenu.add(new InlineLabel(" | "));
-      btmmenu.add(a);
-    }
-    btmmenu.add(new InlineLabel(" | "));
-    btmmenu.add(new InlineLabel(C.keyHelp()));
-  }
-
-  private static void updateUiLink(String token) {
-    if (uiSwitcherLink != null) {
-      uiSwitcherLink.setHref(getUiSwitcherUrl(token));
-    }
-  }
-
-  private void onModuleLoad2(HostPageData hpd) {
-    RESOURCES.gwt_override().ensureInjected();
-    RESOURCES.css().ensureInjected();
-
-    topMenu = RootPanel.get("gerrit_topmenu");
-    final RootPanel gStarting = RootPanel.get("gerrit_startinggerrit");
-    final RootPanel gBody = RootPanel.get("gerrit_body");
-    bottomMenu = RootPanel.get("gerrit_btmmenu");
-
-    topMenu.setStyleName(RESOURCES.css().gerritTopMenu());
-    gBody.setStyleName(RESOURCES.css().gerritBody());
-
-    final Grid menuLine = new Grid(1, 3);
-    menuLeft = new MorphingTabPanel();
-    menuRight = new LinkMenuBar();
-    searchPanel = new SearchPanel();
-    menuLeft.setStyleName(RESOURCES.css().topmenuMenuLeft());
-    menuLine.setStyleName(RESOURCES.css().topmenu());
-    topMenu.add(menuLine);
-    final FlowPanel menuRightPanel = new FlowPanel();
-    menuRightPanel.setStyleName(RESOURCES.css().topmenuMenuRight());
-    menuRightPanel.add(searchPanel);
-    menuRightPanel.add(menuRight);
-    menuLine.setWidget(0, 0, menuLeft);
-    menuLine.setWidget(0, 1, new FlowPanel());
-    menuLine.setWidget(0, 2, menuRightPanel);
-    final CellFormatter fmt = menuLine.getCellFormatter();
-    fmt.setStyleName(0, 0, RESOURCES.css().topmenuTDmenu());
-    fmt.setStyleName(0, 1, RESOURCES.css().topmenuTDglue());
-    fmt.setStyleName(0, 2, RESOURCES.css().topmenuTDmenu());
-
-    siteHeader = RootPanel.get("gerrit_header");
-    siteFooter = RootPanel.get("gerrit_footer");
-
-    body =
-        new ViewSite<Screen>() {
-          @Override
-          protected void onShowView(Screen view) {
-            String token = view.getToken();
-            History.newItem(token, false);
-            dispatchHistoryHooks(token);
-
-            if (view instanceof ChangeListScreen) {
-              lastChangeListToken = token;
-            }
-
-            super.onShowView(view);
-            view.onShowView();
-            lastViewToken = token;
-          }
-        };
-    gBody.add(body);
-
-    JsonUtil.addRpcStartHandler(RpcStatus.INSTANCE);
-    JsonUtil.addRpcCompleteHandler(RpcStatus.INSTANCE);
-
-    gStarting.getElement().getParentElement().removeChild(gStarting.getElement());
-    RootPanel.detachNow(gStarting);
-    ApiGlue.init();
-
-    applyUserPreferences();
-    populateBottomMenu(bottomMenu, hpd);
-    refreshMenuBar();
-
-    History.addValueChangeHandler(
-        new ValueChangeHandler<String>() {
-          @Override
-          public void onValueChange(ValueChangeEvent<String> event) {
-            display(event.getValue());
-          }
-        });
-    JumpKeys.register(body);
-
-    saveDefaultTheme();
-    if (hpd.messages != null) {
-      new MessageOfTheDayBar(hpd.messages).show();
-    }
-    PluginLoader.load(
-        hpd.plugins,
-        hpd.pluginsLoadTimeout,
-        new GerritCallback<VoidResult>() {
-          @Override
-          public void onSuccess(VoidResult result) {
-            String token = History.getToken();
-            if (token.isEmpty()) {
-              token = isSignedIn() ? PageLinks.MINE : PageLinks.toChangeQuery("status:open");
-            }
-            display(token);
-          }
-        });
-  }
-
-  private void saveDefaultTheme() {
-    THEMER.init(
-        Document.get().getElementById("gerrit_sitecss"),
-        Document.get().getElementById("gerrit_header"),
-        Document.get().getElementById("gerrit_footer"));
-  }
-
-  public static void refreshMenuBar() {
-    menuLeft.clear();
-    menuRight.clear();
-
-    menuBars = new HashMap<>();
-
-    boolean signedIn = isSignedIn();
-    AuthInfo authInfo = info().auth();
-    LinkMenuBar m;
-
-    m = new LinkMenuBar();
-    menuBars.put(GerritTopMenu.ALL.menuName, m);
-    addLink(m, C.menuAllOpen(), PageLinks.toChangeQuery("status:open"));
-    addLink(m, C.menuAllMerged(), PageLinks.toChangeQuery("status:merged"));
-    addLink(m, C.menuAllAbandoned(), PageLinks.toChangeQuery("status:abandoned"));
-    menuLeft.add(m, C.menuAll());
-
-    if (signedIn) {
-      LinkMenuBar myBar = new LinkMenuBar();
-      menuBars.put(GerritTopMenu.MY.menuName, myBar);
-
-      if (myPrefs.my() != null) {
-        myBar.clear();
-        String url = null;
-        List<TopMenuItem> myMenuItems = Natives.asList(myPrefs.my());
-        if (!myMenuItems.isEmpty()) {
-          if (myMenuItems.get(0).getUrl().startsWith("#")) {
-            url = myMenuItems.get(0).getUrl().substring(1);
-          }
-          for (TopMenuItem item : myMenuItems) {
-            addExtensionLink(myBar, item);
-          }
-        }
-        defaultScreenToken = url;
-      }
-
-      menuLeft.add(myBar, C.menuMine());
-      menuLeft.selectTab(1);
-    } else {
-      menuLeft.selectTab(0);
-    }
-
-    final LinkMenuBar projectsBar = new LinkMenuBar();
-    menuBars.put(GerritTopMenu.PROJECTS.menuName, projectsBar);
-    addLink(projectsBar, C.menuProjectsList(), PageLinks.ADMIN_PROJECTS);
-    projectsBar.addItem(new ProjectLinkMenuItem(C.menuProjectsInfo(), ProjectScreen.INFO));
-    projectsBar.addItem(new ProjectLinkMenuItem(C.menuProjectsBranches(), ProjectScreen.BRANCHES));
-    projectsBar.addItem(new ProjectLinkMenuItem(C.menuProjectsTags(), ProjectScreen.TAGS));
-    projectsBar.addItem(new ProjectLinkMenuItem(C.menuProjectsAccess(), ProjectScreen.ACCESS));
-    final LinkMenuItem dashboardsMenuItem =
-        new ProjectLinkMenuItem(C.menuProjectsDashboards(), ProjectScreen.DASHBOARDS) {
-          @Override
-          protected boolean match(String token) {
-            return super.match(token)
-                || (!getTargetHistoryToken().isEmpty()
-                    && ("/admin" + token).startsWith(getTargetHistoryToken()));
-          }
-        };
-    projectsBar.addItem(dashboardsMenuItem);
-    menuLeft.add(projectsBar, C.menuProjects());
-
-    if (signedIn) {
-      final LinkMenuBar peopleBar = new LinkMenuBar();
-      menuBars.put(GerritTopMenu.PEOPLE.menuName, peopleBar);
-      final LinkMenuItem groupsListMenuItem =
-          addLink(peopleBar, C.menuPeopleGroupsList(), PageLinks.ADMIN_GROUPS);
-      menuLeft.add(peopleBar, C.menuPeople());
-
-      final LinkMenuBar pluginsBar = new LinkMenuBar();
-      menuBars.put(GerritTopMenu.PLUGINS.menuName, pluginsBar);
-      AccountCapabilities.all(
-          new GerritCallback<AccountCapabilities>() {
-            @Override
-            public void onSuccess(AccountCapabilities result) {
-              if (result.canPerform(CREATE_PROJECT)) {
-                insertLink(
-                    projectsBar,
-                    C.menuProjectsCreate(),
-                    PageLinks.ADMIN_CREATE_PROJECT,
-                    projectsBar.getWidgetIndex(dashboardsMenuItem) + 1);
-              }
-              if (result.canPerform(CREATE_GROUP)) {
-                insertLink(
-                    peopleBar,
-                    C.menuPeopleGroupsCreate(),
-                    PageLinks.ADMIN_CREATE_GROUP,
-                    peopleBar.getWidgetIndex(groupsListMenuItem) + 1);
-              }
-              if (result.canPerform(VIEW_PLUGINS)) {
-                insertLink(pluginsBar, C.menuPluginsInstalled(), PageLinks.ADMIN_PLUGINS, 0);
-                menuLeft.insert(
-                    pluginsBar, C.menuPlugins(), menuLeft.getWidgetIndex(peopleBar) + 1);
-              }
-            }
-          },
-          CREATE_PROJECT,
-          CREATE_GROUP,
-          VIEW_PLUGINS);
-    }
-
-    if (hasDocumentation) {
-      m = new LinkMenuBar();
-      menuBars.put(GerritTopMenu.DOCUMENTATION.menuName, m);
-      addDocLink(m, C.menuDocumentationTOC(), "index.html");
-      addDocLink(m, C.menuDocumentationSearch(), "user-search.html");
-      addDocLink(m, C.menuDocumentationUpload(), "user-upload.html");
-      addDocLink(m, C.menuDocumentationAccess(), "access-control.html");
-      addDocLink(m, C.menuDocumentationAPI(), "rest-api.html");
-      addDocLink(m, C.menuDocumentationProjectOwnerGuide(), "intro-project-owner.html");
-      menuLeft.add(m, C.menuDocumentation());
-    }
-
-    if (signedIn) {
-      whoAmI(!authInfo.isClientSslCertLdap());
-    } else {
-      switch (authInfo.authType()) {
-        case CLIENT_SSL_CERT_LDAP:
-          break;
-
-        case OPENID:
-          menuRight.addItem(
-              C.menuRegister(),
-              new Command() {
-                @Override
-                public void execute() {
-                  String t = History.getToken();
-                  if (t == null) {
-                    t = "";
-                  }
-                  doSignIn(PageLinks.REGISTER + t);
-                }
-              });
-          menuRight.addItem(
-              C.menuSignIn(),
-              new Command() {
-                @Override
-                public void execute() {
-                  doSignIn(History.getToken());
-                }
-              });
-          break;
-
-        case OAUTH:
-          menuRight.addItem(
-              C.menuSignIn(),
-              new Command() {
-                @Override
-                public void execute() {
-                  doSignIn(History.getToken());
-                }
-              });
-          break;
-
-        case OPENID_SSO:
-          menuRight.addItem(
-              C.menuSignIn(),
-              new Command() {
-                @Override
-                public void execute() {
-                  doSignIn(History.getToken());
-                }
-              });
-          break;
-
-        case HTTP:
-        case HTTP_LDAP:
-          if (authInfo.loginUrl() != null) {
-            String signinText =
-                authInfo.loginText() == null ? C.menuSignIn() : authInfo.loginText();
-            menuRight.add(anchor(signinText, authInfo.loginUrl()));
-          }
-          break;
-
-        case LDAP:
-        case LDAP_BIND:
-        case CUSTOM_EXTENSION:
-          if (authInfo.registerUrl() != null) {
-            String registerText =
-                authInfo.registerText() == null ? C.menuRegister() : authInfo.registerText();
-            menuRight.add(anchor(registerText, authInfo.registerUrl()));
-          }
-          menuRight.addItem(
-              C.menuSignIn(),
-              new Command() {
-                @Override
-                public void execute() {
-                  doSignIn(History.getToken());
-                }
-              });
-          break;
-
-        case DEVELOPMENT_BECOME_ANY_ACCOUNT:
-          menuRight.add(anchor("Become", loginRedirect("")));
-          break;
-      }
-    }
-    ConfigServerApi.topMenus(
-        new GerritCallback<TopMenuList>() {
-          @Override
-          public void onSuccess(TopMenuList result) {
-            List<TopMenu> topMenuExtensions = Natives.asList(result);
-            for (TopMenu menu : topMenuExtensions) {
-              String name = menu.getName();
-              LinkMenuBar existingBar = menuBars.get(name);
-              LinkMenuBar bar = existingBar != null ? existingBar : new LinkMenuBar();
-              for (TopMenuItem item : Natives.asList(menu.getItems())) {
-                addMenuLink(bar, item);
-              }
-              if (existingBar == null) {
-                menuBars.put(name, bar);
-                menuLeft.add(bar, name);
-              }
-            }
-          }
-        });
-  }
-
-  public static void refreshUserPreferences() {
-    if (isSignedIn()) {
-      AccountApi.self()
-          .view("preferences")
-          .get(
-              new GerritCallback<GeneralPreferences>() {
-                @Override
-                public void onSuccess(GeneralPreferences prefs) {
-                  setUserPreferences(prefs);
-                }
-              });
-    } else {
-      setUserPreferences(GeneralPreferences.createDefault());
-    }
-  }
-
-  public static void setUserPreferences(GeneralPreferences prefs) {
-    myPrefs = prefs;
-    applyUserPreferences();
-    refreshMenuBar();
-  }
-
-  private static void applyUserPreferences() {
-    CopyableLabel.setFlashEnabled(myPrefs.useFlashClipboard());
-    if (siteHeader != null) {
-      siteHeader.setVisible(myPrefs.showSiteHeader());
-    }
-    if (siteFooter != null) {
-      siteFooter.setVisible(myPrefs.showSiteHeader());
-    }
-    FormatUtil.setPreferences(myPrefs);
-    urlAliasMatcher.updateUserAliases(myPrefs.urlAliases());
-  }
-
-  public static boolean hasDocSearch() {
-    return docSearch;
-  }
-
-  private static void getDocIndex(AsyncCallback<DocInfo> cb) {
-    RequestBuilder req = new RequestBuilder(RequestBuilder.HEAD, GWT.getHostPageBaseURL() + INDEX);
-    req.setCallback(
-        new RequestCallback() {
-          @Override
-          public void onResponseReceived(Request req, Response resp) {
-            switch (resp.getStatusCode()) {
-              case Response.SC_OK:
-              case Response.SC_MOVED_PERMANENTLY:
-              case Response.SC_MOVED_TEMPORARILY:
-                cb.onSuccess(DocInfo.create());
-                break;
-              default:
-                cb.onSuccess(null);
-                break;
-            }
-          }
-
-          @Override
-          public void onError(Request request, Throwable e) {
-            cb.onFailure(e);
-          }
-        });
-    try {
-      req.send();
-    } catch (RequestException e) {
-      cb.onFailure(e);
-    }
-  }
-
-  private static void whoAmI(boolean canLogOut) {
-    AccountInfo account = getUserAccount();
-    final UserPopupPanel userPopup = new UserPopupPanel(account, canLogOut, true);
-    final FlowPanel userSummaryPanel = new FlowPanel();
-    class PopupHandler implements KeyDownHandler, ClickHandler {
-      private void showHidePopup() {
-        if (userPopup.isShowing() && userPopup.isVisible()) {
-          userPopup.hide();
-        } else {
-          userPopup.showRelativeTo(userSummaryPanel);
-        }
-      }
-
-      @Override
-      public void onClick(ClickEvent event) {
-        showHidePopup();
-      }
-
-      @Override
-      public void onKeyDown(KeyDownEvent event) {
-        if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
-          showHidePopup();
-          event.preventDefault();
-        }
-      }
-    }
-    final PopupHandler popupHandler = new PopupHandler();
-    final InlineLabel l = new InlineLabel(FormatUtil.name(account));
-    l.setStyleName(RESOURCES.css().menuBarUserName());
-    final AvatarImage avatar = new AvatarImage(account, 26, false);
-    avatar.setStyleName(RESOURCES.css().menuBarUserNameAvatar());
-    userSummaryPanel.setStyleName(RESOURCES.css().menuBarUserNamePanel());
-    userSummaryPanel.add(l);
-    userSummaryPanel.add(avatar);
-    // "BLACK DOWN-POINTING SMALL TRIANGLE"
-    userSummaryPanel.add(new InlineLabel(" \u25be"));
-    userPopup.addAutoHidePartner(userSummaryPanel.getElement());
-    FocusPanel fp = new FocusPanel(userSummaryPanel);
-    fp.setStyleName(RESOURCES.css().menuBarUserNameFocusPanel());
-    fp.addKeyDownHandler(popupHandler);
-    fp.addClickHandler(popupHandler);
-    menuRight.add(fp);
-  }
-
-  private static Anchor anchor(String text, String to) {
-    final Anchor a = new Anchor(text, to);
-    a.setStyleName(RESOURCES.css().menuItem());
-    Roles.getMenuitemRole().set(a.getElement());
-    return a;
-  }
-
-  private static LinkMenuItem addLink(final LinkMenuBar m, String text, String historyToken) {
-    LinkMenuItem i = new LinkMenuItem(text, historyToken);
-    m.addItem(i);
-    return i;
-  }
-
-  private static void insertLink(
-      final LinkMenuBar m, String text, String historyToken, int beforeIndex) {
-    m.insertItem(new LinkMenuItem(text, historyToken), beforeIndex);
-  }
-
-  private static LinkMenuItem addProjectLink(LinkMenuBar m, TopMenuItem item) {
-    LinkMenuItem i =
-        new ProjectLinkMenuItem(item.getName(), item.getUrl()) {
-          @Override
-          protected void onScreenLoad(Project.NameKey project) {
-            String p = panel.replace(PROJECT_NAME_MENU_VAR, URL.encodeQueryString(project.get()));
-            if (!panel.startsWith("/x/") && !isAbsolute(panel)) {
-              UrlBuilder builder = new UrlBuilder();
-              builder.setProtocol(Location.getProtocol());
-              builder.setHost(Location.getHost());
-              String port = Location.getPort();
-              if (port != null && !port.isEmpty()) {
-                builder.setPort(Integer.parseInt(port));
-              }
-              builder.setPath(Location.getPath());
-              p = builder.buildString() + p;
-            }
-            getElement().setPropertyString("href", p);
-          }
-
-          @Override
-          public void go() {
-            String href = getElement().getPropertyString("href");
-            if (href.startsWith("#")) {
-              super.go();
-            } else {
-              Window.open(href, getElement().getPropertyString("target"), "");
-            }
-          }
-        };
-    if (item.getTarget() != null && !item.getTarget().isEmpty()) {
-      i.getElement().setAttribute("target", item.getTarget());
-    }
-    if (item.getId() != null) {
-      i.getElement().setAttribute("id", item.getId());
-    }
-    m.addItem(i);
-    return i;
-  }
-
-  private static void addDocLink(LinkMenuBar m, String text, String href) {
-    final Anchor atag = anchor(text, docUrl + href);
-    atag.setTarget("_blank");
-    m.add(atag);
-  }
-
-  private static void addMenuLink(LinkMenuBar m, TopMenuItem item) {
-    if (item.getUrl().contains(PROJECT_NAME_MENU_VAR)) {
-      addProjectLink(m, item);
-    } else {
-      addExtensionLink(m, item);
-    }
-  }
-
-  private static void addExtensionLink(LinkMenuBar m, TopMenuItem item) {
-    if (item.getUrl().startsWith("#") && (item.getTarget() == null || item.getTarget().isEmpty())) {
-      LinkMenuItem a = new LinkMenuItem(item.getName(), item.getUrl().substring(1));
-      if (item.getId() != null) {
-        a.getElement().setAttribute("id", item.getId());
-      }
-      m.addItem(a);
-    } else {
-      Anchor atag =
-          anchor(
-              item.getName(),
-              isAbsolute(item.getUrl()) ? item.getUrl() : selfRedirect(item.getUrl()));
-      if (item.getTarget() != null && !item.getTarget().isEmpty()) {
-        atag.setTarget(item.getTarget());
-      }
-      if (item.getId() != null) {
-        atag.getElement().setAttribute("id", item.getId());
-      }
-      m.add(atag);
-    }
-  }
-
-  private static boolean isAbsolute(String url) {
-    return url.matches("^https?://.*");
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java
deleted file mode 100644
index eae3431..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gwt.i18n.client.Constants;
-
-public interface GerritConstants extends Constants {
-  String menuSignIn();
-
-  String menuRegister();
-
-  String reportBug();
-
-  String loadingPlugins();
-
-  String signInDialogTitle();
-
-  String signInDialogGoAnonymous();
-
-  String linkIdentityDialogTitle();
-
-  String registerDialogTitle();
-
-  String loginTypeUnsupported();
-
-  String errorTitle();
-
-  String errorDialogContinue();
-
-  String warnTitle();
-
-  String confirmationDialogOk();
-
-  String confirmationDialogCancel();
-
-  String branchCreationDialogTitle();
-
-  String branchCreationConfirmationMessage();
-
-  String tagCreationDialogTitle();
-
-  String tagCreationConfirmationMessage();
-
-  String branchDeletionDialogTitle();
-
-  String branchDeletionConfirmationMessage();
-
-  String tagDeletionDialogTitle();
-
-  String tagDeletionConfirmationMessage();
-
-  String newUi();
-
-  String notSignedInTitle();
-
-  String notSignedInBody();
-
-  String notFoundTitle();
-
-  String notFoundBody();
-
-  String noSuchAccountTitle();
-
-  String noSuchGroupTitle();
-
-  String inactiveAccountBody();
-
-  String labelNotApplicable();
-
-  String menuAll();
-
-  String menuAllOpen();
-
-  String menuAllMerged();
-
-  String menuAllAbandoned();
-
-  String menuMine();
-
-  String menuMyChanges();
-
-  String menuMyWatchedChanges();
-
-  String menuMyStarredChanges();
-
-  String menuMyDraftComments();
-
-  String menuDiff();
-
-  String menuDiffCommit();
-
-  String menuDiffPreferences();
-
-  String menuDiffPatchSets();
-
-  String menuDiffFiles();
-
-  String menuProjects();
-
-  String menuProjectsList();
-
-  String menuProjectsInfo();
-
-  String menuProjectsBranches();
-
-  String menuProjectsTags();
-
-  String menuProjectsAccess();
-
-  String menuProjectsDashboards();
-
-  String menuProjectsCreate();
-
-  String menuPeople();
-
-  String menuPeopleGroupsList();
-
-  String menuPeopleGroupsCreate();
-
-  String menuPlugins();
-
-  String menuPluginsInstalled();
-
-  String menuDocumentation();
-
-  String menuDocumentationTOC();
-
-  String menuDocumentationSearch();
-
-  String menuDocumentationUpload();
-
-  String menuDocumentationAccess();
-
-  String menuDocumentationAPI();
-
-  String menuDocumentationProjectOwnerGuide();
-
-  String searchHint();
-
-  String searchButton();
-
-  String rpcStatusWorking();
-
-  String sectionNavigation();
-
-  String sectionActions();
-
-  String keySearch();
-
-  String keyEditor();
-
-  String keyHelp();
-
-  String sectionJumping();
-
-  String jumpAllOpen();
-
-  String jumpAllMerged();
-
-  String jumpAllAbandoned();
-
-  String jumpMine();
-
-  String jumpMineWatched();
-
-  String jumpMineStarred();
-
-  String jumpMineDraftComments();
-
-  String projectAccessError();
-
-  String projectAccessProposeForReviewHint();
-
-  String userCannotVoteToolTip();
-
-  String stringListPanelAdd();
-
-  String stringListPanelDelete();
-
-  String stringListPanelUp();
-
-  String stringListPanelDown();
-
-  String searchDropdownChanges();
-
-  String searchDropdownDoc();
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties
deleted file mode 100644
index 2819d22..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties
+++ /dev/null
@@ -1,121 +0,0 @@
-menuSignIn = Sign In
-menuRegister = Register
-reportBug = Report Bug
-loadingPlugins = Loading plugins ...
-
-signInDialogTitle = Code Review - Sign In
-signInDialogGoAnonymous = Go Anonymous
-
-linkIdentityDialogTitle = Code Review - Link Identity
-registerDialogTitle = Code Review - Register New Account
-loginTypeUnsupported = Sign in is not available.
-
-errorTitle = Code Review - Error
-errorDialogContinue = Continue
-warnTitle = Code Review - Warning
-
-confirmationDialogOk = OK
-confirmationDialogCancel = Cancel
-
-branchCreationDialogTitle = Branch Creation
-branchCreationConfirmationMessage = The following branch was successfully created:
-
-tagCreationDialogTitle = Tag Creation
-tagCreationConfirmationMessage = The following tag was successfully created:
-
-branchDeletionDialogTitle = Branch Deletion
-branchDeletionConfirmationMessage = Do you really want to delete the following branches?
-
-tagDeletionDialogTitle = Tag Deletion
-tagDeletionConfirmationMessage = Do you really want to delete the following tags?
-
-newUi = Switch to New UI
-
-notSignedInTitle = Code Review - Session Expired
-notSignedInBody = <b>Session Expired</b>\
-<p>You are no longer signed in to Gerrit Code Review.</p>\
-<p>To continue, please sign-in again.</p>
-
-notFoundTitle = Not Found
-notFoundBody = The page you requested was not found, or you do not have permission to view this page.
-noSuchAccountTitle = Code Review - Unknown User
-
-noSuchGroupTitle = Code Review - Unknown Group
-
-inactiveAccountBody = This user is currently inactive.
-
-labelNotApplicable = Label not applicable
-
-menuAll = All
-menuAllOpen = Open
-menuAllMerged = Merged
-menuAllAbandoned = Abandoned
-
-menuMine = My
-menuMyChanges = Changes
-menuMyStarredChanges = Starred Changes
-menuMyWatchedChanges = Watched Changes
-menuMyDraftComments = Draft Comments
-
-menuDiff = Differences
-menuDiffCommit = Commit Message
-menuDiffPreferences = Preferences
-menuDiffPatchSets = Patch Sets
-menuDiffFiles = Files
-
-menuProjects = Projects
-menuProjectsList = List
-menuProjectsInfo = General
-menuProjectsBranches = Branches
-menuProjectsTags = Tags
-menuProjectsAccess = Access
-menuProjectsDashboards = Dashboards
-menuProjectsCreate = Create New Project
-
-menuPeople = People
-menuPeopleGroupsList = List Groups
-menuPeopleGroupsCreate = Create New Group
-
-menuPlugins = Plugins
-menuPluginsInstalled = Installed
-
-menuDocumentation = Documentation
-menuDocumentationTOC = Table of Contents
-menuDocumentationSearch = Searching
-menuDocumentationUpload = Uploading
-menuDocumentationAccess = Access Controls
-menuDocumentationAPI = REST API
-menuDocumentationProjectOwnerGuide = Project Owner Guide
-
-searchHint = Search term
-searchButton = Search
-
-rpcStatusWorking = Working ...
-
-sectionNavigation = Navigation
-sectionActions = Actions
-keySearch = Search
-keyEditor = Open Inline Editor
-keyHelp = Press '?' to view keyboard shortcuts
-
-sectionJumping = Jumping
-jumpAllOpen = Go to all open changes
-jumpAllMerged = Go to all merged changes
-jumpAllAbandoned = Go to all abandoned changes
-jumpMine = Go to my dashboard
-jumpMineWatched = Go to watched changes
-jumpMineStarred = Go to starred changes
-jumpMineDraftComments = Go to draft comments
-
-projectAccessError = You don't have permissions to modify the access rights for the following refs:
-projectAccessProposeForReviewHint = You may propose these modifications to the project owners by clicking on 'Save for Review'.
-
-userCannotVoteToolTip = User cannot vote in this category
-
-stringListPanelAdd = Add
-stringListPanelDelete = Delete
-stringListPanelUp = Up
-stringListPanelDown = Down
-
-searchDropdownChanges = Changes
-searchDropdownDoc = Docs
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java
deleted file mode 100644
index 968104c..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java
+++ /dev/null
@@ -1,299 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gwt.resources.client.CssResource;
-
-public interface GerritCss extends CssResource {
-  String accountDashboard();
-
-  String accountInfoBlock();
-
-  String accountLinkPanel();
-
-  String accountPassword();
-
-  String accountUsername();
-
-  String activeRow();
-
-  String addBranch();
-
-  String addMemberTextBox();
-
-  String addSshKeyPanel();
-
-  String addWatchPanel();
-
-  String avatarInfoPanel();
-
-  String bottomheader();
-
-  String branchTableDeleteButton();
-
-  String branchTablePrevNextLinks();
-
-  String cAPPROVAL();
-
-  String cASSIGNEE();
-
-  String cASSIGNEDTOME();
-
-  String cLastUpdate();
-
-  String cOWNER();
-
-  String cSIZE();
-
-  String cSUBJECT();
-
-  String cSTATUS();
-
-  String changeSize();
-
-  String changeTable();
-
-  String changeTablePrevNextLinks();
-
-  String commentedActionDialog();
-
-  String commentedActionMessage();
-
-  String contributorAgreementAlreadySubmitted();
-
-  String contributorAgreementButton();
-
-  String contributorAgreementLegal();
-
-  String contributorAgreementShortDescription();
-
-  String createProjectPanel();
-
-  String dataCell();
-
-  String dataCellHidden();
-
-  String dataHeader();
-
-  String dataHeaderHidden();
-
-  String downloadBox();
-
-  String downloadBoxTable();
-
-  String downloadBoxTableCommandColumn();
-
-  String downloadBoxSpacer();
-
-  String downloadBoxScheme();
-
-  String downloadBoxCopyLabel();
-
-  String downloadLink();
-
-  String downloadLinkCopyLabel();
-
-  String downloadLinkHeader();
-
-  String downloadLinkHeaderGap();
-
-  String downloadLinkList();
-
-  String downloadLink_Active();
-
-  String editHeadButton();
-
-  String emptySection();
-
-  String errorDialog();
-
-  String errorDialogButtons();
-
-  String errorDialogErrorType();
-
-  String errorDialogGlass();
-
-  String errorDialogTitle();
-
-  String extensionPanel();
-
-  String loadingPluginsDialog();
-
-  String gerritBody();
-
-  String gerritTopMenu();
-
-  String greenCheckClass();
-
-  String groupDescriptionPanel();
-
-  String groupIncludesTable();
-
-  String groupMembersTable();
-
-  String groupName();
-
-  String groupNamePanel();
-
-  String groupNameTextBox();
-
-  String groupOptionsPanel();
-
-  String groupOwnerPanel();
-
-  String groupOwnerTextBox();
-
-  String groupUUIDPanel();
-
-  String header();
-
-  String iconCell();
-
-  String iconHeader();
-
-  String identityUntrustedExternalId();
-
-  String infoBlock();
-
-  String inputFieldTypeHint();
-
-  String labelNotApplicable();
-
-  String leftMostCell();
-
-  String link();
-
-  String linkMenuBar();
-
-  String linkMenuItemNotLast();
-
-  String maxObjectSizeLimitEffectiveLabel();
-
-  String menuBarUserName();
-
-  String menuBarUserNameAvatar();
-
-  String menuBarUserNameFocusPanel();
-
-  String menuBarUserNamePanel();
-
-  String menuItem();
-
-  String menuScreenMenuBar();
-
-  String needsReview();
-
-  String negscore();
-
-  String oauthExpires();
-
-  String oauthInfoBlock();
-
-  String oauthPanel();
-
-  String oauthPanelCookieEntry();
-
-  String oauthPanelCookieHeading();
-
-  String oauthPanelNetRCEntry();
-
-  String oauthPanelNetRCHeading();
-
-  String oauthToken();
-
-  String pagingLink();
-
-  String patchSetActions();
-
-  String pluginProjectConfigInheritedValue();
-
-  String pluginsTable();
-
-  String posscore();
-
-  String projectActions();
-
-  String projectFilterLabel();
-
-  String projectFilterPanel();
-
-  String projectNameColumn();
-
-  String queryIcon();
-
-  String rebaseContentPanel();
-
-  String rebaseSuggestBox();
-
-  String registerScreenExplain();
-
-  String registerScreenNextLinks();
-
-  String registerScreenSection();
-
-  String rpcStatus();
-
-  String screen();
-
-  String screenHeader();
-
-  String searchPanel();
-
-  String suggestBoxPopup();
-
-  String sectionHeader();
-
-  String singleLine();
-
-  String smallHeading();
-
-  String specialBranchDataCell();
-
-  String specialBranchIconCell();
-
-  String sshHostKeyPanel();
-
-  String sshHostKeyPanelFingerprintData();
-
-  String sshHostKeyPanelHeading();
-
-  String sshHostKeyPanelKnownHostEntry();
-
-  String sshKeyPanelEncodedKey();
-
-  String sshKeyPanelInvalid();
-
-  String sshKeyTable();
-
-  String stringListPanelButtons();
-
-  String topmenu();
-
-  String topmenuMenuLeft();
-
-  String topmenuMenuRight();
-
-  String topmenuTDglue();
-
-  String topmenuTDmenu();
-
-  String topmost();
-
-  String userInfoPopup();
-
-  String usernameField();
-
-  String watchedProjectFilter();
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritMessages.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritMessages.java
deleted file mode 100644
index 980529a..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritMessages.java
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gwt.i18n.client.Messages;
-
-public interface GerritMessages extends Messages {
-  String windowTitle1(String hostname);
-
-  String windowTitle2(String section, String hostname);
-
-  String poweredBy(String version);
-
-  String noSuchAccountMessage(String who);
-
-  String noSuchGroupMessage(String who);
-
-  String nameAlreadyUsedBody(String alreadyUsedName);
-
-  String branchCreationFailed(String branchName, String error);
-
-  String invalidBranchName(String branchName);
-
-  String invalidRevision(String revision);
-
-  String branchCreationNotAllowedUnderRefnamePrefix(String refnamePrefix);
-
-  String branchAlreadyExists(String branchName);
-
-  String branchCreationConflict(String branchName, String existingBranchName);
-
-  String pluginFailed(String scriptPath);
-
-  String cannotDownloadPlugin(String scriptPath);
-
-  String parentUpdateFailed(String message);
-
-  String fileCount(int fileNumber, int fileCount);
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritMessages.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritMessages.properties
deleted file mode 100644
index b2d67b8..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritMessages.properties
+++ /dev/null
@@ -1,21 +0,0 @@
-windowTitle1 = {0} Code Review
-windowTitle2 = {0} | {1} Code Review
-poweredBy = Powered by <a href="https://www.gerritcodereview.com/" target="_blank">Gerrit Code Review</a> ({0})
-
-noSuchAccountMessage = {0} is not a registered user.
-noSuchGroupMessage = Group {0} does not exist or is not visible to you.
-nameAlreadyUsedBody = The name {0} is already in use.
-
-branchCreationFailed = Creating branch {0} failed. Error: {1}
-invalidBranchName = The branch name {0} is not valid.
-invalidRevision = The revision {0} is not valid.
-branchCreationNotAllowedUnderRefnamePrefix = Branch creation is not allowed under {0}.
-branchAlreadyExists = A branch with the name {0} already exists.
-branchCreationConflict = Cannot create branch {0} since it conflicts with branch {1}.
-
-pluginFailed = Plugin "{0}" failed to load
-cannotDownloadPlugin = Cannot load plugin from {0}
-
-parentUpdateFailed = Setting parent project failed: {0}
-
-fileCount = File {0} of {1}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritResources.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritResources.java
deleted file mode 100644
index 01be2f2..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritResources.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gwt.resources.client.CssResource;
-
-public interface GerritResources extends Resources {
-  @Source("gerrit.css")
-  GerritCss css();
-
-  @Source("gwt_override.css")
-  CssResource gwt_override();
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/HostPageDataService.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/HostPageDataService.java
deleted file mode 100644
index bd3d483..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/HostPageDataService.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gerrit.common.data.HostPageData;
-import com.google.gwtjsonrpc.common.AsyncCallback;
-import com.google.gwtjsonrpc.common.HostPageCache;
-import com.google.gwtjsonrpc.common.RemoteJsonService;
-import com.google.gwtjsonrpc.common.RpcImpl;
-import com.google.gwtjsonrpc.common.RpcImpl.Version;
-
-@RpcImpl(version = Version.V2_0)
-interface HostPageDataService extends RemoteJsonService {
-  @HostPageCache(name = "gerrit_hostpagedata", once = true)
-  void load(AsyncCallback<HostPageData> callback);
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/JumpKeys.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/JumpKeys.java
deleted file mode 100644
index a4879ca..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/JumpKeys.java
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gerrit.common.PageLinks;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.globalkey.client.CompoundKeyCommand;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-import com.google.gwtexpui.globalkey.client.KeyCommand;
-import com.google.gwtexpui.globalkey.client.KeyCommandSet;
-
-public class JumpKeys {
-  private static HandlerRegistration activeHandler;
-  private static KeyCommandSet keys;
-  private static Widget bodyWidget;
-
-  public static void enable(boolean enable) {
-    if (enable && activeHandler == null) {
-      activeHandler = GlobalKey.add(bodyWidget, keys);
-    } else if (!enable && activeHandler != null) {
-      activeHandler.removeHandler();
-      activeHandler = null;
-    }
-  }
-
-  static void register(Widget body) {
-    final KeyCommandSet jumps = new KeyCommandSet();
-
-    jumps.add(
-        new KeyCommand(0, 'o', Gerrit.C.jumpAllOpen()) {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            Gerrit.display(PageLinks.toChangeQuery("status:open"));
-          }
-        });
-    jumps.add(
-        new KeyCommand(0, 'm', Gerrit.C.jumpAllMerged()) {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            Gerrit.display(PageLinks.toChangeQuery("status:merged"));
-          }
-        });
-    jumps.add(
-        new KeyCommand(0, 'a', Gerrit.C.jumpAllAbandoned()) {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            Gerrit.display(PageLinks.toChangeQuery("status:abandoned"));
-          }
-        });
-
-    if (Gerrit.isSignedIn()) {
-      jumps.add(
-          new KeyCommand(0, 'i', Gerrit.C.jumpMine()) {
-            @Override
-            public void onKeyPress(KeyPressEvent event) {
-              Gerrit.display(PageLinks.MINE);
-            }
-          });
-      jumps.add(
-          new KeyCommand(0, 'c', Gerrit.C.jumpMineDraftComments()) {
-            @Override
-            public void onKeyPress(KeyPressEvent event) {
-              Gerrit.display(PageLinks.toChangeQuery("has:draft"));
-            }
-          });
-      jumps.add(
-          new KeyCommand(0, 'w', Gerrit.C.jumpMineWatched()) {
-            @Override
-            public void onKeyPress(KeyPressEvent event) {
-              Gerrit.display(PageLinks.toChangeQuery("is:watched status:open"));
-            }
-          });
-      jumps.add(
-          new KeyCommand(0, 's', Gerrit.C.jumpMineStarred()) {
-            @Override
-            public void onKeyPress(KeyPressEvent event) {
-              Gerrit.display(PageLinks.toChangeQuery("is:starred"));
-            }
-          });
-    }
-
-    keys = new KeyCommandSet(Gerrit.C.sectionJumping());
-    keys.add(new CompoundKeyCommand(0, 'g', "", jumps));
-    bodyWidget = body;
-    activeHandler = GlobalKey.add(body, keys);
-  }
-
-  private JumpKeys() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/MessageOfTheDayBar.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/MessageOfTheDayBar.java
deleted file mode 100644
index 36fa6e8..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/MessageOfTheDayBar.java
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gerrit.common.data.HostPageData;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.Cookies;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwtexpui.safehtml.client.SafeHtml;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-import java.util.ArrayList;
-import java.util.List;
-
-/** Displays pending messages from the server. */
-class MessageOfTheDayBar extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, MessageOfTheDayBar> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  private final List<HostPageData.Message> motd;
-  @UiField HTML message;
-  @UiField Anchor dismiss;
-
-  MessageOfTheDayBar(List<HostPageData.Message> motd) {
-    this.motd = filter(motd);
-    initWidget(uiBinder.createAndBindUi(this));
-
-    SafeHtmlBuilder b = new SafeHtmlBuilder();
-    if (this.motd.size() == 1) {
-      b.append(SafeHtml.asis(this.motd.get(0).html));
-    } else {
-      for (HostPageData.Message m : this.motd) {
-        b.openDiv();
-        b.append(SafeHtml.asis(m.html));
-        b.openElement("hr");
-        b.closeSelf();
-        b.closeDiv();
-      }
-    }
-    message.setHTML(b);
-  }
-
-  void show() {
-    if (!motd.isEmpty()) {
-      RootPanel.get().add(this);
-    }
-  }
-
-  @UiHandler("dismiss")
-  void onDismiss(@SuppressWarnings("unused") ClickEvent e) {
-    removeFromParent();
-
-    for (HostPageData.Message m : motd) {
-      Cookies.setCookie(cookieName(m), "1", m.redisplay);
-    }
-  }
-
-  private static List<HostPageData.Message> filter(List<HostPageData.Message> in) {
-    List<HostPageData.Message> show = new ArrayList<>();
-    for (HostPageData.Message m : in) {
-      if (Cookies.getCookie(cookieName(m)) == null) {
-        show.add(m);
-      }
-    }
-    return show;
-  }
-
-  private static String cookieName(HostPageData.Message m) {
-    return "msg-" + m.id;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/MessageOfTheDayBar.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/MessageOfTheDayBar.ui.xml
deleted file mode 100644
index 36d08b1..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/MessageOfTheDayBar.ui.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:c='urn:import:com.google.gwtexpui.globalkey.client'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-  <ui:style gss='false'>
-    .popup {
-      position: fixed;
-      top: 5px;
-      left: 50%;
-      margin-left: -200px;
-      z-index: 201;
-      padding-top: 5px;
-      padding-bottom: 5px;
-      padding-left: 12px;
-      padding-right: 12px;
-      background: #FFF1A8;
-      border-radius: 10px;
-    }
-
-    @if user.agent safari {
-      .popup {
-        \-webkit-border-radius: 10px;
-      }
-    }
-    @if user.agent gecko1_8 {
-      .popup {
-        \-moz-border-radius: 10px;
-      }
-    }
-
-    .message {
-      display: inline;
-    }
-    .message a {
-      color: #222;
-      text-decoration: underline;
-    }
-    a.action {
-      color: #222;
-      text-decoration: underline;
-      display: inline-block;
-      margin-left: 0.5em;
-    }
-  </ui:style>
-  <g:HTMLPanel styleName='{style.popup}'>
-    <g:HTML ui:field='message' styleName='{style.message}'/>
-    <g:Anchor ui:field='dismiss'
-        styleName='{style.action}'
-        href='javascript:;'
-        title='Hide this message'>
-      <ui:attribute name='title'/>
-      Dismiss
-    </g:Anchor>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/NotFoundScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/NotFoundScreen.java
deleted file mode 100644
index 29bbf85..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/NotFoundScreen.java
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gerrit.client.ui.Screen;
-import com.google.gwt.user.client.ui.Label;
-
-/** Displays an error message letting the user know the page doesn't exist. */
-public class NotFoundScreen extends Screen {
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    setPageTitle(Gerrit.C.notFoundTitle());
-    add(new Label(Gerrit.C.notFoundBody()));
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    display();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/NotSignedInDialog.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/NotSignedInDialog.java
deleted file mode 100644
index cd5197a..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/NotSignedInDialog.java
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.user.client.History;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-
-/** A dialog box telling the user they are not signed in. */
-public class NotSignedInDialog extends PopupPanel implements CloseHandler<PopupPanel> {
-  private Button signin;
-  private boolean buttonClicked;
-
-  public NotSignedInDialog() {
-    super(/* auto hide */ false, /* modal */ true);
-    setGlassEnabled(true);
-    getGlassElement().addClassName(Gerrit.RESOURCES.css().errorDialogGlass());
-    addStyleName(Gerrit.RESOURCES.css().errorDialog());
-
-    final FlowPanel buttons = new FlowPanel();
-    signin = new Button();
-    signin.setText(Gerrit.C.menuSignIn());
-    signin.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            buttonClicked = true;
-            hide();
-            Gerrit.doSignIn(History.getToken());
-          }
-        });
-    buttons.add(signin);
-
-    final Button close = new Button();
-    close.getElement().getStyle().setProperty("marginLeft", "200px");
-    close.setText(Gerrit.C.signInDialogGoAnonymous());
-    close.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            buttonClicked = true;
-            Gerrit.deleteSessionCookie();
-            hide();
-          }
-        });
-    buttons.add(close);
-
-    Label title = new Label(Gerrit.C.notSignedInTitle());
-    title.setStyleName(Gerrit.RESOURCES.css().errorDialogTitle());
-
-    FlowPanel center = new FlowPanel();
-    center.add(title);
-    center.add(new HTML(Gerrit.C.notSignedInBody()));
-    center.add(buttons);
-    add(center);
-
-    int l = Window.getScrollLeft() + 20;
-    int t = Window.getScrollTop() + 20;
-    setPopupPosition(l, t);
-    addCloseHandler(this);
-  }
-
-  @Override
-  public void onClose(CloseEvent<PopupPanel> event) {
-    if (!buttonClicked) {
-      // the dialog was closed without one of the buttons being pressed
-      // e.g. the user pressed ESC to close the dialog
-      Gerrit.deleteSessionCookie();
-    }
-  }
-
-  @Override
-  public void center() {
-    show();
-    GlobalKey.dialog(this);
-    signin.setFocus(true);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/RangeInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/RangeInfo.java
deleted file mode 100644
index 42454a3..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/RangeInfo.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class RangeInfo extends JavaScriptObject {
-  public final native int start() /*-{ return this.start; }-*/;
-
-  public final native int end() /*-{ return this.end; }-*/;
-
-  protected RangeInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/RpcStatus.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/RpcStatus.java
deleted file mode 100644
index 4153439..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/RpcStatus.java
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gwt.user.client.ui.InlineLabel;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwtjsonrpc.client.event.RpcCompleteEvent;
-import com.google.gwtjsonrpc.client.event.RpcCompleteHandler;
-import com.google.gwtjsonrpc.client.event.RpcStartEvent;
-import com.google.gwtjsonrpc.client.event.RpcStartHandler;
-
-public class RpcStatus implements RpcStartHandler, RpcCompleteHandler {
-  public static RpcStatus INSTANCE;
-
-  private static int hideDepth;
-
-  /** Execute code, hiding the RPCs they execute from being shown visually. */
-  public static void hide(Runnable run) {
-    try {
-      hideDepth++;
-      run.run();
-    } finally {
-      hideDepth--;
-    }
-  }
-
-  private final Label loading;
-  private int activeCalls;
-
-  RpcStatus() {
-    loading = new InlineLabel();
-    loading.setText(Gerrit.C.rpcStatusWorking());
-    loading.setStyleName(Gerrit.RESOURCES.css().rpcStatus());
-    loading.setVisible(false);
-    RootPanel.get().add(loading);
-  }
-
-  @Override
-  public void onRpcStart(RpcStartEvent event) {
-    onRpcStart();
-  }
-
-  public void onRpcStart() {
-    if (++activeCalls == 1) {
-      if (hideDepth == 0) {
-        loading.setVisible(true);
-      }
-    }
-  }
-
-  @Override
-  public void onRpcComplete(RpcCompleteEvent event) {
-    onRpcComplete();
-  }
-
-  public void onRpcComplete() {
-    if (--activeCalls == 0) {
-      loading.setVisible(false);
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java
deleted file mode 100644
index 406ab4e..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gerrit.client.changes.QueryScreen;
-import com.google.gerrit.client.ui.HintTextBox;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.ListBox;
-import com.google.gwt.user.client.ui.SuggestBox;
-import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-import com.google.gwtexpui.globalkey.client.KeyCommand;
-
-class SearchPanel extends Composite {
-  private final HintTextBox searchBox;
-  private final ListBox dropdown;
-  private HandlerRegistration regFocus;
-
-  SearchPanel() {
-    final FlowPanel body = new FlowPanel();
-    initWidget(body);
-    setStyleName(Gerrit.RESOURCES.css().searchPanel());
-
-    searchBox = new HintTextBox();
-    final MySuggestionDisplay suggestionDisplay = new MySuggestionDisplay();
-    searchBox.addKeyPressHandler(
-        new KeyPressHandler() {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
-              if (!suggestionDisplay.isSuggestionSelected) {
-                doSearch();
-              }
-            }
-          }
-        });
-
-    if (Gerrit.hasDocSearch()) {
-      dropdown = new ListBox();
-      dropdown.setStyleName("searchDropdown");
-      dropdown.addItem(Gerrit.C.searchDropdownChanges());
-      dropdown.addItem(Gerrit.C.searchDropdownDoc());
-      dropdown.setVisibleItemCount(1);
-      dropdown.setSelectedIndex(0);
-    } else {
-      // Doc search is NOT available.
-      dropdown = null;
-    }
-
-    final SuggestBox suggestBox =
-        new SuggestBox(new SearchSuggestOracle(), searchBox, suggestionDisplay);
-    searchBox.setStyleName("searchTextBox");
-    searchBox.setVisibleLength(70);
-    searchBox.setHintText(Gerrit.C.searchHint());
-
-    final Button searchButton = new Button(Gerrit.C.searchButton());
-    searchButton.setStyleName("searchButton");
-    searchButton.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            doSearch();
-          }
-        });
-
-    body.add(suggestBox);
-    if (dropdown != null) {
-      body.add(dropdown);
-    }
-    body.add(searchButton);
-  }
-
-  void setText(String query) {
-    searchBox.setText(query);
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    if (regFocus == null) {
-      regFocus =
-          GlobalKey.addApplication(
-              this,
-              new KeyCommand(0, '/', Gerrit.C.keySearch()) {
-                @Override
-                public void onKeyPress(KeyPressEvent event) {
-                  event.preventDefault();
-                  searchBox.setFocus(true);
-                  searchBox.selectAll();
-                }
-              });
-    }
-  }
-
-  @Override
-  protected void onUnload() {
-    if (regFocus != null) {
-      regFocus.removeHandler();
-      regFocus = null;
-    }
-  }
-
-  private void doSearch() {
-    final String query = searchBox.getText().trim();
-    if ("".equals(query)) {
-      return;
-    }
-
-    searchBox.setFocus(false);
-
-    if (dropdown != null && dropdown.getSelectedValue().equals(Gerrit.C.searchDropdownDoc())) {
-      // doc
-      Gerrit.display(PageLinks.toDocumentationQuery(query));
-    } else {
-      // changes
-      if (query.matches("^[1-9][0-9]*$")) {
-        // Query is a change number. Project can't be supplied.
-        Gerrit.display(PageLinks.toChange(null, Change.Id.parse(query)));
-      } else {
-        Gerrit.display(PageLinks.toChangeQuery(query), QueryScreen.forQuery(query));
-      }
-    }
-  }
-
-  private static class MySuggestionDisplay extends SuggestBox.DefaultSuggestionDisplay {
-    private boolean isSuggestionSelected;
-
-    private MySuggestionDisplay() {
-      super();
-
-      getPopupPanel().addStyleName(Gerrit.RESOURCES.css().suggestBoxPopup());
-    }
-
-    @Override
-    protected Suggestion getCurrentSelection() {
-      Suggestion currentSelection = super.getCurrentSelection();
-      isSuggestionSelected = currentSelection != null;
-      return currentSelection;
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchSuggestOracle.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchSuggestOracle.java
deleted file mode 100644
index cb3e9f0..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchSuggestOracle.java
+++ /dev/null
@@ -1,311 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gerrit.client.ui.AccountGroupSuggestOracle;
-import com.google.gerrit.client.ui.AccountSuggestOracle;
-import com.google.gerrit.client.ui.ProjectNameSuggestOracle;
-import com.google.gwt.user.client.ui.SuggestOracle;
-import com.google.gwtexpui.safehtml.client.HighlightSuggestOracle;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.TreeSet;
-
-public class SearchSuggestOracle extends HighlightSuggestOracle {
-  private static final List<ParamSuggester> paramSuggester =
-      Arrays.asList(
-          new ParamSuggester(
-              Arrays.asList("project:", "p:", "parentproject:"), new ProjectNameSuggestOracle()),
-          new ParamSuggester(
-              Arrays.asList(
-                  "owner:",
-                  "o:",
-                  "reviewer:",
-                  "r:",
-                  "commentby:",
-                  "reviewedby:",
-                  "author:",
-                  "committer:",
-                  "from:",
-                  "assignee:",
-                  "cc:"),
-              new AccountSuggestOracle() {
-                @Override
-                public void onRequestSuggestions(Request request, Callback done) {
-                  super.onRequestSuggestions(
-                      request,
-                      new Callback() {
-                        @Override
-                        public void onSuggestionsReady(final Request request, Response response) {
-                          if ("self".startsWith(request.getQuery())) {
-                            final ArrayList<SuggestOracle.Suggestion> r =
-                                new ArrayList<>(response.getSuggestions().size() + 1);
-                            r.add(
-                                new SuggestOracle.Suggestion() {
-                                  @Override
-                                  public String getDisplayString() {
-                                    return getReplacementString();
-                                  }
-
-                                  @Override
-                                  public String getReplacementString() {
-                                    return "self";
-                                  }
-                                });
-                            r.addAll(response.getSuggestions());
-                            response.setSuggestions(r);
-                          }
-                          done.onSuggestionsReady(request, response);
-                        }
-                      });
-                }
-              }),
-          new ParamSuggester(
-              Arrays.asList("ownerin:", "reviewerin:"), new AccountGroupSuggestOracle()));
-
-  private static final TreeSet<String> suggestions = new TreeSet<>();
-
-  static {
-    suggestions.add("age:");
-    suggestions.add("age:1week"); // Give an example age
-
-    suggestions.add("change:");
-
-    suggestions.add("owner:");
-    suggestions.add("owner:self");
-    suggestions.add("ownerin:");
-    suggestions.add("author:");
-    suggestions.add("committer:");
-    suggestions.add("assignee:");
-
-    suggestions.add("reviewer:");
-    suggestions.add("reviewer:self");
-    suggestions.add("reviewerin:");
-    suggestions.add("reviewedby:");
-
-    suggestions.add("commit:");
-    suggestions.add("comment:");
-    suggestions.add("message:");
-    suggestions.add("commentby:");
-    suggestions.add("from:");
-    suggestions.add("file:");
-    suggestions.add("conflicts:");
-    suggestions.add("project:");
-    suggestions.add("projects:");
-    suggestions.add("parentproject:");
-    suggestions.add("branch:");
-    suggestions.add("topic:");
-    suggestions.add("intopic:");
-    suggestions.add("ref:");
-    suggestions.add("tr:");
-    suggestions.add("bug:");
-    suggestions.add("label:");
-    suggestions.add("query:");
-    suggestions.add("has:");
-    suggestions.add("has:draft");
-    suggestions.add("has:edit");
-    suggestions.add("has:star");
-    suggestions.add("has:stars");
-    suggestions.add("has:unresolved");
-    suggestions.add("star:");
-
-    suggestions.add("is:");
-    suggestions.add("is:starred");
-    suggestions.add("is:watched");
-    suggestions.add("is:reviewed");
-    suggestions.add("is:owner");
-    suggestions.add("is:reviewer");
-    suggestions.add("is:open");
-    suggestions.add("is:pending");
-    suggestions.add("is:private");
-    suggestions.add("is:closed");
-    suggestions.add("is:merged");
-    suggestions.add("is:abandoned");
-    suggestions.add("is:mergeable");
-    suggestions.add("is:ignored");
-    suggestions.add("is:wip");
-    suggestions.add("is:assigned");
-
-    suggestions.add("status:");
-    suggestions.add("status:open");
-    suggestions.add("status:pending");
-    suggestions.add("status:reviewed");
-    suggestions.add("status:closed");
-    suggestions.add("status:merged");
-    suggestions.add("status:abandoned");
-
-    suggestions.add("added:");
-    suggestions.add("deleted:");
-    suggestions.add("delta:");
-    suggestions.add("size:");
-
-    suggestions.add("unresolved:");
-
-    suggestions.add("revertof:");
-
-    if (Gerrit.isNoteDbEnabled()) {
-      suggestions.add("cc:");
-      suggestions.add("hashtag:");
-    }
-
-    suggestions.add("is:assigned");
-    suggestions.add("is:unassigned");
-    suggestions.add("assignee:");
-
-    suggestions.add("AND");
-    suggestions.add("OR");
-    suggestions.add("NOT");
-  }
-
-  @Override
-  public void requestDefaultSuggestions(Request request, Callback done) {
-    final ArrayList<SearchSuggestion> r = new ArrayList<>();
-    // No text - show some default suggestions.
-    r.add(new SearchSuggestion("status:open", "status:open"));
-    r.add(new SearchSuggestion("age:1week", "age:1week"));
-    if (Gerrit.isSignedIn()) {
-      r.add(new SearchSuggestion("owner:self", "owner:self"));
-    }
-    done.onSuggestionsReady(request, new Response(r));
-  }
-
-  @Override
-  protected void onRequestSuggestions(Request request, Callback done) {
-    final String query = request.getQuery();
-
-    final String lastWord = getLastWord(query);
-    if (lastWord == null) {
-      // Starting a new word - don't show suggestions yet.
-      done.onSuggestionsReady(request, null);
-      return;
-    }
-
-    for (ParamSuggester ps : paramSuggester) {
-      if (ps.applicable(lastWord)) {
-        ps.suggest(lastWord, request, done);
-        return;
-      }
-    }
-
-    final ArrayList<SearchSuggestion> r = new ArrayList<>();
-    for (String suggestion : suggestions.tailSet(lastWord)) {
-      if ((lastWord.length() < suggestion.length()) && suggestion.startsWith(lastWord)) {
-        if (suggestion.contains("self") && !Gerrit.isSignedIn()) {
-          continue;
-        }
-        r.add(new SearchSuggestion(suggestion, query + suggestion.substring(lastWord.length())));
-      }
-    }
-    done.onSuggestionsReady(request, new Response(r));
-  }
-
-  private String getLastWord(String query) {
-    final int lastSpace = query.lastIndexOf(' ');
-    if (lastSpace == query.length() - 1) {
-      return null;
-    }
-    if (lastSpace == -1) {
-      return query;
-    }
-    return query.substring(lastSpace + 1);
-  }
-
-  @Override
-  protected String getQueryPattern(String query) {
-    return super.getQueryPattern(getLastWord(query));
-  }
-
-  @Override
-  protected boolean isHTML() {
-    return true;
-  }
-
-  private static class SearchSuggestion implements SuggestOracle.Suggestion {
-    private final String suggestion;
-    private final String fullQuery;
-
-    SearchSuggestion(String suggestion, String fullQuery) {
-      this.suggestion = suggestion;
-      // Add a space to the query if it is a complete operation (e.g.
-      // "status:open") so the user can keep on typing.
-      this.fullQuery = fullQuery.endsWith(":") ? fullQuery : fullQuery + " ";
-    }
-
-    @Override
-    public String getDisplayString() {
-      return suggestion;
-    }
-
-    @Override
-    public String getReplacementString() {
-      return fullQuery;
-    }
-  }
-
-  private static class ParamSuggester {
-    private final List<String> operators;
-    private final SuggestOracle parameterSuggestionOracle;
-
-    ParamSuggester(List<String> operators, SuggestOracle parameterSuggestionOracle) {
-      this.operators = operators;
-      this.parameterSuggestionOracle = parameterSuggestionOracle;
-    }
-
-    boolean applicable(String query) {
-      final String operator = getApplicableOperator(query, operators);
-      return operator != null && query.length() > operator.length();
-    }
-
-    private String getApplicableOperator(String lastWord, List<String> operators) {
-      for (String operator : operators) {
-        if (lastWord.startsWith(operator)) {
-          return operator;
-        }
-      }
-      return null;
-    }
-
-    void suggest(String lastWord, Request request, Callback done) {
-      final String operator = getApplicableOperator(lastWord, operators);
-      parameterSuggestionOracle.requestSuggestions(
-          new Request(lastWord.substring(operator.length()), request.getLimit()),
-          new Callback() {
-            @Override
-            public void onSuggestionsReady(Request req, Response response) {
-              final String query = request.getQuery();
-              final List<SearchSuggestOracle.Suggestion> r =
-                  new ArrayList<>(response.getSuggestions().size());
-              for (SearchSuggestOracle.Suggestion s : response.getSuggestions()) {
-                r.add(
-                    new SearchSuggestion(
-                        s.getDisplayString(),
-                        query.substring(0, query.length() - lastWord.length())
-                            + operator
-                            + quoteIfNeeded(s.getReplacementString())));
-              }
-              done.onSuggestionsReady(request, new Response(r));
-            }
-
-            private String quoteIfNeeded(String s) {
-              if (!s.matches("^\\S*$")) {
-                return "\"" + s + "\"";
-              }
-              return s;
-            }
-          });
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/StringListPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/StringListPanel.java
deleted file mode 100644
index f771fee..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/StringListPanel.java
+++ /dev/null
@@ -1,359 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gerrit.client.ui.NavigationTable;
-import com.google.gerrit.client.ui.OnEditEnabler;
-import com.google.gerrit.client.ui.SmallHeading;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.logical.shared.ValueChangeHandler;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.FocusWidget;
-import com.google.gwt.user.client.ui.HasEnabled;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.ImageResourceRenderer;
-import com.google.gwtexpui.globalkey.client.NpTextBox;
-import java.util.ArrayList;
-import java.util.List;
-
-public class StringListPanel extends FlowPanel implements HasEnabled {
-  private final StringListTable t;
-  private HorizontalPanel titlePanel;
-  protected final HorizontalPanel buttonPanel;
-  private final Button deleteButton;
-  private Image info;
-  protected FocusWidget widget;
-
-  public StringListPanel(String title, List<String> fieldNames, FocusWidget w, boolean autoSort) {
-    widget = w;
-    if (title != null) {
-      titlePanel = new HorizontalPanel();
-      SmallHeading titleLabel = new SmallHeading(title);
-      titlePanel.add(titleLabel);
-      add(titlePanel);
-    }
-
-    t = new StringListTable(fieldNames, autoSort);
-    add(t);
-
-    buttonPanel = new HorizontalPanel();
-    buttonPanel.setStyleName(Gerrit.RESOURCES.css().stringListPanelButtons());
-    deleteButton = new Button(Gerrit.C.stringListPanelDelete());
-    deleteButton.setEnabled(false);
-    deleteButton.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            widget.setEnabled(true);
-            t.deleteChecked();
-          }
-        });
-    buttonPanel.add(deleteButton);
-    add(buttonPanel);
-  }
-
-  public void display(List<List<String>> values) {
-    t.display(values);
-  }
-
-  public void setInfo(String msg) {
-    if (info == null && titlePanel != null) {
-      info = new Image(Gerrit.RESOURCES.info());
-      titlePanel.add(info);
-    }
-    if (info != null) {
-      info.setTitle(msg);
-    }
-  }
-
-  public List<List<String>> getValues() {
-    return t.getValues();
-  }
-
-  public List<String> getValues(int i) {
-    List<List<String>> allValuesList = getValues();
-    List<String> singleValueList = new ArrayList<>(allValuesList.size());
-    for (List<String> values : allValuesList) {
-      singleValueList.add(values.get(i));
-    }
-    return singleValueList;
-  }
-
-  private class StringListTable extends NavigationTable<List<String>> {
-    private final Button addButton;
-    private final List<NpTextBox> inputs;
-    private final boolean autoSort;
-
-    StringListTable(List<String> names, boolean autoSort) {
-      this.autoSort = autoSort;
-
-      addButton = new Button(new ImageResourceRenderer().render(Gerrit.RESOURCES.listAdd()));
-      addButton.setTitle(Gerrit.C.stringListPanelAdd());
-      OnEditEnabler e = new OnEditEnabler(addButton);
-      inputs = new ArrayList<>();
-
-      FlexCellFormatter fmt = table.getFlexCellFormatter();
-      fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().iconHeader());
-      fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().leftMostCell());
-      for (int i = 0; i < names.size(); i++) {
-        fmt.addStyleName(0, i + 1, Gerrit.RESOURCES.css().dataHeader());
-        table.setText(0, i + 1, names.get(i));
-
-        NpTextBox input = new NpTextBox();
-        input.setVisibleLength(35);
-        input.addKeyPressHandler(
-            new KeyPressHandler() {
-              @Override
-              public void onKeyPress(KeyPressEvent event) {
-                if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
-                  widget.setEnabled(true);
-                  add();
-                }
-              }
-            });
-        inputs.add(input);
-        fmt.addStyleName(1, i + 1, Gerrit.RESOURCES.css().dataHeader());
-        table.setWidget(1, i + 1, input);
-        e.listenTo(input);
-      }
-      addButton.setEnabled(false);
-
-      addButton.addClickHandler(
-          new ClickHandler() {
-            @Override
-            public void onClick(ClickEvent event) {
-              widget.setEnabled(true);
-              add();
-            }
-          });
-      fmt.addStyleName(1, 0, Gerrit.RESOURCES.css().iconHeader());
-      fmt.addStyleName(1, 0, Gerrit.RESOURCES.css().leftMostCell());
-      table.setWidget(1, 0, addButton);
-
-      if (!autoSort) {
-        fmt.addStyleName(0, names.size() + 1, Gerrit.RESOURCES.css().iconHeader());
-        fmt.addStyleName(0, names.size() + 2, Gerrit.RESOURCES.css().iconHeader());
-        fmt.addStyleName(1, names.size() + 1, Gerrit.RESOURCES.css().iconHeader());
-        fmt.addStyleName(1, names.size() + 2, Gerrit.RESOURCES.css().iconHeader());
-      }
-    }
-
-    void display(List<List<String>> values) {
-      for (int row = 2; row < table.getRowCount(); row++) {
-        table.removeRow(row--);
-      }
-      int row = 2;
-      for (List<String> v : values) {
-        populate(row, v);
-        row++;
-      }
-      updateNavigationLinks();
-    }
-
-    List<List<String>> getValues() {
-      List<List<String>> values = new ArrayList<>();
-      for (int row = 2; row < table.getRowCount(); row++) {
-        values.add(getRowItem(row));
-      }
-      return values;
-    }
-
-    @Override
-    protected List<String> getRowItem(int row) {
-      List<String> v = new ArrayList<>();
-      for (int i = 0; i < inputs.size(); i++) {
-        v.add(table.getText(row, i + 1));
-      }
-      return v;
-    }
-
-    private void populate(int row, List<String> values) {
-      FlexCellFormatter fmt = table.getFlexCellFormatter();
-      fmt.addStyleName(row, 0, Gerrit.RESOURCES.css().iconCell());
-      fmt.addStyleName(row, 0, Gerrit.RESOURCES.css().leftMostCell());
-      CheckBox checkBox = new CheckBox();
-      checkBox.addValueChangeHandler(
-          new ValueChangeHandler<Boolean>() {
-            @Override
-            public void onValueChange(ValueChangeEvent<Boolean> event) {
-              enableDelete();
-            }
-          });
-      table.setWidget(row, 0, checkBox);
-      for (int i = 0; i < values.size(); i++) {
-        fmt.addStyleName(row, i + 1, Gerrit.RESOURCES.css().dataCell());
-        table.setText(row, i + 1, values.get(i));
-      }
-      if (!autoSort) {
-        fmt.addStyleName(row, values.size() + 1, Gerrit.RESOURCES.css().iconCell());
-        fmt.addStyleName(row, values.size() + 2, Gerrit.RESOURCES.css().dataCell());
-
-        Image down = new Image(Gerrit.RESOURCES.arrowDown());
-        down.setTitle(Gerrit.C.stringListPanelDown());
-        down.addClickHandler(
-            new ClickHandler() {
-              @Override
-              public void onClick(ClickEvent event) {
-                moveDown(row);
-              }
-            });
-        table.setWidget(row, values.size() + 1, down);
-
-        Image up = new Image(Gerrit.RESOURCES.arrowUp());
-        up.setTitle(Gerrit.C.stringListPanelUp());
-        up.addClickHandler(
-            new ClickHandler() {
-              @Override
-              public void onClick(ClickEvent event) {
-                moveUp(row);
-              }
-            });
-        table.setWidget(row, values.size() + 2, up);
-      }
-    }
-
-    @Override
-    protected void onCellSingleClick(Event event, int row, int column) {
-      if (column == inputs.size() + 1 && row >= 2 && row < table.getRowCount() - 2) {
-        moveDown(row);
-      } else if (column == inputs.size() + 2 && row > 2) {
-        moveUp(row);
-      }
-    }
-
-    void moveDown(int row) {
-      if (row < table.getRowCount() - 1) {
-        swap(row, row + 1);
-      }
-    }
-
-    void moveUp(int row) {
-      if (row > 2) {
-        swap(row - 1, row);
-      }
-    }
-
-    void swap(int row1, int row2) {
-      List<String> value = getRowItem(row1);
-      List<String> nextValue = getRowItem(row2);
-      populate(row1, nextValue);
-      populate(row2, value);
-      updateNavigationLinks();
-      widget.setEnabled(true);
-    }
-
-    private void updateNavigationLinks() {
-      if (!autoSort) {
-        for (int row = 2; row < table.getRowCount(); row++) {
-          table.getWidget(row, inputs.size() + 1).setVisible(row < table.getRowCount() - 1);
-          table.getWidget(row, inputs.size() + 2).setVisible(row > 2);
-        }
-      }
-    }
-
-    void add() {
-      List<String> values = new ArrayList<>();
-      for (NpTextBox input : inputs) {
-        values.add(input.getValue().trim());
-        input.setValue("");
-      }
-      insert(values);
-    }
-
-    void insert(List<String> v) {
-      int insertPos = table.getRowCount();
-      if (autoSort) {
-        for (int row = 1; row < table.getRowCount(); row++) {
-          int compareResult = v.get(0).compareTo(table.getText(row, 1));
-          if (compareResult < 0) {
-            insertPos = row;
-            break;
-          } else if (compareResult == 0) {
-            return;
-          }
-        }
-      }
-      table.insertRow(insertPos);
-      populate(insertPos, v);
-      updateNavigationLinks();
-    }
-
-    void enableDelete() {
-      for (int row = 2; row < table.getRowCount(); row++) {
-        if (((CheckBox) table.getWidget(row, 0)).getValue()) {
-          deleteButton.setEnabled(true);
-          return;
-        }
-      }
-      deleteButton.setEnabled(false);
-    }
-
-    void deleteChecked() {
-      deleteButton.setEnabled(false);
-      for (int row = 2; row < table.getRowCount(); row++) {
-        if (((CheckBox) table.getWidget(row, 0)).getValue()) {
-          table.removeRow(row--);
-        }
-      }
-      updateNavigationLinks();
-    }
-
-    @Override
-    protected void onOpenRow(int row) {}
-
-    @Override
-    protected Object getRowItemKey(List<String> item) {
-      return item.get(0);
-    }
-
-    void setEnabled(boolean enabled) {
-      addButton.setVisible(enabled);
-      for (NpTextBox input : inputs) {
-        input.setEnabled(enabled);
-      }
-      for (int row = 2; row < table.getRowCount(); row++) {
-        table.getWidget(row, 0).setVisible(enabled);
-        if (!autoSort) {
-          table.getWidget(row, inputs.size() + 1).setVisible(enabled);
-          table.getWidget(row, inputs.size() + 2).setVisible(enabled);
-        }
-      }
-      if (enabled) {
-        updateNavigationLinks();
-      }
-    }
-  }
-
-  @Override
-  public boolean isEnabled() {
-    return deleteButton.isVisible();
-  }
-
-  @Override
-  public void setEnabled(boolean enabled) {
-    t.setEnabled(enabled);
-    deleteButton.setVisible(enabled);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Themer.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Themer.java
deleted file mode 100644
index d87c0b8..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Themer.java
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gerrit.client.projects.ThemeInfo;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.StyleElement;
-
-public class Themer {
-  public static class ThemerIE extends Themer {
-    protected ThemerIE() {}
-
-    @Override
-    protected String getCssText(StyleElement el) {
-      return el.getCssText();
-    }
-
-    @Override
-    protected void setCssText(StyleElement el, String css) {
-      el.setCssText(css);
-    }
-  }
-
-  protected StyleElement cssElement;
-  protected Element headerElement;
-  protected Element footerElement;
-  protected String cssText;
-  protected String headerHtml;
-  protected String footerHtml;
-
-  protected Themer() {}
-
-  public void set(ThemeInfo theme) {
-    if (theme != null) {
-      set(
-          theme.css() != null ? theme.css() : cssText,
-          theme.header() != null ? theme.header() : headerHtml,
-          theme.footer() != null ? theme.footer() : footerHtml);
-    } else {
-      set(cssText, headerHtml, footerHtml);
-    }
-  }
-
-  public void clear() {
-    set(null);
-  }
-
-  void init(Element css, Element header, Element footer) {
-    cssElement = StyleElement.as(css);
-    headerElement = header;
-    footerElement = footer;
-
-    cssText = getCssText(this.cssElement);
-    headerHtml = header.getInnerHTML();
-    footerHtml = footer.getInnerHTML();
-  }
-
-  protected String getCssText(StyleElement el) {
-    return el.getInnerHTML();
-  }
-
-  protected void setCssText(StyleElement el, String css) {
-    el.setInnerHTML(css);
-  }
-
-  private void set(String css, String header, String footer) {
-    setCssText(cssElement, css);
-    headerElement.setInnerHTML(header);
-    footerElement.setInnerHTML(footer);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/UrlAliasMatcher.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/UrlAliasMatcher.java
deleted file mode 100644
index acaaf46..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/UrlAliasMatcher.java
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gwt.regexp.shared.RegExp;
-import java.util.HashMap;
-import java.util.Map;
-
-public class UrlAliasMatcher {
-  private final Map<RegExp, String> userUrlAliases;
-  private final Map<RegExp, String> globalUrlAliases;
-
-  UrlAliasMatcher(Map<String, String> globalUrlAliases) {
-    this.globalUrlAliases = compile(globalUrlAliases);
-    this.userUrlAliases = new HashMap<>();
-  }
-
-  private static Map<RegExp, String> compile(Map<String, String> urlAliases) {
-    Map<RegExp, String> compiledUrlAliases = new HashMap<>();
-    if (urlAliases != null) {
-      for (Map.Entry<String, String> e : urlAliases.entrySet()) {
-        compiledUrlAliases.put(RegExp.compile(e.getKey()), e.getValue());
-      }
-    }
-    return compiledUrlAliases;
-  }
-
-  void clearUserAliases() {
-    this.userUrlAliases.clear();
-  }
-
-  void updateUserAliases(Map<String, String> userUrlAliases) {
-    clearUserAliases();
-    this.userUrlAliases.putAll(compile(userUrlAliases));
-  }
-
-  public String replace(String token) {
-    for (Map.Entry<RegExp, String> e : userUrlAliases.entrySet()) {
-      RegExp pat = e.getKey();
-      if (pat.exec(token) != null) {
-        return pat.replace(token, e.getValue());
-      }
-    }
-
-    for (Map.Entry<RegExp, String> e : globalUrlAliases.entrySet()) {
-      RegExp pat = e.getKey();
-      if (pat.exec(token) != null) {
-        return pat.replace(token, e.getValue());
-      }
-    }
-    return token;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/UserPopupPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/UserPopupPanel.java
deleted file mode 100644
index cb529f4..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/UserPopupPanel.java
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.ui.InlineHyperlink;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.AnchorElement;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.Widget;
-
-public class UserPopupPanel extends PopupPanel {
-  interface Binder extends UiBinder<Widget, UserPopupPanel> {}
-
-  private static final Binder binder = GWT.create(Binder.class);
-
-  @UiField(provided = true)
-  AvatarImage avatar;
-
-  @UiField Label userName;
-  @UiField Label userEmail;
-  @UiField Element userLinks;
-  @UiField AnchorElement switchAccount;
-  @UiField AnchorElement logout;
-  @UiField InlineHyperlink settings;
-
-  public UserPopupPanel(AccountInfo account, boolean canLogOut, boolean showSettingsLink) {
-    super(/* auto hide */ true, /* modal */ false);
-    avatar = new AvatarImage(account, 100, false);
-    setWidget(binder.createAndBindUi(this));
-    setStyleName(Gerrit.RESOURCES.css().userInfoPopup());
-    if (account.name() != null) {
-      userName.setText(account.name());
-    }
-    if (account.email() != null) {
-      userEmail.setText(account.email());
-    }
-    if (showSettingsLink) {
-      String switchAccountUrl = Gerrit.info().auth().switchAccountUrl();
-      if (switchAccountUrl != null) {
-        switchAccount.setHref(switchAccountUrl.replace("${path}", "/"));
-      } else if (Gerrit.info().auth().isDev() || Gerrit.info().auth().isOpenId()) {
-        switchAccount.setHref(Gerrit.selfRedirect("/login"));
-      } else {
-        switchAccount.removeFromParent();
-        switchAccount = null;
-      }
-      if (canLogOut) {
-        logout.setHref(Gerrit.selfRedirect("/logout"));
-      } else {
-        logout.removeFromParent();
-        logout = null;
-      }
-
-    } else {
-      settings.removeFromParent();
-      settings = null;
-      userLinks.removeFromParent();
-      userLinks = null;
-      logout = null;
-    }
-
-    // We must show and then hide this popup so that it is part of the DOM.
-    // Otherwise the image does not get any events.  Calling hide() would
-    // remove it from the DOM so we use setVisible(false) instead.
-    show();
-    setVisible(false);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/UserPopupPanel.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/UserPopupPanel.ui.xml
deleted file mode 100644
index 8f5073d..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/UserPopupPanel.ui.xml
+++ /dev/null
@@ -1,70 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2012 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
-<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
-  xmlns:g='urn:import:com.google.gwt.user.client.ui'
-  xmlns:gerrit='urn:import:com.google.gerrit.client'
-  xmlns:u='urn:import:com.google.gerrit.client.ui'>
-  <ui:style gss='false'>
-    .panel {
-      padding: 8px;
-    }
-    .avatar {
-      padding-right: 4px;
-      width: 100px;
-      height: 100px;
-    }
-    .infoCell {
-      vertical-align: top;
-    }
-    .userName {
-      font-weight: bold;
-    }
-    .email {
-      padding-bottom: 6px;
-    }
-    .userLinks {
-      min-width: 250px;
-    }
-    .userLinksRight {
-      float: right;
-    }
-    .switchAccount {
-      border-right: 1px solid black;
-      padding-right: 0.5em;
-      margin-right: 0.5em;
-    }
-  </ui:style>
-
-  <g:HTMLPanel styleName='{style.panel}'>
-    <table><tr><td>
-      <gerrit:AvatarImage ui:field='avatar' styleName='{style.avatar}' />
-    </td><td class='{style.infoCell}'>
-      <g:Label ui:field='userName' styleName="{style.userName}" />
-      <g:Label ui:field='userEmail' styleName="{style.email}" />
-    </td></tr></table>
-    <div ui:field='userLinks' class='{style.userLinks}'>
-      <u:InlineHyperlink ui:field='settings' targetHistoryToken='/settings/'>
-        <ui:msg>Settings</ui:msg>
-      </u:InlineHyperlink>
-      <span class='{style.userLinksRight}'>
-        <a ui:field='switchAccount' class='{style.switchAccount}'><ui:msg>Switch Account</ui:msg></a
-        ><a ui:field='logout'><ui:msg>Sign Out</ui:msg></a>
-      </span>
-    </div>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/VoidResult.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/VoidResult.java
deleted file mode 100644
index 810ebe7..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/VoidResult.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-public final class VoidResult extends JavaScriptObject {
-  protected VoidResult() {}
-
-  public static VoidResult create() {
-    return createObject().cast();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/access/AccessMap.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/access/AccessMap.java
deleted file mode 100644
index a0060d5..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/access/AccessMap.java
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.access;
-
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import java.util.Collections;
-import java.util.Set;
-
-/** Access rights available from {@code /access/}. */
-public class AccessMap extends NativeMap<ProjectAccessInfo> {
-  public static void get(Set<Project.NameKey> projects, AsyncCallback<AccessMap> callback) {
-    RestApi api = new RestApi("/access/");
-    for (Project.NameKey p : projects) {
-      api.addParameter("project", p.get());
-    }
-    api.get(NativeMap.copyKeysIntoChildren(callback));
-  }
-
-  public static void get(Project.NameKey project, AsyncCallback<ProjectAccessInfo> cb) {
-    get(
-        Collections.singleton(project),
-        new AsyncCallback<AccessMap>() {
-          @Override
-          public void onSuccess(AccessMap result) {
-            cb.onSuccess(result.get(project.get()));
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            cb.onFailure(caught);
-          }
-        });
-  }
-
-  protected AccessMap() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/access/ProjectAccessInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/access/ProjectAccessInfo.java
deleted file mode 100644
index 88635df..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/access/ProjectAccessInfo.java
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.access;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class ProjectAccessInfo extends JavaScriptObject {
-  public final native boolean canAddRefs() /*-{ return this.can_add ? true : false; }-*/;
-
-  public final native boolean canAddTagRefs() /*-{ return this.can_add_tags ? true : false; }-*/;
-
-  public final native boolean isOwner() /*-{ return this.is_owner ? true : false; }-*/;
-
-  public final native boolean configVisible() /*-{ return this.config_visible ? true : false; }-*/;
-
-  protected ProjectAccessInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountApi.java
deleted file mode 100644
index 7f4522f..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountApi.java
+++ /dev/null
@@ -1,287 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.client.VoidResult;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.info.AgreementInfo;
-import com.google.gerrit.client.info.GpgKeyInfo;
-import com.google.gerrit.client.rpc.CallbackGroup;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.NativeString;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtorm.client.KeyUtil;
-import java.util.HashSet;
-import java.util.Set;
-
-/** A collection of static methods which work on the Gerrit REST API for specific accounts. */
-public class AccountApi {
-  public static RestApi self() {
-    return new RestApi("/accounts/").view("self");
-  }
-
-  /** Retrieve the account edit preferences */
-  public static void getEditPreferences(AsyncCallback<EditPreferences> cb) {
-    self().view("preferences.edit").get(cb);
-  }
-
-  /** Put the account edit preferences */
-  public static void putEditPreferences(EditPreferences in, AsyncCallback<EditPreferences> cb) {
-    self().view("preferences.edit").put(in, cb);
-  }
-
-  public static void suggest(String query, int limit, AsyncCallback<JsArray<AccountInfo>> cb) {
-    new RestApi("/accounts/")
-        .addParameterTrue("suggest")
-        .addParameterRaw("q", KeyUtil.encode(query))
-        .addParameter("n", limit)
-        .background()
-        .get(cb);
-  }
-
-  public static void putDiffPreferences(DiffPreferences in, AsyncCallback<DiffPreferences> cb) {
-    self().view("preferences.diff").put(in, cb);
-  }
-
-  /** Retrieve the username */
-  public static void getUsername(String account, AsyncCallback<NativeString> cb) {
-    new RestApi("/accounts/").id(account).view("username").get(cb);
-  }
-
-  /** Set the username */
-  public static void setUsername(String account, String username, AsyncCallback<NativeString> cb) {
-    UsernameInput input = UsernameInput.create();
-    input.username(username);
-    new RestApi("/accounts/").id(account).view("username").put(input, cb);
-  }
-
-  /** Retrieve the account name */
-  public static void getName(String account, AsyncCallback<NativeString> cb) {
-    new RestApi("/accounts/").id(account).view("name").get(cb);
-  }
-
-  /** Set the account name */
-  public static void setName(String account, String name, AsyncCallback<NativeString> cb) {
-    AccountNameInput input = AccountNameInput.create();
-    input.name(name);
-    new RestApi("/accounts/").id(account).view("name").put(input, cb);
-  }
-
-  /** Retrieve email addresses */
-  public static void getEmails(String account, AsyncCallback<JsArray<EmailInfo>> cb) {
-    new RestApi("/accounts/").id(account).view("emails").get(cb);
-  }
-
-  /** Register a new email address */
-  public static void registerEmail(String account, String email, AsyncCallback<EmailInfo> cb) {
-    JavaScriptObject in = JavaScriptObject.createObject();
-    new RestApi("/accounts/").id(account).view("emails").id(email).ifNoneMatch().put(in, cb);
-  }
-
-  /** Set preferred email address */
-  public static void setPreferredEmail(
-      String account, String email, AsyncCallback<NativeString> cb) {
-    new RestApi("/accounts/").id(account).view("emails").id(email).view("preferred").put(cb);
-  }
-
-  /** Retrieve SSH keys */
-  public static void getSshKeys(String account, AsyncCallback<JsArray<SshKeyInfo>> cb) {
-    new RestApi("/accounts/").id(account).view("sshkeys").get(cb);
-  }
-
-  /** Add a new SSH keys */
-  public static void addSshKey(String account, String sshPublicKey, AsyncCallback<SshKeyInfo> cb) {
-    new RestApi("/accounts/").id(account).view("sshkeys").post(sshPublicKey, cb);
-  }
-
-  /** Retrieve Watched Projects */
-  public static void getWatchedProjects(
-      String account, AsyncCallback<JsArray<ProjectWatchInfo>> cb) {
-    new RestApi("/accounts/").id(account).view("watched.projects").get(cb);
-  }
-
-  /** Create/Update Watched Project */
-  public static void updateWatchedProject(
-      String account,
-      ProjectWatchInfo watchedProjectInfo,
-      AsyncCallback<JsArray<ProjectWatchInfo>> cb) {
-    Set<ProjectWatchInfo> watchedProjectInfos = new HashSet<>();
-    watchedProjectInfos.add(watchedProjectInfo);
-    updateWatchedProjects(account, watchedProjectInfos, cb);
-  }
-
-  /** Create/Update Watched Projects */
-  public static void updateWatchedProjects(
-      String account,
-      Set<ProjectWatchInfo> watchedProjectInfos,
-      AsyncCallback<JsArray<ProjectWatchInfo>> cb) {
-    new RestApi("/accounts/")
-        .id(account)
-        .view("watched.projects")
-        .post(projectWatchArrayFromSet(watchedProjectInfos), cb);
-  }
-
-  /** Delete Watched Project */
-  public static void deleteWatchedProject(
-      String account,
-      ProjectWatchInfo watchedProjectInfo,
-      AsyncCallback<JsArray<ProjectWatchInfo>> cb) {
-    Set<ProjectWatchInfo> watchedProjectInfos = new HashSet<>();
-    watchedProjectInfos.add(watchedProjectInfo);
-    deleteWatchedProjects(account, watchedProjectInfos, cb);
-  }
-
-  /** Delete Watched Projects */
-  public static void deleteWatchedProjects(
-      String account,
-      Set<ProjectWatchInfo> watchedProjectInfos,
-      AsyncCallback<JsArray<ProjectWatchInfo>> cb) {
-    new RestApi("/accounts/")
-        .id(account)
-        .view("watched.projects:delete")
-        .post(projectWatchArrayFromSet(watchedProjectInfos), cb);
-  }
-
-  /**
-   * Delete SSH keys. For each key to be deleted a separate DELETE request is fired to the server.
-   * The {@code onSuccess} method of the provided callback is invoked once after all requests
-   * succeeded. If any request fails the callbacks' {@code onFailure} method is invoked. In a
-   * failure case it can be that still some of the keys were successfully deleted.
-   */
-  public static void deleteSshKeys(
-      String account, Set<Integer> sequenceNumbers, AsyncCallback<VoidResult> cb) {
-    CallbackGroup group = new CallbackGroup();
-    for (int seq : sequenceNumbers) {
-      new RestApi("/accounts/").id(account).view("sshkeys").id(seq).delete(group.add(cb));
-      cb = CallbackGroup.emptyCallback();
-    }
-    group.done();
-  }
-
-  /** Generate a new HTTP password */
-  public static void generateHttpPassword(String account, AsyncCallback<NativeString> cb) {
-    HttpPasswordInput in = HttpPasswordInput.create();
-    in.generate(true);
-    new RestApi("/accounts/").id(account).view("password.http").put(in, cb);
-  }
-
-  /** Retrieve account external ids */
-  public static void getExternalIds(AsyncCallback<JsArray<ExternalIdInfo>> cb) {
-    self().view("external.ids").get(cb);
-  }
-
-  /** Delete account external ids */
-  public static void deleteExternalIds(Set<String> ids, AsyncCallback<VoidResult> cb) {
-    self().view("external.ids:delete").post(Natives.arrayOf(ids), cb);
-  }
-
-  /** Enter a contributor agreement */
-  public static void enterAgreement(String account, String name, AsyncCallback<NativeString> cb) {
-    AgreementInput in = AgreementInput.create();
-    in.name(name);
-    new RestApi("/accounts/").id(account).view("agreements").put(in, cb);
-  }
-
-  private static JsArray<ProjectWatchInfo> projectWatchArrayFromSet(Set<ProjectWatchInfo> set) {
-    JsArray<ProjectWatchInfo> jsArray = JsArray.createArray().cast();
-    for (ProjectWatchInfo p : set) {
-      jsArray.push(p);
-    }
-    return jsArray;
-  }
-
-  private static class AgreementInput extends JavaScriptObject {
-    final native void name(String n) /*-{ if(n)this.name=n; }-*/;
-
-    static AgreementInput create() {
-      return createObject().cast();
-    }
-
-    protected AgreementInput() {}
-  }
-
-  private static class HttpPasswordInput extends JavaScriptObject {
-    final native void generate(boolean g) /*-{ if(g)this.generate=g; }-*/;
-
-    static HttpPasswordInput create() {
-      return createObject().cast();
-    }
-
-    protected HttpPasswordInput() {}
-  }
-
-  private static class UsernameInput extends JavaScriptObject {
-    final native void username(String u) /*-{ if(u)this.username=u; }-*/;
-
-    static UsernameInput create() {
-      return createObject().cast();
-    }
-
-    protected UsernameInput() {}
-  }
-
-  private static class AccountNameInput extends JavaScriptObject {
-    final native void name(String n) /*-{ if(n)this.name=n; }-*/;
-
-    static AccountNameInput create() {
-      return createObject().cast();
-    }
-
-    protected AccountNameInput() {}
-  }
-
-  public static void addGpgKey(
-      String account, String armored, AsyncCallback<NativeMap<GpgKeyInfo>> cb) {
-    new RestApi("/accounts/").id(account).view("gpgkeys").post(GpgKeysInput.add(armored), cb);
-  }
-
-  public static void deleteGpgKeys(
-      String account, Iterable<String> fingerprints, AsyncCallback<NativeMap<GpgKeyInfo>> cb) {
-    new RestApi("/accounts/")
-        .id(account)
-        .view("gpgkeys")
-        .post(GpgKeysInput.delete(fingerprints), cb);
-  }
-
-  /** List contributor agreements */
-  public static void getAgreements(String account, AsyncCallback<JsArray<AgreementInfo>> cb) {
-    new RestApi("/accounts/").id(account).view("agreements").get(cb);
-  }
-
-  private static class GpgKeysInput extends JavaScriptObject {
-    static GpgKeysInput add(String key) {
-      return createWithAdd(Natives.arrayOf(key));
-    }
-
-    static GpgKeysInput delete(Iterable<String> fingerprints) {
-      return createWithDelete(Natives.arrayOf(fingerprints));
-    }
-
-    private static native GpgKeysInput createWithAdd(JsArrayString keys) /*-{
-      return {'add': keys};
-    }-*/;
-
-    private static native GpgKeysInput createWithDelete(JsArrayString fingerprints) /*-{
-      return {'delete': fingerprints};
-    }-*/;
-
-    protected GpgKeysInput() {}
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountCapabilities.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountCapabilities.java
deleted file mode 100644
index d317881..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountCapabilities.java
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-/** Capabilities the caller has from {@code /accounts/self/capabilities}. */
-public class AccountCapabilities extends JavaScriptObject {
-  public static void all(AsyncCallback<AccountCapabilities> cb, String... filter) {
-    new RestApi("/accounts/self/capabilities").addParameter("q", filter).get(cb);
-  }
-
-  protected AccountCapabilities() {}
-
-  public final native boolean canPerform(String name) /*-{ return this[name] ? true : false; }-*/;
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.java
deleted file mode 100644
index 3e21619..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.java
+++ /dev/null
@@ -1,311 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gwt.i18n.client.Constants;
-
-public interface AccountConstants extends Constants {
-  String settingsHeading();
-
-  String changeAvatar();
-
-  String fullName();
-
-  String preferredEmail();
-
-  String registeredOn();
-
-  String accountId();
-
-  String diffViewLabel();
-
-  String maximumPageSizeFieldLabel();
-
-  String dateFormatLabel();
-
-  String contextWholeFile();
-
-  String showSiteHeader();
-
-  String useFlashClipboard();
-
-  String reviewCategoryLabel();
-
-  String messageShowInReviewCategoryNone();
-
-  String messageShowInReviewCategoryName();
-
-  String messageShowInReviewCategoryEmail();
-
-  String messageShowInReviewCategoryUsername();
-
-  String messageShowInReviewCategoryAbbrev();
-
-  String buttonSaveChanges();
-
-  String highlightAssigneeInChangeTable();
-
-  String showRelativeDateInChangeTable();
-
-  String showSizeBarInChangeTable();
-
-  String showLegacycidInChangeTable();
-
-  String muteCommonPathPrefixes();
-
-  String signedOffBy();
-
-  String publishCommentsOnPush();
-
-  String workInProgressByDefault();
-
-  String myMenu();
-
-  String myMenuInfo();
-
-  String myMenuName();
-
-  String myMenuUrl();
-
-  String myMenuReset();
-
-  String tabAccountSummary();
-
-  String tabAgreements();
-
-  String tabContactInformation();
-
-  String tabDiffPreferences();
-
-  String tabEditPreferences();
-
-  String tabGpgKeys();
-
-  String tabHttpAccess();
-
-  String tabMyGroups();
-
-  String tabOAuthToken();
-
-  String tabPreferences();
-
-  String tabSshKeys();
-
-  String tabWatchedProjects();
-
-  String tabWebIdentities();
-
-  String buttonShowAddSshKey();
-
-  String buttonCloseAddSshKey();
-
-  String buttonDeleteSshKey();
-
-  String buttonClearSshKeyInput();
-
-  String buttonAddSshKey();
-
-  String userName();
-
-  String password();
-
-  String buttonSetUserName();
-
-  String confirmSetUserNameTitle();
-
-  String confirmSetUserName();
-
-  String buttonClearPassword();
-
-  String buttonGeneratePassword();
-
-  String revokePassword();
-
-  String linkObtainPassword();
-
-  String linkEditFullName();
-
-  String linkReloadContact();
-
-  String invalidUserName();
-
-  String invalidUserEmail();
-
-  String labelOAuthToken();
-
-  String labelOAuthExpires();
-
-  String labelOAuthNetRCEntry();
-
-  String labelOAuthGitCookie();
-
-  String labelOAuthExpired();
-
-  String sshKeyInvalid();
-
-  String sshKeyAlgorithm();
-
-  String sshKeyKey();
-
-  String sshKeyComment();
-
-  String sshKeyStatus();
-
-  String addSshKeyPanelHeader();
-
-  String addSshKeyHelpTitle();
-
-  String addSshKeyHelp();
-
-  String sshJavaAppletNotAvailable();
-
-  String invalidSshKeyError();
-
-  String sshHostKeyTitle();
-
-  String sshHostKeyFingerprint();
-
-  String sshHostKeyKnownHostEntry();
-
-  String gpgKeyId();
-
-  String gpgKeyFingerprint();
-
-  String gpgKeyUserIds();
-
-  String webIdStatus();
-
-  String webIdEmail();
-
-  String webIdIdentity();
-
-  String untrustedProvider();
-
-  String buttonDeleteIdentity();
-
-  String buttonLinkIdentity();
-
-  String buttonWatchProject();
-
-  String defaultProjectName();
-
-  String defaultFilter();
-
-  String buttonBrowseProjects();
-
-  String projects();
-
-  String projectsClose();
-
-  String projectListOpen();
-
-  String watchedProjectName();
-
-  String watchedProjectFilter();
-
-  String watchedProjectColumnEmailNotifications();
-
-  String watchedProjectColumnNewChanges();
-
-  String watchedProjectColumnNewPatchSets();
-
-  String watchedProjectColumnAllComments();
-
-  String watchedProjectColumnSubmittedChanges();
-
-  String watchedProjectColumnAbandonedChanges();
-
-  String contactFieldFullName();
-
-  String contactFieldEmail();
-
-  String buttonOpenRegisterNewEmail();
-
-  String buttonSendRegisterNewEmail();
-
-  String buttonCancel();
-
-  String titleRegisterNewEmail();
-
-  String descRegisterNewEmail();
-
-  String errorDialogTitleRegisterNewEmail();
-
-  String emailFilterHelpTitle();
-
-  String emailFilterHelp();
-
-  String newAgreement();
-
-  String agreementName();
-
-  String agreementDescription();
-
-  String newAgreementSelectTypeHeading();
-
-  String newAgreementNoneAvailable();
-
-  String newAgreementReviewLegalHeading();
-
-  String newAgreementReviewContactHeading();
-
-  String newAgreementCompleteHeading();
-
-  String newAgreementIAGREE();
-
-  String newAgreementAlreadySubmitted();
-
-  String buttonSubmitNewAgreement();
-
-  String welcomeToGerritCodeReview();
-
-  String welcomeReviewContact();
-
-  String welcomeContactFrom();
-
-  String welcomeUsernameHeading();
-
-  String welcomeSshKeyHeading();
-
-  String welcomeSshKeyText();
-
-  String welcomeAgreementHeading();
-
-  String welcomeAgreementText();
-
-  String welcomeAgreementLater();
-
-  String welcomeContinue();
-
-  String messageEnabled();
-
-  String messageCCMeOnMyComments();
-
-  String messageDisabled();
-
-  String emailFieldLabel();
-
-  String emailFormatFieldLabel();
-
-  String messagePlaintextOnly();
-
-  String messageHtmlPlaintext();
-
-  String defaultBaseForMerges();
-
-  String autoMerge();
-
-  String firstParent();
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.properties
deleted file mode 100644
index c32efed..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.properties
+++ /dev/null
@@ -1,274 +0,0 @@
-settingsHeading = Settings
-
-changeAvatar = Change Avatar
-fullName = Full Name
-preferredEmail = Email Address
-registeredOn = Registered
-accountId = Account ID
-showSiteHeader = Show Site Header / Footer
-useFlashClipboard = Use Flash Clipboard Widget
-reviewCategoryLabel = Display In Review Category
-messageShowInReviewCategoryNone = None (default)
-messageShowInReviewCategoryName = Show Name
-messageShowInReviewCategoryEmail = Show Email
-messageShowInReviewCategoryUsername = Show Username
-messageShowInReviewCategoryAbbrev = Show Abbreviated Name
-
-emailFieldLabel = Email Notifications:
-messageCCMeOnMyComments = Every Comment
-messageEnabled = Only Comments Left By Others
-messageDisabled = None
-
-emailFormatFieldLabel = Email Format:
-messagePlaintextOnly = Plaintext Only
-messageHtmlPlaintext = HTML and Plaintext
-
-defaultBaseForMerges = Default Base For Merges:
-autoMerge = Auto Merge
-firstParent = First Parent
-
-maximumPageSizeFieldLabel = Maximum Page Size:
-diffViewLabel = Diff View:
-dateFormatLabel = Date/Time Format:
-contextWholeFile = Whole File
-buttonSaveChanges = Save Changes
-highlightAssigneeInChangeTable = Highlight Changes Assigned To Me In Changes Table
-showRelativeDateInChangeTable = Show Relative Dates In Changes Table
-showSizeBarInChangeTable = Show Change Sizes As Colored Bars
-showLegacycidInChangeTable = Show Change Number In Changes Table
-muteCommonPathPrefixes = Mute Common Path Prefixes In File List
-signedOffBy = Insert Signed-off-by Footer For Inline Edit Changes
-publishCommentsOnPush = Publish Comments On Push
-workInProgressByDefault = Set all new changes work-in-progress by default
-myMenu = My Menu
-myMenuInfo = \
-  Menu items for the 'My' top level menu. \
-  The first menu item defines the default screen.
-myMenuName = Name
-myMenuUrl = URL
-myMenuReset = Reset
-
-tabAccountSummary = Profile
-tabAgreements = Agreements
-tabContactInformation = Contact Information
-tabDiffPreferences = Diff Preferences
-tabEditPreferences = Edit Preferences
-tabGpgKeys = GPG Public Keys
-tabHttpAccess = HTTP Password
-tabOAuthToken = OAuth Token
-tabMyGroups = Groups
-tabPreferences = Preferences
-tabSshKeys = SSH Public Keys
-tabWatchedProjects = Watched Projects
-tabWebIdentities = Identities
-
-buttonShowAddSshKey = Add Key ...
-buttonCloseAddSshKey = Close
-buttonDeleteSshKey = Delete
-buttonClearSshKeyInput = Clear
-buttonAddSshKey = Add
-
-userName = Username
-password = Password
-buttonSetUserName = Select Username
-confirmSetUserNameTitle = Confirm Setting the Username
-confirmSetUserName = Setting the Username is permanent.  Are you sure?
-buttonClearPassword = Clear Password
-buttonGeneratePassword = Generate Password
-revokePassword = (click 'Generate Password' to revoke an old password)
-linkObtainPassword = Obtain Password
-linkEditFullName = Edit
-linkReloadContact = Reload
-invalidUserName = Username must contain only letters, numbers, _, - or .
-invalidUserEmail = Email format is wrong.
-
-labelOAuthToken = Access Token
-labelOAuthExpires = Expires
-labelOAuthNetRCEntry = Entry for ~/.netrc
-labelOAuthGitCookie = Entry for ~/.gitcookies
-labelOAuthExpired = To obtain an access token please sign out and sign in again.
-
-sshKeyInvalid = Invalid Key
-sshKeyAlgorithm = Algorithm
-sshKeyKey = Key
-sshKeyComment = Comment
-sshKeyStatus = Status
-
-sshHostKeyTitle = Server Host Key
-sshHostKeyFingerprint = Fingerprint:
-sshHostKeyKnownHostEntry = Entry for <code>~/.ssh/known_hosts</code>:
-
-gpgKeyId = ID
-gpgKeyFingerprint = Fingerprint
-gpgKeyUserIds = User IDs
-
-webIdStatus = Status
-webIdEmail = Email Address
-webIdIdentity = Identity
-untrustedProvider = Untrusted
-buttonDeleteIdentity = Delete
-buttonLinkIdentity = Link Another Identity
-
-addSshKeyPanelHeader = Add SSH Public Key
-addSshKeyHelpTitle = How to Generate an SSH Key
-addSshKeyHelp = \
-  <ol>\
-    <li>\
-      From the Terminal or Git Bash, run <em>ssh-keygen</em>\
-    </li>\
-    <li>\
-      Confirm the default path <em>.ssh/id_rsa</em>\
-    </li>\
-    <li>\
-      Enter a passphrase (recommended) or leave it blank.<br />\
-      Remember this passphrase, as you will need it to unlock the<br />\
-      key whenever you use it.\
-    </li>\
-    <li>\
-      Open <em>~/.ssh/id_rsa.pub</em> and copy & paste the contents into<br />\
-      the box below, then click on "Add".<br />\
-      Note that <em>id_rsa.pub</em> is your public key and can be shared,<br />\
-      while <em>id_rsa</em> is your private key and should be kept secret.\
-    </li>\
-  <\ol>
-invalidSshKeyError = Invalid SSH Key
-sshJavaAppletNotAvailable = Open Key Unavailable: Java not enabled
-
-buttonWatchProject = Watch
-defaultProjectName = Project Name
-defaultFilter = branch:name, or other search expression
-projects = All Watchable Projects
-projectsClose = Close
-buttonBrowseProjects = Browse
-projectListOpen = Watch Selected project
-watchedProjectName = Project Name
-watchedProjectFilter = Only If
-watchedProjectColumnEmailNotifications = Email Notifications
-watchedProjectColumnNewChanges = New Changes
-watchedProjectColumnNewPatchSets = New Patch Sets
-watchedProjectColumnAllComments = All Comments
-watchedProjectColumnSubmittedChanges = Submitted Changes
-watchedProjectColumnAbandonedChanges = Abandoned Changes
-
-contactFieldFullName = Full Name
-contactFieldEmail = Preferred Email
-buttonOpenRegisterNewEmail = Register New Email ...
-buttonSendRegisterNewEmail = Register
-buttonCancel = Cancel
-titleRegisterNewEmail = Register Email Address
-descRegisterNewEmail = \
-  <p>A confirmation link will be sent by email to this address.</p>\
-  <p>You must click on the link to complete the registration and make the address available for selection.</p>
-errorDialogTitleRegisterNewEmail = Email Registration Failed
-emailFilterHelpTitle = Mail Filters
-emailFilterHelp = \
-  <p>\
-    Gerrit emails include metadata about the change to support \
-    writing mail filters.\
-  </p>\
-  <p>\
-    Here are some example Gmail queries that can be used for filters or \
-    for searching through archived messages. View the \
-    <a href="https://gerrit-review.googlesource.com/Documentation/user-notify.html"\
-        target="_blank" rel="nofollow">Gerrit documentation</a> for \
-    the complete set of footers.\
-  </p>\
-  <table>\
-    <tbody>\
-      <tr><th>Name</th><th>Query</th></tr>\
-      <tr>\
-        <td>Changes requesting my review</td>\
-        <td>\
-          <code>\
-            "Gerrit-Reviewer: <em>Your Name</em>\
-            &lt;<em>your.email@example.com</em>&gt;"\
-          </code>\
-        </td>\
-      </tr>\
-      <tr>\
-        <td>Changes from a specific owner</td>\
-        <td>\
-          <code>\
-            "Gerrit-Owner: <em>Owner name</em>\
-            &lt;<em>owner.email@example.com</em>&gt;"\
-          </code>\
-        </td>\
-      </tr>\
-      <tr>\
-        <td>Changes targeting a specific branch</td>\
-        <td>\
-          <code>\
-            "Gerrit-Branch: <em>branch-name</em>"\
-          </code>\
-        </td>\
-      </tr>\
-      <tr>\
-        <td>Changes in a specific project</td>\
-        <td>\
-          <code>\
-            "Gerrit-Project: <em>project-name</em>"\
-          </code>\
-        </td>\
-      </tr>\
-      <tr>\
-        <td>Messages related to a specific Change ID</td>\
-        <td>\
-          <code>\
-            "Gerrit-Change-Id: <em>Change ID</em>"\
-          </code>\
-        </td>\
-      </tr>\
-      <tr>\
-        <td>Messages related to a specific change number</td>\
-        <td>\
-          <code>\
-            "Gerrit-Change-Number: <em>change number</em>"\
-          </code>\
-        </td>\
-      </tr>\
-    </tbody>\
-  </table>
-
-newAgreement = New Contributor Agreement
-agreementName = Name
-agreementDescription = Description
-
-newAgreementSelectTypeHeading = Select an agreement type:
-newAgreementNoneAvailable = No contributor agreements are configured.
-newAgreementReviewLegalHeading = Review the agreement:
-newAgreementReviewContactHeading = Review your contact information:
-newAgreementCompleteHeading = Complete the agreement:
-newAgreementIAGREE = I AGREE
-newAgreementAlreadySubmitted = Agreement already submitted.
-buttonSubmitNewAgreement = Submit Agreement
-
-welcomeToGerritCodeReview = Welcome to Gerrit Code Review
-welcomeReviewContact = Please review your contact information:
-welcomeContactFrom = \
-  <p>The following contact information was automatically obtained when \
-  you signed-in to the site.  This information is used to display who \
-  you are to others, and to send updates to code reviews you have either \
-  started or subscribed to.</p>
-
-welcomeUsernameHeading = Select a unique username:
-
-welcomeSshKeyHeading = Register an SSH public key:
-welcomeSshKeyText = \
-  <p>Gerrit Code Review uses \
-  <a href="http://en.wikipedia.org/wiki/Public-key_cryptography" target="_blank">public-key cryptography</a> \
-  and \
-  <a href="http://en.wikipedia.org/wiki/Secure_Shell" target="_blank">SSH</a> \
-  to authenticate \
-  you during git's push and pull commands to hosted projects.  Registering \
-  your public key allows Gerrit to identify you whenever you connect through \
-  SSH.</p>\
-  <p>This step can also be completed at a later time.</p>
-
-welcomeAgreementHeading = Complete a contributor agreement:
-welcomeAgreementText = \
-  <p>If you will be contributing code or documentation changes to projects \
-  hosted here, please consider taking a minute to review and complete \
-  a contributor agreement.</p>\
-  <p>This step can also be completed at a later time.</p>
-welcomeAgreementLater = Continue Without Agreement
-welcomeContinue = Continue
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountMessages.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountMessages.java
deleted file mode 100644
index 4cff1e2..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountMessages.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gwt.i18n.client.Messages;
-
-public interface AccountMessages extends Messages {
-  String lines(short cnt);
-
-  String rowsPerPage(int cnt);
-
-  String changeScreenServerDefault(String d);
-
-  String enterIAGREE(String iagree);
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountMessages.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountMessages.properties
deleted file mode 100644
index a8d61cf..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountMessages.properties
+++ /dev/null
@@ -1,4 +0,0 @@
-lines = {0} lines
-rowsPerPage = {0} rows per page
-changeScreenServerDefault = Server Default ({0})
-enterIAGREE = (enter {0} in the box to the left)
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelShort.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelShort.java
deleted file mode 100644
index a537063..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelShort.java
+++ /dev/null
@@ -1,484 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.client.ErrorDialog;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.rpc.CallbackGroup;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.NativeString;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.ComplexDisclosurePanel;
-import com.google.gerrit.client.ui.OnEditEnabler;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.common.errors.EmailException;
-import com.google.gerrit.extensions.client.AccountFieldName;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.event.dom.client.ChangeEvent;
-import com.google.gwt.event.dom.client.ChangeHandler;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.i18n.client.LocaleInfo;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.FormPanel;
-import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
-import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.ListBox;
-import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.globalkey.client.NpTextBox;
-import com.google.gwtexpui.user.client.AutoCenterDialogBox;
-
-class ContactPanelShort extends Composite {
-  protected final FlowPanel body;
-  protected int labelIdx;
-  protected int fieldIdx;
-  protected Button save;
-
-  private String currentEmail;
-  protected boolean haveAccount;
-  private boolean haveEmails;
-
-  NpTextBox nameTxt;
-  private ListBox emailPick;
-  private Button registerNewEmail;
-  private OnEditEnabler onEditEnabler;
-
-  ContactPanelShort() {
-    body = new FlowPanel();
-    initWidget(body);
-  }
-
-  protected void onInitUI() {
-    if (LocaleInfo.getCurrentLocale().isRTL()) {
-      labelIdx = 1;
-      fieldIdx = 0;
-    } else {
-      labelIdx = 0;
-      fieldIdx = 1;
-    }
-
-    nameTxt = new NpTextBox();
-    nameTxt.setVisibleLength(60);
-    nameTxt.setReadOnly(!canEditFullName());
-
-    emailPick = new ListBox();
-
-    final Grid infoPlainText = new Grid(2, 2);
-    infoPlainText.setStyleName(Gerrit.RESOURCES.css().infoBlock());
-    infoPlainText.addStyleName(Gerrit.RESOURCES.css().accountInfoBlock());
-
-    body.add(infoPlainText);
-
-    registerNewEmail = new Button(Util.C.buttonOpenRegisterNewEmail());
-    registerNewEmail.setEnabled(false);
-    registerNewEmail.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            doRegisterNewEmail();
-          }
-        });
-    final FlowPanel emailLine = new FlowPanel();
-    emailLine.add(emailPick);
-    if (canRegisterNewEmail()) {
-      emailLine.add(registerNewEmail);
-    }
-
-    int row = 0;
-    if (!Gerrit.info().auth().canEdit(AccountFieldName.USER_NAME)
-        && Gerrit.info().auth().siteHasUsernames()) {
-      infoPlainText.resizeRows(infoPlainText.getRowCount() + 1);
-      row(infoPlainText, row++, Util.C.userName(), new UsernameField());
-    }
-
-    if (!canEditFullName()) {
-      FlowPanel nameLine = new FlowPanel();
-      nameLine.add(nameTxt);
-      if (Gerrit.info().auth().editFullNameUrl() != null) {
-        Button edit = new Button(Util.C.linkEditFullName());
-        edit.addClickHandler(
-            new ClickHandler() {
-              @Override
-              public void onClick(ClickEvent event) {
-                Window.open(Gerrit.info().auth().editFullNameUrl(), "_blank", null);
-              }
-            });
-        nameLine.add(edit);
-      }
-      Button reload = new Button(Util.C.linkReloadContact());
-      reload.addClickHandler(
-          new ClickHandler() {
-            @Override
-            public void onClick(ClickEvent event) {
-              Window.Location.replace(Gerrit.loginRedirect(PageLinks.SETTINGS_CONTACT));
-            }
-          });
-      nameLine.add(reload);
-      row(infoPlainText, row++, Util.C.contactFieldFullName(), nameLine);
-    } else {
-      row(infoPlainText, row++, Util.C.contactFieldFullName(), nameTxt);
-    }
-    row(infoPlainText, row++, Util.C.contactFieldEmail(), emailLine);
-
-    infoPlainText.getCellFormatter().addStyleName(0, 0, Gerrit.RESOURCES.css().topmost());
-    infoPlainText.getCellFormatter().addStyleName(0, 1, Gerrit.RESOURCES.css().topmost());
-    infoPlainText
-        .getCellFormatter()
-        .addStyleName(row - 1, 0, Gerrit.RESOURCES.css().bottomheader());
-
-    save = new Button(Util.C.buttonSaveChanges());
-    save.setEnabled(false);
-    save.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            doSave();
-          }
-        });
-
-    final ComplexDisclosurePanel mailFilterHelp =
-        new ComplexDisclosurePanel(Util.C.emailFilterHelpTitle(), false);
-    mailFilterHelp.setContent(new HTML(Util.C.emailFilterHelp()));
-    body.add(mailFilterHelp);
-
-    emailPick.addChangeHandler(
-        new ChangeHandler() {
-          @Override
-          public void onChange(ChangeEvent event) {
-            final int idx = emailPick.getSelectedIndex();
-            final String v = 0 <= idx ? emailPick.getValue(idx) : null;
-            if (Util.C.buttonOpenRegisterNewEmail().equals(v)) {
-              for (int i = 0; i < emailPick.getItemCount(); i++) {
-                if (currentEmail.equals(emailPick.getValue(i))) {
-                  emailPick.setSelectedIndex(i);
-                  break;
-                }
-              }
-              doRegisterNewEmail();
-            } else {
-              save.setEnabled(true);
-            }
-          }
-        });
-
-    onEditEnabler = new OnEditEnabler(save, nameTxt);
-  }
-
-  private boolean canEditFullName() {
-    return Gerrit.info().auth().canEdit(AccountFieldName.FULL_NAME);
-  }
-
-  private boolean canRegisterNewEmail() {
-    return Gerrit.info().auth().canEdit(AccountFieldName.REGISTER_NEW_EMAIL);
-  }
-
-  void hideSaveButton() {
-    save.setVisible(false);
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-
-    onInitUI();
-    body.add(save);
-    display(Gerrit.getUserAccount());
-
-    emailPick.clear();
-    emailPick.setEnabled(false);
-    registerNewEmail.setEnabled(false);
-
-    haveAccount = false;
-    haveEmails = false;
-
-    CallbackGroup group = new CallbackGroup();
-    AccountApi.getName(
-        "self",
-        group.add(
-            new GerritCallback<NativeString>() {
-
-              @Override
-              public void onSuccess(NativeString result) {
-                nameTxt.setText(result.asString());
-                haveAccount = true;
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {}
-            }));
-
-    AccountApi.getEmails(
-        "self",
-        group.addFinal(
-            new GerritCallback<JsArray<EmailInfo>>() {
-              @Override
-              public void onSuccess(JsArray<EmailInfo> result) {
-                for (EmailInfo i : Natives.asList(result)) {
-                  emailPick.addItem(i.email());
-                  if (i.isPreferred()) {
-                    currentEmail = i.email();
-                  }
-                }
-                haveEmails = true;
-                postLoad();
-              }
-            }));
-  }
-
-  private void postLoad() {
-    if (haveAccount && haveEmails) {
-      updateEmailList();
-      registerNewEmail.setEnabled(true);
-      save.setEnabled(false);
-      onEditEnabler.updateOriginalValue(nameTxt);
-    }
-    display();
-  }
-
-  void display() {}
-
-  protected void row(Grid info, int row, String name, Widget field) {
-    info.setText(row, labelIdx, name);
-    info.setWidget(row, fieldIdx, field);
-    info.getCellFormatter().addStyleName(row, 0, Gerrit.RESOURCES.css().header());
-  }
-
-  protected void display(AccountInfo account) {
-    currentEmail = account.email();
-    nameTxt.setText(account.name());
-    save.setEnabled(false);
-    onEditEnabler.updateOriginalValue(nameTxt);
-  }
-
-  private void doRegisterNewEmail() {
-    if (!canRegisterNewEmail()) {
-      return;
-    }
-
-    final AutoCenterDialogBox box = new AutoCenterDialogBox(true, true);
-    final VerticalPanel body = new VerticalPanel();
-
-    final NpTextBox inEmail = new NpTextBox();
-    inEmail.setVisibleLength(60);
-
-    final Button register = new Button(Util.C.buttonSendRegisterNewEmail());
-    final Button cancel = new Button(Util.C.buttonCancel());
-    final FormPanel form = new FormPanel();
-    form.addSubmitHandler(
-        new FormPanel.SubmitHandler() {
-          @Override
-          public void onSubmit(SubmitEvent event) {
-            event.cancel();
-            final String addr = inEmail.getText().trim();
-            if (!addr.contains("@")) {
-              new ErrorDialog(Util.C.invalidUserEmail()).center();
-              return;
-            }
-
-            inEmail.setEnabled(false);
-            register.setEnabled(false);
-            AccountApi.registerEmail(
-                "self",
-                addr,
-                new GerritCallback<EmailInfo>() {
-                  @Override
-                  public void onSuccess(EmailInfo result) {
-                    box.hide();
-                    if (Gerrit.info().auth().isDev()) {
-                      currentEmail = addr;
-                      if (emailPick.getItemCount() == 0) {
-                        AccountInfo me = Gerrit.getUserAccount();
-                        me.email(addr);
-                        onSaveSuccess(me);
-                      } else {
-                        save.setEnabled(true);
-                      }
-                      updateEmailList();
-                    }
-                  }
-
-                  @Override
-                  public void onFailure(Throwable caught) {
-                    inEmail.setEnabled(true);
-                    register.setEnabled(true);
-                    if (caught.getMessage().startsWith(EmailException.MESSAGE)) {
-                      final ErrorDialog d =
-                          new ErrorDialog(
-                              caught.getMessage().substring(EmailException.MESSAGE.length()));
-                      d.setText(Util.C.errorDialogTitleRegisterNewEmail());
-                      d.center();
-                    } else {
-                      super.onFailure(caught);
-                    }
-                  }
-                });
-          }
-        });
-    form.setWidget(body);
-
-    register.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            form.submit();
-          }
-        });
-    cancel.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            box.hide();
-          }
-        });
-
-    final FlowPanel buttons = new FlowPanel();
-    buttons.setStyleName(Gerrit.RESOURCES.css().patchSetActions());
-    buttons.add(register);
-    buttons.add(cancel);
-
-    if (!Gerrit.info().auth().isDev()) {
-      body.add(new HTML(Util.C.descRegisterNewEmail()));
-    }
-    body.add(inEmail);
-    body.add(buttons);
-
-    box.setText(Util.C.titleRegisterNewEmail());
-    box.setWidget(form);
-    box.center();
-    inEmail.setFocus(true);
-  }
-
-  void doSave() {
-    final String newName;
-    String name = canEditFullName() ? nameTxt.getText() : null;
-    if (name != null && name.trim().isEmpty()) {
-      newName = null;
-    } else {
-      newName = name;
-    }
-
-    final String newEmail;
-    if (emailPick.isEnabled() && emailPick.getSelectedIndex() >= 0) {
-      final String v = emailPick.getValue(emailPick.getSelectedIndex());
-      if (Util.C.buttonOpenRegisterNewEmail().equals(v)) {
-        newEmail = currentEmail;
-      } else {
-        newEmail = v;
-      }
-    } else {
-      newEmail = currentEmail;
-    }
-
-    save.setEnabled(false);
-    registerNewEmail.setEnabled(false);
-
-    CallbackGroup group = new CallbackGroup();
-    if (currentEmail != null && !newEmail.equals(currentEmail)) {
-      AccountApi.setPreferredEmail(
-          "self",
-          newEmail,
-          group.add(
-              new GerritCallback<NativeString>() {
-                @Override
-                public void onSuccess(NativeString result) {}
-              }));
-    }
-    AccountApi.setName(
-        "self",
-        newName,
-        group.add(
-            new GerritCallback<NativeString>() {
-              @Override
-              public void onSuccess(NativeString result) {}
-
-              @Override
-              public void onFailure(Throwable caught) {
-                save.setEnabled(true);
-                registerNewEmail.setEnabled(true);
-                super.onFailure(caught);
-              }
-            }));
-    group.done();
-    group.addListener(
-        new GerritCallback<Void>() {
-          @Override
-          public void onSuccess(Void result) {
-            currentEmail = newEmail;
-            AccountInfo me = Gerrit.getUserAccount();
-            me.email(currentEmail);
-            me.name(newName);
-            onSaveSuccess(me);
-            registerNewEmail.setEnabled(true);
-          }
-        });
-  }
-
-  void onSaveSuccess(AccountInfo result) {
-    AccountInfo me = Gerrit.getUserAccount();
-    me.name(result.name());
-    me.email(result.email());
-    Gerrit.refreshMenuBar();
-    display(me);
-  }
-
-  private int emailListIndexOf(String value) {
-    for (int i = 0; i < emailPick.getItemCount(); i++) {
-      if (value.equalsIgnoreCase(emailPick.getValue(i))) {
-        return i;
-      }
-    }
-    return -1;
-  }
-
-  private void updateEmailList() {
-    if (currentEmail != null) {
-      int index = emailListIndexOf(currentEmail);
-      if (index == -1) {
-        emailPick.addItem(currentEmail);
-        emailPick.setSelectedIndex(emailPick.getItemCount() - 1);
-      } else {
-        emailPick.setSelectedIndex(index);
-      }
-    }
-    if (emailPick.getItemCount() > 0) {
-      if (currentEmail == null) {
-        int index = emailListIndexOf("");
-        if (index != -1) {
-          emailPick.removeItem(index);
-        }
-        emailPick.insertItem("", 0);
-        emailPick.setSelectedIndex(0);
-      }
-      emailPick.setVisible(true);
-      emailPick.setEnabled(true);
-      if (canRegisterNewEmail()) {
-        final String t = Util.C.buttonOpenRegisterNewEmail();
-        int index = emailListIndexOf(t);
-        if (index != -1) {
-          emailPick.removeItem(index);
-        }
-        emailPick.addItem("... " + t + "  ", t);
-      }
-    } else {
-      emailPick.setVisible(false);
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/DiffPreferences.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/DiffPreferences.java
deleted file mode 100644
index 286d29a..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/DiffPreferences.java
+++ /dev/null
@@ -1,226 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.extensions.client.DiffPreferencesInfo;
-import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace;
-import com.google.gerrit.extensions.client.Theme;
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class DiffPreferences extends JavaScriptObject {
-  public static DiffPreferences create(DiffPreferencesInfo in) {
-    if (in == null) {
-      in = DiffPreferencesInfo.defaults();
-    }
-    DiffPreferences p = createObject().cast();
-    p.ignoreWhitespace(in.ignoreWhitespace);
-    p.tabSize(in.tabSize);
-    p.lineLength(in.lineLength);
-    p.cursorBlinkRate(in.cursorBlinkRate);
-    p.context(in.context);
-    p.intralineDifference(in.intralineDifference);
-    p.showLineEndings(in.showLineEndings);
-    p.showTabs(in.showTabs);
-    p.showWhitespaceErrors(in.showWhitespaceErrors);
-    p.syntaxHighlighting(in.syntaxHighlighting);
-    p.hideTopMenu(in.hideTopMenu);
-    p.autoHideDiffTableHeader(in.autoHideDiffTableHeader);
-    p.hideLineNumbers(in.hideLineNumbers);
-    p.expandAllComments(in.expandAllComments);
-    p.manualReview(in.manualReview);
-    p.renderEntireFile(in.renderEntireFile);
-    p.theme(in.theme);
-    p.hideEmptyPane(in.hideEmptyPane);
-    p.retainHeader(in.retainHeader);
-    p.skipUnchanged(in.skipUnchanged);
-    p.skipUncommented(in.skipUncommented);
-    p.skipDeleted(in.skipDeleted);
-    p.matchBrackets(in.matchBrackets);
-    p.lineWrapping(in.lineWrapping);
-    return p;
-  }
-
-  public final void copyTo(DiffPreferencesInfo p) {
-    p.context = context();
-    p.tabSize = tabSize();
-    p.lineLength = lineLength();
-    p.cursorBlinkRate = cursorBlinkRate();
-    p.expandAllComments = expandAllComments();
-    p.intralineDifference = intralineDifference();
-    p.manualReview = manualReview();
-    p.retainHeader = retainHeader();
-    p.showLineEndings = showLineEndings();
-    p.showTabs = showTabs();
-    p.showWhitespaceErrors = showWhitespaceErrors();
-    p.skipDeleted = skipDeleted();
-    p.skipUnchanged = skipUnchanged();
-    p.skipUncommented = skipUncommented();
-    p.syntaxHighlighting = syntaxHighlighting();
-    p.hideTopMenu = hideTopMenu();
-    p.autoHideDiffTableHeader = autoHideDiffTableHeader();
-    p.hideLineNumbers = hideLineNumbers();
-    p.renderEntireFile = renderEntireFile();
-    p.hideEmptyPane = hideEmptyPane();
-    p.matchBrackets = matchBrackets();
-    p.lineWrapping = lineWrapping();
-    p.theme = theme();
-    p.ignoreWhitespace = ignoreWhitespace();
-  }
-
-  public final void ignoreWhitespace(Whitespace i) {
-    setIgnoreWhitespaceRaw(i.toString());
-  }
-
-  public final void theme(Theme i) {
-    setThemeRaw(i != null ? i.toString() : Theme.DEFAULT.toString());
-  }
-
-  public final void showLineNumbers(boolean s) {
-    hideLineNumbers(!s);
-  }
-
-  public final Whitespace ignoreWhitespace() {
-    String s = ignoreWhitespaceRaw();
-    return s != null ? Whitespace.valueOf(s) : Whitespace.IGNORE_NONE;
-  }
-
-  public final Theme theme() {
-    String s = themeRaw();
-    return s != null ? Theme.valueOf(s) : Theme.DEFAULT;
-  }
-
-  public final int tabSize() {
-    return get("tab_size", 8);
-  }
-
-  public final int context() {
-    return get("context", 10);
-  }
-
-  public final int lineLength() {
-    return get("line_length", 100);
-  }
-
-  public final int cursorBlinkRate() {
-    return get("cursor_blink_rate", 0);
-  }
-
-  public final boolean showLineNumbers() {
-    return !hideLineNumbers();
-  }
-
-  public final boolean autoReview() {
-    return !manualReview();
-  }
-
-  public final native void tabSize(int t) /*-{ this.tab_size = t }-*/;
-
-  public final native void lineLength(int c) /*-{ this.line_length = c }-*/;
-
-  public final native void context(int c) /*-{ this.context = c }-*/;
-
-  public final native void cursorBlinkRate(int r) /*-{ this.cursor_blink_rate = r }-*/;
-
-  public final native void intralineDifference(Boolean i) /*-{ this.intraline_difference = i }-*/;
-
-  public final native void showLineEndings(Boolean s) /*-{ this.show_line_endings = s }-*/;
-
-  public final native void showTabs(Boolean s) /*-{ this.show_tabs = s }-*/;
-
-  public final native void showWhitespaceErrors(
-      Boolean s) /*-{ this.show_whitespace_errors = s }-*/;
-
-  public final native void syntaxHighlighting(Boolean s) /*-{ this.syntax_highlighting = s }-*/;
-
-  public final native void hideTopMenu(Boolean s) /*-{ this.hide_top_menu = s }-*/;
-
-  public final native void autoHideDiffTableHeader(
-      Boolean s) /*-{ this.auto_hide_diff_table_header = s }-*/;
-
-  public final native void hideLineNumbers(Boolean s) /*-{ this.hide_line_numbers = s }-*/;
-
-  public final native void expandAllComments(Boolean e) /*-{ this.expand_all_comments = e }-*/;
-
-  public final native void manualReview(Boolean r) /*-{ this.manual_review = r }-*/;
-
-  public final native void renderEntireFile(Boolean r) /*-{ this.render_entire_file = r }-*/;
-
-  public final native void retainHeader(Boolean r) /*-{ this.retain_header = r }-*/;
-
-  public final native void hideEmptyPane(Boolean s) /*-{ this.hide_empty_pane = s }-*/;
-
-  public final native void skipUnchanged(Boolean s) /*-{ this.skip_unchanged = s }-*/;
-
-  public final native void skipUncommented(Boolean s) /*-{ this.skip_uncommented = s }-*/;
-
-  public final native void skipDeleted(Boolean s) /*-{ this.skip_deleted = s }-*/;
-
-  public final native void matchBrackets(Boolean m) /*-{ this.match_brackets = m }-*/;
-
-  public final native void lineWrapping(Boolean w) /*-{ this.line_wrapping = w }-*/;
-
-  public final native boolean
-      intralineDifference() /*-{ return this.intraline_difference || false }-*/;
-
-  public final native boolean showLineEndings() /*-{ return this.show_line_endings || false }-*/;
-
-  public final native boolean showTabs() /*-{ return this.show_tabs || false }-*/;
-
-  public final native boolean
-      showWhitespaceErrors() /*-{ return this.show_whitespace_errors || false }-*/;
-
-  public final native boolean
-      syntaxHighlighting() /*-{ return this.syntax_highlighting || false }-*/;
-
-  public final native boolean hideTopMenu() /*-{ return this.hide_top_menu || false }-*/;
-
-  public final native boolean
-      autoHideDiffTableHeader() /*-{ return this.auto_hide_diff_table_header || false }-*/;
-
-  public final native boolean hideLineNumbers() /*-{ return this.hide_line_numbers || false }-*/;
-
-  public final native boolean
-      expandAllComments() /*-{ return this.expand_all_comments || false }-*/;
-
-  public final native boolean manualReview() /*-{ return this.manual_review || false }-*/;
-
-  public final native boolean renderEntireFile() /*-{ return this.render_entire_file || false }-*/;
-
-  public final native boolean hideEmptyPane() /*-{ return this.hide_empty_pane || false }-*/;
-
-  public final native boolean retainHeader() /*-{ return this.retain_header || false }-*/;
-
-  public final native boolean skipUnchanged() /*-{ return this.skip_unchanged || false }-*/;
-
-  public final native boolean skipUncommented() /*-{ return this.skip_uncommented || false }-*/;
-
-  public final native boolean skipDeleted() /*-{ return this.skip_deleted || false }-*/;
-
-  public final native boolean matchBrackets() /*-{ return this.match_brackets || false }-*/;
-
-  public final native boolean lineWrapping() /*-{ return this.line_wrapping || false }-*/;
-
-  private native void setThemeRaw(String i) /*-{ this.theme = i }-*/;
-
-  private native void setIgnoreWhitespaceRaw(String i) /*-{ this.ignore_whitespace = i }-*/;
-
-  private native String ignoreWhitespaceRaw() /*-{ return this.ignore_whitespace }-*/;
-
-  private native String themeRaw() /*-{ return this.theme }-*/;
-
-  private native int get(String n, int d) /*-{ return this.hasOwnProperty(n) ? this[n] : d }-*/;
-
-  protected DiffPreferences() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/EditPreferences.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/EditPreferences.java
deleted file mode 100644
index 9cd2f17..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/EditPreferences.java
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.extensions.client.EditPreferencesInfo;
-import com.google.gerrit.extensions.client.KeyMapType;
-import com.google.gerrit.extensions.client.Theme;
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class EditPreferences extends JavaScriptObject {
-  public static EditPreferences create(EditPreferencesInfo in) {
-    EditPreferences p = createObject().cast();
-    p.tabSize(in.tabSize);
-    p.lineLength(in.lineLength);
-    p.indentUnit(in.indentUnit);
-    p.cursorBlinkRate(in.cursorBlinkRate);
-    p.hideTopMenu(in.hideTopMenu);
-    p.showTabs(in.showTabs);
-    p.showWhitespaceErrors(in.showWhitespaceErrors);
-    p.syntaxHighlighting(in.syntaxHighlighting);
-    p.hideLineNumbers(in.hideLineNumbers);
-    p.matchBrackets(in.matchBrackets);
-    p.lineWrapping(in.lineWrapping);
-    p.indentWithTabs(in.indentWithTabs);
-    p.autoCloseBrackets(in.autoCloseBrackets);
-    p.showBase(in.showBase);
-    p.theme(in.theme);
-    p.keyMapType(in.keyMapType);
-    return p;
-  }
-
-  public final EditPreferencesInfo copyTo(EditPreferencesInfo p) {
-    p.tabSize = tabSize();
-    p.lineLength = lineLength();
-    p.indentUnit = indentUnit();
-    p.cursorBlinkRate = cursorBlinkRate();
-    p.hideTopMenu = hideTopMenu();
-    p.showTabs = showTabs();
-    p.showWhitespaceErrors = showWhitespaceErrors();
-    p.syntaxHighlighting = syntaxHighlighting();
-    p.hideLineNumbers = hideLineNumbers();
-    p.matchBrackets = matchBrackets();
-    p.lineWrapping = lineWrapping();
-    p.indentWithTabs = indentWithTabs();
-    p.autoCloseBrackets = autoCloseBrackets();
-    p.showBase = showBase();
-    p.theme = theme();
-    p.keyMapType = keyMapType();
-    return p;
-  }
-
-  public final void theme(Theme i) {
-    setThemeRaw(i != null ? i.toString() : Theme.DEFAULT.toString());
-  }
-
-  private native void setThemeRaw(String i) /*-{ this.theme = i }-*/;
-
-  public final void keyMapType(KeyMapType i) {
-    setkeyMapTypeRaw(i != null ? i.toString() : KeyMapType.DEFAULT.toString());
-  }
-
-  private native void setkeyMapTypeRaw(String i) /*-{ this.key_map_type = i }-*/;
-
-  public final native void tabSize(int t) /*-{ this.tab_size = t }-*/;
-
-  public final native void lineLength(int c) /*-{ this.line_length = c }-*/;
-
-  public final native void indentUnit(int c) /*-{ this.indent_unit = c }-*/;
-
-  public final native void cursorBlinkRate(int r) /*-{ this.cursor_blink_rate = r }-*/;
-
-  public final native void hideTopMenu(boolean s) /*-{ this.hide_top_menu = s }-*/;
-
-  public final native void showTabs(boolean s) /*-{ this.show_tabs = s }-*/;
-
-  public final native void showWhitespaceErrors(
-      boolean s) /*-{ this.show_whitespace_errors = s }-*/;
-
-  public final native void syntaxHighlighting(boolean s) /*-{ this.syntax_highlighting = s }-*/;
-
-  public final native void hideLineNumbers(boolean s) /*-{ this.hide_line_numbers = s }-*/;
-
-  public final native void matchBrackets(boolean m) /*-{ this.match_brackets = m }-*/;
-
-  public final native void lineWrapping(boolean w) /*-{ this.line_wrapping = w }-*/;
-
-  public final native void indentWithTabs(boolean w) /*-{ this.indent_with_tabs = w }-*/;
-
-  public final native void autoCloseBrackets(boolean c) /*-{ this.auto_close_brackets = c }-*/;
-
-  public final native void showBase(boolean s) /*-{ this.show_base = s }-*/;
-
-  public final Theme theme() {
-    String s = themeRaw();
-    return s != null ? Theme.valueOf(s) : Theme.DEFAULT;
-  }
-
-  private native String themeRaw() /*-{ return this.theme }-*/;
-
-  public final KeyMapType keyMapType() {
-    String s = keyMapTypeRaw();
-    return s != null ? KeyMapType.valueOf(s) : KeyMapType.DEFAULT;
-  }
-
-  private native String keyMapTypeRaw() /*-{ return this.key_map_type }-*/;
-
-  public final int tabSize() {
-    return get("tab_size", 8);
-  }
-
-  public final int lineLength() {
-    return get("line_length", 100);
-  }
-
-  public final int indentUnit() {
-    return get("indent_unit", 2);
-  }
-
-  public final int cursorBlinkRate() {
-    return get("cursor_blink_rate", 0);
-  }
-
-  public final native boolean hideTopMenu() /*-{ return this.hide_top_menu || false }-*/;
-
-  public final native boolean showTabs() /*-{ return this.show_tabs || false }-*/;
-
-  public final native boolean
-      showWhitespaceErrors() /*-{ return this.show_whitespace_errors || false }-*/;
-
-  public final native boolean
-      syntaxHighlighting() /*-{ return this.syntax_highlighting || false }-*/;
-
-  public final native boolean hideLineNumbers() /*-{ return this.hide_line_numbers || false }-*/;
-
-  public final native boolean matchBrackets() /*-{ return this.match_brackets || false }-*/;
-
-  public final native boolean lineWrapping() /*-{ return this.line_wrapping || false }-*/;
-
-  public final native boolean indentWithTabs() /*-{ return this.indent_with_tabs || false }-*/;
-
-  public final native boolean
-      autoCloseBrackets() /*-{ return this.auto_close_brackets || false }-*/;
-
-  public final native boolean showBase() /*-{ return this.show_base || false }-*/;
-
-  private native int get(String n, int d) /*-{ return this.hasOwnProperty(n) ? this[n] : d }-*/;
-
-  protected EditPreferences() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/EmailInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/EmailInfo.java
deleted file mode 100644
index 9c324be..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/EmailInfo.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class EmailInfo extends JavaScriptObject {
-  public final native String email() /*-{ return this.email; }-*/;
-
-  public final native boolean isPreferred() /*-{ return this['preferred'] ? true : false; }-*/;
-
-  public final native boolean
-      isConfirmationPending() /*-{ return this['pending_confirmation'] ? true : false; }-*/;
-
-  protected EmailInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ExternalIdInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ExternalIdInfo.java
deleted file mode 100644
index 4ac0716..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ExternalIdInfo.java
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright (C) 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.client.auth.openid.OpenIdUtil;
-import com.google.gerrit.common.auth.openid.OpenIdUrls;
-import com.google.gerrit.extensions.client.AuthType;
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class ExternalIdInfo extends JavaScriptObject implements Comparable<ExternalIdInfo> {
-  /**
-   * Scheme used for {@link AuthType#LDAP}, {@link AuthType#CLIENT_SSL_CERT_LDAP}, {@link
-   * AuthType#HTTP_LDAP}, and {@link AuthType#LDAP_BIND} usernames.
-   *
-   * <p>The name {@code gerrit:} was a very poor choice.
-   */
-  private static final String SCHEME_GERRIT = "gerrit:";
-
-  /** Scheme used to represent only an email address. */
-  private static final String SCHEME_MAILTO = "mailto:";
-
-  /** Scheme for the username used to authenticate an account, e.g. over SSH. */
-  private static final String SCHEME_USERNAME = "username:";
-
-  public final native String identity() /*-{ return this.identity; }-*/;
-
-  public final native String emailAddress() /*-{ return this.email_address; }-*/;
-
-  public final native boolean isTrusted() /*-{ return this['trusted'] ? true : false; }-*/;
-
-  public final native boolean canDelete() /*-{ return this['can_delete'] ? true : false; }-*/;
-
-  public final boolean isUsername() {
-    return isScheme(SCHEME_USERNAME);
-  }
-
-  public final String describe() {
-    if (isScheme(SCHEME_GERRIT)) {
-      // A local user identity should just be itself.
-      return getSchemeRest();
-    } else if (isScheme(SCHEME_USERNAME)) {
-      // A local user identity should just be itself.
-      return getSchemeRest();
-    } else if (isScheme(SCHEME_MAILTO)) {
-      // Describe a mailto address as just its email address,
-      // which is already shown in the email address field.
-      return "";
-    } else if (isScheme(OpenIdUrls.URL_LAUNCHPAD)) {
-      return OpenIdUtil.C.nameLaunchpad();
-    } else if (isScheme(OpenIdUrls.URL_YAHOO)) {
-      return OpenIdUtil.C.nameYahoo();
-    }
-
-    return identity();
-  }
-
-  @Override
-  public final int compareTo(ExternalIdInfo a) {
-    return emailOf(this).compareTo(emailOf(a));
-  }
-
-  private boolean isScheme(String scheme) {
-    return identity() != null && identity().startsWith(scheme);
-  }
-
-  private String getSchemeRest() {
-    int colonIdx = identity().indexOf(':');
-    String scheme = (colonIdx > 0) ? identity().substring(0, colonIdx) : null;
-    return scheme != null ? identity().substring(scheme.length() + 1) : null;
-  }
-
-  private String emailOf(ExternalIdInfo a) {
-    return a.emailAddress() != null ? a.emailAddress() : "";
-  }
-
-  protected ExternalIdInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyAgreementsScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyAgreementsScreen.java
deleted file mode 100644
index 4592b62..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyAgreementsScreen.java
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.info.AgreementInfo;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gerrit.client.ui.FancyFlexTable;
-import com.google.gerrit.client.ui.Hyperlink;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.common.data.ContributorAgreement;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
-import java.util.List;
-
-public class MyAgreementsScreen extends SettingsScreen {
-  private AgreementTable agreements;
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-
-    agreements = new AgreementTable();
-    add(agreements);
-    add(new Hyperlink(Util.C.newAgreement(), PageLinks.SETTINGS_NEW_AGREEMENT));
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    AccountApi.getAgreements(
-        "self",
-        new ScreenLoadCallback<JsArray<AgreementInfo>>(this) {
-          @Override
-          public void preDisplay(JsArray<AgreementInfo> result) {
-            agreements.display(Natives.asList(result));
-          }
-        });
-  }
-
-  private static class AgreementTable extends FancyFlexTable<ContributorAgreement> {
-    AgreementTable() {
-      table.setWidth("");
-      table.setText(0, 1, Util.C.agreementName());
-      table.setText(0, 2, Util.C.agreementDescription());
-
-      FlexCellFormatter fmt = table.getFlexCellFormatter();
-      for (int c = 1; c < 3; c++) {
-        fmt.addStyleName(0, c, Gerrit.RESOURCES.css().dataHeader());
-      }
-    }
-
-    void display(List<AgreementInfo> result) {
-      while (1 < table.getRowCount()) {
-        table.removeRow(table.getRowCount() - 1);
-      }
-
-      for (AgreementInfo info : result) {
-        addOne(info);
-      }
-    }
-
-    void addOne(AgreementInfo info) {
-      int row = table.getRowCount();
-      table.insertRow(row);
-      applyDataRowStyle(row);
-
-      String url = info.url();
-      if (url != null && url.length() > 0) {
-        Anchor a = new Anchor(info.name(), url);
-        a.setTarget("_blank");
-        table.setWidget(row, 1, a);
-      } else {
-        table.setText(row, 1, info.name());
-      }
-      table.setText(row, 2, info.description());
-      FlexCellFormatter fmt = table.getFlexCellFormatter();
-      for (int c = 1; c < 3; c++) {
-        fmt.addStyleName(row, c, Gerrit.RESOURCES.css().dataCell());
-      }
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyContactInformationScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyContactInformationScreen.java
deleted file mode 100644
index d5884f4..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyContactInformationScreen.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-public class MyContactInformationScreen extends SettingsScreen {
-  private ContactPanelShort panel;
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    panel =
-        new ContactPanelShort() {
-          @Override
-          void display() {
-            MyContactInformationScreen.this.display();
-          }
-        };
-    add(panel);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyDiffPreferencesScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyDiffPreferencesScreen.java
deleted file mode 100644
index a721441..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyDiffPreferencesScreen.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.diff.PreferencesBox;
-import com.google.gwt.user.client.ui.FlowPanel;
-
-public class MyDiffPreferencesScreen extends SettingsScreen {
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-
-    PreferencesBox pb = new PreferencesBox(null);
-    pb.set(DiffPreferences.create(Gerrit.getDiffPreferences()));
-    FlowPanel p = new FlowPanel();
-    p.setStyleName(pb.getStyle().dialog());
-    p.add(pb);
-    add(p);
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    display();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyEditPreferencesScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyEditPreferencesScreen.java
deleted file mode 100644
index 424b5d5..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyEditPreferencesScreen.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.editor.EditPreferencesBox;
-import com.google.gwt.user.client.ui.FlowPanel;
-
-public class MyEditPreferencesScreen extends SettingsScreen {
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-
-    EditPreferencesBox pb = new EditPreferencesBox(null);
-    pb.set(EditPreferences.create(Gerrit.getEditPreferences()));
-    FlowPanel p = new FlowPanel();
-    p.setStyleName(pb.getStyle().dialog());
-    p.add(pb);
-    add(p);
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    display();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyGpgKeysScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyGpgKeysScreen.java
deleted file mode 100644
index 1a0090a..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyGpgKeysScreen.java
+++ /dev/null
@@ -1,289 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import static java.util.Comparator.comparing;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.info.GpgKeyInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.FancyFlexTable;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.logical.shared.ValueChangeHandler;
-import com.google.gwt.http.client.Response;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.rpc.StatusCodeException;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.InlineLabel;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwtexpui.clippy.client.CopyableLabel;
-import com.google.gwtexpui.globalkey.client.NpTextArea;
-import java.util.ArrayList;
-import java.util.List;
-
-public class MyGpgKeysScreen extends SettingsScreen {
-  interface Binder extends UiBinder<HTMLPanel, MyGpgKeysScreen> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  @UiField(provided = true)
-  GpgKeyTable keys;
-
-  @UiField Button deleteKey;
-  @UiField Button addKey;
-
-  @UiField VerticalPanel addKeyBlock;
-  @UiField NpTextArea keyText;
-
-  @UiField VerticalPanel errorPanel;
-  @UiField Label errorText;
-
-  @UiField Button clearButton;
-  @UiField Button addButton;
-  @UiField Button closeButton;
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    keys = new GpgKeyTable();
-    add(uiBinder.createAndBindUi(this));
-    keys.updateDeleteButton();
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    refreshKeys();
-  }
-
-  @UiHandler("deleteKey")
-  void onDeleteKey(@SuppressWarnings("unused") ClickEvent e) {
-    keys.deleteChecked();
-  }
-
-  @UiHandler("addKey")
-  void onAddKey(@SuppressWarnings("unused") ClickEvent e) {
-    showAddKeyBlock(true);
-  }
-
-  @UiHandler("clearButton")
-  void onClearButton(@SuppressWarnings("unused") ClickEvent e) {
-    keyText.setText("");
-    keyText.setFocus(true);
-    errorPanel.setVisible(false);
-  }
-
-  @UiHandler("closeButton")
-  void onCloseButton(@SuppressWarnings("unused") ClickEvent e) {
-    showAddKeyBlock(false);
-  }
-
-  @UiHandler("addButton")
-  void onAddButton(@SuppressWarnings("unused") ClickEvent e) {
-    doAddKey();
-  }
-
-  private void refreshKeys() {
-    AccountApi.self()
-        .view("gpgkeys")
-        .get(
-            NativeMap.copyKeysIntoChildren(
-                "id",
-                new GerritCallback<NativeMap<GpgKeyInfo>>() {
-                  @Override
-                  public void onSuccess(NativeMap<GpgKeyInfo> result) {
-                    List<GpgKeyInfo> list = Natives.asList(result.values());
-                    // TODO(dborowitz): Sort on something more meaningful, like
-                    // created date?
-                    list.sort(comparing(GpgKeyInfo::id));
-                    keys.clear();
-                    keyText.setText("");
-                    errorPanel.setVisible(false);
-                    addButton.setEnabled(true);
-                    if (!list.isEmpty()) {
-                      keys.setVisible(true);
-                      for (GpgKeyInfo k : list) {
-                        keys.addOneKey(k);
-                      }
-                      showKeyTable(true);
-                      showAddKeyBlock(false);
-                    } else {
-                      keys.setVisible(false);
-                      showAddKeyBlock(true);
-                      showKeyTable(false);
-                    }
-
-                    display();
-                  }
-                }));
-  }
-
-  private void showAddKeyBlock(boolean show) {
-    addKey.setVisible(!show);
-    addKeyBlock.setVisible(show);
-  }
-
-  private void showKeyTable(boolean show) {
-    keys.setVisible(show);
-    deleteKey.setVisible(show);
-    addKey.setVisible(show);
-  }
-
-  private void doAddKey() {
-    if (keyText.getText().isEmpty()) {
-      return;
-    }
-    addButton.setEnabled(false);
-    keyText.setEnabled(false);
-    AccountApi.addGpgKey(
-        "self",
-        keyText.getText(),
-        new AsyncCallback<NativeMap<GpgKeyInfo>>() {
-          @Override
-          public void onSuccess(NativeMap<GpgKeyInfo> result) {
-            keyText.setEnabled(true);
-            refreshKeys();
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            keyText.setEnabled(true);
-            addButton.setEnabled(true);
-            if (caught instanceof StatusCodeException) {
-              StatusCodeException sce = (StatusCodeException) caught;
-              if (sce.getStatusCode() == Response.SC_CONFLICT
-                  || sce.getStatusCode() == Response.SC_BAD_REQUEST) {
-                errorText.setText(sce.getEncodedResponse());
-              } else {
-                errorText.setText(sce.getMessage());
-              }
-            } else {
-              errorText.setText("Unexpected error saving key: " + caught.getMessage());
-            }
-            errorPanel.setVisible(true);
-          }
-        });
-  }
-
-  private class GpgKeyTable extends FancyFlexTable<GpgKeyInfo> {
-    private final ValueChangeHandler<Boolean> updateDeleteHandler;
-
-    GpgKeyTable() {
-      table.setWidth("");
-      table.setText(0, 1, Util.C.gpgKeyId());
-      table.setText(0, 2, Util.C.gpgKeyFingerprint());
-      table.setText(0, 3, Util.C.gpgKeyUserIds());
-
-      FlexCellFormatter fmt = table.getFlexCellFormatter();
-      fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().iconHeader());
-      fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().dataHeader());
-      fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader());
-      fmt.addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader());
-
-      updateDeleteHandler =
-          new ValueChangeHandler<Boolean>() {
-            @Override
-            public void onValueChange(ValueChangeEvent<Boolean> event) {
-              updateDeleteButton();
-            }
-          };
-    }
-
-    private void addOneKey(GpgKeyInfo k) {
-      int row = table.getRowCount();
-      table.insertRow(row);
-      applyDataRowStyle(row);
-
-      CheckBox sel = new CheckBox();
-      sel.addValueChangeHandler(updateDeleteHandler);
-      table.setWidget(row, 0, sel);
-      table.setWidget(row, 1, new CopyableLabel(k.id()));
-      table.setText(row, 2, k.fingerprint());
-
-      VerticalPanel userIds = new VerticalPanel();
-      for (int i = 0; i < k.userIds().length(); i++) {
-        userIds.add(new InlineLabel(k.userIds().get(i)));
-      }
-      table.setWidget(row, 3, userIds);
-
-      FlexCellFormatter fmt = table.getFlexCellFormatter();
-      fmt.addStyleName(row, 0, Gerrit.RESOURCES.css().iconCell());
-      fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().dataCell());
-      fmt.addStyleName(row, 2, Gerrit.RESOURCES.css().dataCell());
-      fmt.addStyleName(row, 3, Gerrit.RESOURCES.css().dataCell());
-
-      setRowItem(row, k);
-    }
-
-    private void updateDeleteButton() {
-      for (int row = 1; row < table.getRowCount(); row++) {
-        if (isChecked(row)) {
-          deleteKey.setEnabled(true);
-          return;
-        }
-      }
-      deleteKey.setEnabled(false);
-    }
-
-    private void deleteChecked() {
-      deleteKey.setEnabled(false);
-      List<String> toDelete = new ArrayList<>(table.getRowCount());
-      for (int row = 1; row < table.getRowCount(); row++) {
-        if (isChecked(row)) {
-          toDelete.add(getRowItem(row).fingerprint());
-        }
-      }
-      AccountApi.deleteGpgKeys(
-          "self",
-          toDelete,
-          new GerritCallback<NativeMap<GpgKeyInfo>>() {
-            @Override
-            public void onSuccess(NativeMap<GpgKeyInfo> result) {
-              refreshKeys();
-            }
-
-            @Override
-            public void onFailure(Throwable caught) {
-              deleteKey.setEnabled(true);
-              super.onFailure(caught);
-            }
-          });
-    }
-
-    private boolean isChecked(int row) {
-      return ((CheckBox) table.getWidget(row, 0)).getValue();
-    }
-
-    private void clear() {
-      while (table.getRowCount() > 1) {
-        table.removeRow(1);
-      }
-      for (int i = table.getRowCount() - 1; i >= 1; i++) {
-        table.removeRow(i);
-      }
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyGpgKeysScreen.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyGpgKeysScreen.ui.xml
deleted file mode 100644
index dc73736..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyGpgKeysScreen.ui.xml
+++ /dev/null
@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2015 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'
-    xmlns:expui='urn:import:com.google.gwtexpui.globalkey.client'>
-  <ui:with field='res' type='com.google.gerrit.client.GerritResources'/>
-
-  <ui:style gss='false'>
-    .errorHeader {
-      font-weight: bold;
-    }
-    .errorText {
-      white-space: pre-wrap;
-      padding-bottom: 6px;
-    }
-  </ui:style>
-
-  <g:HTMLPanel>
-    <g:Widget ui:field='keys' addStyleNames='{res.css.sshKeyTable}'/>
-    <g:FlowPanel>
-      <g:Button ui:field='deleteKey'>
-        <div><ui:msg>Delete</ui:msg></div>
-      </g:Button>
-      <g:Button ui:field='addKey'>
-        <div><ui:msg>Add Key ...</ui:msg></div>
-      </g:Button>
-    </g:FlowPanel>
-    <g:VerticalPanel ui:field='addKeyBlock'
-        styleName='{res.css.addSshKeyPanel}'
-        visible='false'>
-      <g:Label>Add GPG Public Key</g:Label>
-      <g:DisclosurePanel>
-        <g:header>How to generate a GPG key</g:header>
-        <g:HTMLPanel>
-          <ol>
-            <li>
-              From the Terminal or Git Bash, run <em>gpg --gen-key</em> and
-              follow the prompts to create the key.
-            </li>
-            <li>
-              Use the default kind. Use the default (or higher) keysize. Choose
-              any value for your expiration.
-            </li>
-            <li>
-              The user ID should contain one of your registered email addresses.
-            </li>
-            <li>Setting a passphrase is strongly recommended.</li>
-            <li>Note the ID of your new key.</li>
-            <li>
-              To export your key, run the following and paste the full output
-              into the text box:
-              <br/>
-              <code>gpg --export -a &lt;key ID&gt;</code>
-            </li>
-          </ol>
-        </g:HTMLPanel>
-      </g:DisclosurePanel>
-      <expui:NpTextArea
-          visibleLines='12'
-          characterWidth='80'
-          spellCheck='false'
-          ui:field='keyText'/>
-      <g:VerticalPanel ui:field='errorPanel' visible='false'>
-        <g:Label styleName='{style.errorHeader}'>Error adding GPG key:</g:Label>
-        <g:Label styleName='{style.errorText}' ui:field='errorText'/>
-      </g:VerticalPanel>
-      <g:FlowPanel>
-        <g:Button ui:field='clearButton'>
-          <div><ui:msg>Clear</ui:msg></div>
-        </g:Button>
-        <g:Button ui:field='addButton'>
-          <div><ui:msg>Add</ui:msg></div>
-        </g:Button>
-        <g:Button ui:field='closeButton'>
-          <div><ui:msg>Close</ui:msg></div>
-        </g:Button>
-      </g:FlowPanel>
-    </g:VerticalPanel>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyGroupsScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyGroupsScreen.java
deleted file mode 100644
index e9112de..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyGroupsScreen.java
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.client.admin.GroupTable;
-import com.google.gerrit.client.groups.GroupList;
-import com.google.gerrit.client.rpc.ScreenLoadCallback;
-
-public class MyGroupsScreen extends SettingsScreen {
-  private GroupTable groups;
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    groups = new GroupTable();
-    add(groups);
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    GroupList.my(
-        new ScreenLoadCallback<GroupList>(this) {
-          @Override
-          protected void preDisplay(GroupList result) {
-            groups.display(result);
-            groups.finishDisplay();
-          }
-        });
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyIdentitiesScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyIdentitiesScreen.java
deleted file mode 100644
index 730d98e..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyIdentitiesScreen.java
+++ /dev/null
@@ -1,224 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import static java.util.Comparator.naturalOrder;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.VoidResult;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.FancyFlexTable;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.logical.shared.ValueChangeHandler;
-import com.google.gwt.user.client.History;
-import com.google.gwt.user.client.Window.Location;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
-import java.util.HashSet;
-import java.util.List;
-
-public class MyIdentitiesScreen extends SettingsScreen {
-  private IdTable identites;
-  private Button deleteIdentity;
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-
-    identites = new IdTable();
-    add(identites);
-
-    deleteIdentity = new Button(Util.C.buttonDeleteIdentity());
-    deleteIdentity.setEnabled(false);
-    deleteIdentity.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            identites.deleteChecked();
-          }
-        });
-    add(deleteIdentity);
-
-    if (Gerrit.info().auth().isOpenId() || Gerrit.info().auth().isOAuth()) {
-      Button linkIdentity = new Button(Util.C.buttonLinkIdentity());
-      linkIdentity.addClickHandler(
-          new ClickHandler() {
-            @Override
-            public void onClick(ClickEvent event) {
-              Location.assign(Gerrit.loginRedirect(History.getToken()) + "?link");
-            }
-          });
-      add(linkIdentity);
-    }
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    AccountApi.getExternalIds(
-        new GerritCallback<JsArray<ExternalIdInfo>>() {
-          @Override
-          public void onSuccess(JsArray<ExternalIdInfo> results) {
-            identites.display(results);
-            display();
-          }
-        });
-  }
-
-  private class IdTable extends FancyFlexTable<ExternalIdInfo> {
-    private ValueChangeHandler<Boolean> updateDeleteHandler;
-
-    IdTable() {
-      table.setWidth("");
-      table.setText(0, 2, Util.C.webIdStatus());
-      table.setText(0, 3, Util.C.webIdEmail());
-      table.setText(0, 4, Util.C.webIdIdentity());
-
-      final FlexCellFormatter fmt = table.getFlexCellFormatter();
-      fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().iconHeader());
-      fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader());
-      fmt.addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader());
-      fmt.addStyleName(0, 4, Gerrit.RESOURCES.css().dataHeader());
-
-      updateDeleteHandler =
-          new ValueChangeHandler<Boolean>() {
-            @Override
-            public void onValueChange(ValueChangeEvent<Boolean> event) {
-              updateDeleteButton();
-            }
-          };
-    }
-
-    void deleteChecked() {
-      final HashSet<String> keys = new HashSet<>();
-      for (int row = 1; row < table.getRowCount(); row++) {
-        final ExternalIdInfo k = getRowItem(row);
-        if (k == null) {
-          continue;
-        }
-        final CheckBox cb = (CheckBox) table.getWidget(row, 1);
-        if (cb == null) {
-          continue;
-        }
-        if (cb.getValue()) {
-          keys.add(k.identity());
-        }
-      }
-      if (keys.isEmpty()) {
-        updateDeleteButton();
-      } else {
-        deleteIdentity.setEnabled(false);
-        AccountApi.deleteExternalIds(
-            keys,
-            new GerritCallback<VoidResult>() {
-              @Override
-              public void onSuccess(VoidResult result) {
-                for (int row = 1; row < table.getRowCount(); ) {
-                  final ExternalIdInfo k = getRowItem(row);
-                  if (k != null && keys.contains(k.identity())) {
-                    table.removeRow(row);
-                  } else {
-                    row++;
-                  }
-                }
-                updateDeleteButton();
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {
-                updateDeleteButton();
-                super.onFailure(caught);
-              }
-            });
-      }
-    }
-
-    void updateDeleteButton() {
-      int off = 0;
-      boolean on = false;
-      for (int row = 1; row < table.getRowCount(); row++) {
-        if (table.getWidget(row, 1) == null) {
-          off++;
-        } else {
-          CheckBox sel = (CheckBox) table.getWidget(row, 1);
-          if (sel.getValue()) {
-            on = true;
-            break;
-          }
-        }
-      }
-      deleteIdentity.setVisible(off < table.getRowCount() - 1);
-      deleteIdentity.setEnabled(on);
-    }
-
-    void display(JsArray<ExternalIdInfo> results) {
-      List<ExternalIdInfo> idList = Natives.asList(results);
-      idList.sort(naturalOrder());
-
-      while (1 < table.getRowCount()) {
-        table.removeRow(table.getRowCount() - 1);
-      }
-
-      for (ExternalIdInfo k : idList) {
-        addOneId(k);
-      }
-      updateDeleteButton();
-    }
-
-    void addOneId(ExternalIdInfo k) {
-      if (k.isUsername()) {
-        // Don't display the username as an identity here.
-        return;
-      }
-
-      final FlexCellFormatter fmt = table.getFlexCellFormatter();
-      final int row = table.getRowCount();
-      table.insertRow(row);
-      applyDataRowStyle(row);
-
-      if (k.canDelete()) {
-        final CheckBox sel = new CheckBox();
-        sel.addValueChangeHandler(updateDeleteHandler);
-        table.setWidget(row, 1, sel);
-      } else {
-        table.setText(row, 1, "");
-      }
-      if (k.isTrusted()) {
-        table.setText(row, 2, "");
-      } else {
-        table.setText(row, 2, Util.C.untrustedProvider());
-        fmt.addStyleName(row, 2, Gerrit.RESOURCES.css().identityUntrustedExternalId());
-      }
-      if (k.emailAddress() != null && k.emailAddress().length() > 0) {
-        table.setText(row, 3, k.emailAddress());
-      } else {
-        table.setText(row, 3, "");
-      }
-      table.setText(row, 4, k.describe());
-
-      fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().iconCell());
-      fmt.addStyleName(row, 2, Gerrit.RESOURCES.css().dataCell());
-      fmt.addStyleName(row, 3, Gerrit.RESOURCES.css().dataCell());
-      fmt.addStyleName(row, 4, Gerrit.RESOURCES.css().dataCell());
-
-      setRowItem(row, k);
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyOAuthTokenScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyOAuthTokenScreen.java
deleted file mode 100644
index 173dba6..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyOAuthTokenScreen.java
+++ /dev/null
@@ -1,198 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.info.GeneralPreferences;
-import com.google.gerrit.client.info.OAuthTokenInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gwt.i18n.client.DateTimeFormat;
-import com.google.gwt.i18n.client.LocaleInfo;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.clippy.client.CopyableLabel;
-import java.util.Date;
-
-public class MyOAuthTokenScreen extends SettingsScreen {
-  private CopyableLabel tokenLabel;
-  private Label expiresLabel;
-  private Label expiredNote;
-  private CopyableLabel netrcValue;
-  private CopyableLabel cookieValue;
-  private FlowPanel flow;
-  private Grid grid;
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-
-    tokenLabel = new CopyableLabel("");
-    tokenLabel.addStyleName(Gerrit.RESOURCES.css().oauthToken());
-
-    expiresLabel = new Label("");
-    expiresLabel.addStyleName(Gerrit.RESOURCES.css().oauthExpires());
-
-    grid = new Grid(2, 2);
-    grid.setStyleName(Gerrit.RESOURCES.css().infoBlock());
-    grid.addStyleName(Gerrit.RESOURCES.css().oauthInfoBlock());
-    add(grid);
-
-    expiredNote = new Label(Util.C.labelOAuthExpired());
-    expiredNote.setVisible(false);
-    add(expiredNote);
-
-    row(grid, 0, Util.C.labelOAuthToken(), tokenLabel);
-    row(grid, 1, Util.C.labelOAuthExpires(), expiresLabel);
-
-    CellFormatter fmt = grid.getCellFormatter();
-    fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().topmost());
-    fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().topmost());
-    fmt.addStyleName(1, 0, Gerrit.RESOURCES.css().bottomheader());
-
-    flow = new FlowPanel();
-    flow.setStyleName(Gerrit.RESOURCES.css().oauthPanel());
-    add(flow);
-
-    Label netrcLabel = new Label(Util.C.labelOAuthNetRCEntry());
-    netrcLabel.setStyleName(Gerrit.RESOURCES.css().oauthPanelNetRCHeading());
-    flow.add(netrcLabel);
-    netrcValue = new CopyableLabel("");
-    netrcValue.setStyleName(Gerrit.RESOURCES.css().oauthPanelNetRCEntry());
-    flow.add(netrcValue);
-
-    Label cookieLabel = new Label(Util.C.labelOAuthGitCookie());
-    cookieLabel.setStyleName(Gerrit.RESOURCES.css().oauthPanelCookieHeading());
-    flow.add(cookieLabel);
-    cookieValue = new CopyableLabel("");
-    cookieValue.setStyleName(Gerrit.RESOURCES.css().oauthPanelCookieEntry());
-    flow.add(cookieValue);
-  }
-
-  private void row(Grid grid, int row, String name, Widget field) {
-    final CellFormatter fmt = grid.getCellFormatter();
-    if (LocaleInfo.getCurrentLocale().isRTL()) {
-      grid.setText(row, 1, name);
-      grid.setWidget(row, 0, field);
-      fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().header());
-    } else {
-      grid.setText(row, 0, name);
-      grid.setWidget(row, 1, field);
-      fmt.addStyleName(row, 0, Gerrit.RESOURCES.css().header());
-    }
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    AccountApi.self()
-        .view("preferences")
-        .get(
-            new ScreenLoadCallback<GeneralPreferences>(this) {
-              @Override
-              protected void preDisplay(GeneralPreferences prefs) {
-                display(prefs);
-              }
-            });
-  }
-
-  private void display(GeneralPreferences prefs) {
-    AccountApi.self()
-        .view("oauthtoken")
-        .get(
-            new GerritCallback<OAuthTokenInfo>() {
-              @Override
-              public void onSuccess(OAuthTokenInfo tokenInfo) {
-                tokenLabel.setText(tokenInfo.accessToken());
-                expiresLabel.setText(getExpiresAt(tokenInfo, prefs));
-                netrcValue.setText(getNetRC(tokenInfo));
-                cookieValue.setText(getCookie(tokenInfo));
-                flow.setVisible(true);
-                expiredNote.setVisible(false);
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {
-                if (isNoSuchEntity(caught) || isSigninFailure(caught)) {
-                  tokenLabel.setText("");
-                  expiresLabel.setText("");
-                  netrcValue.setText("");
-                  cookieValue.setText("");
-                  flow.setVisible(false);
-                  expiredNote.setVisible(true);
-                } else {
-                  showFailure(caught);
-                }
-              }
-            });
-  }
-
-  private static long getExpiresAt(OAuthTokenInfo tokenInfo) {
-    if (tokenInfo.expiresAt() == null) {
-      return Long.MAX_VALUE;
-    }
-    long expiresAt;
-    try {
-      expiresAt = Long.parseLong(tokenInfo.expiresAt());
-    } catch (NumberFormatException e) {
-      return Long.MAX_VALUE;
-    }
-    return expiresAt;
-  }
-
-  private static long getExpiresAtSeconds(OAuthTokenInfo tokenInfo) {
-    return getExpiresAt(tokenInfo) / 1000L;
-  }
-
-  private static String getExpiresAt(OAuthTokenInfo tokenInfo, GeneralPreferences prefs) {
-    long expiresAt = getExpiresAt(tokenInfo);
-    if (expiresAt == Long.MAX_VALUE) {
-      return "";
-    }
-    String dateFormat = prefs.dateFormat().getLongFormat();
-    String timeFormat = prefs.timeFormat().getFormat();
-    DateTimeFormat formatter = DateTimeFormat.getFormat(dateFormat + " " + timeFormat);
-    return formatter.format(new Date(expiresAt));
-  }
-
-  private static String getNetRC(OAuthTokenInfo accessTokenInfo) {
-    StringBuilder sb = new StringBuilder();
-    sb.append("machine ");
-    sb.append(accessTokenInfo.resourceHost());
-    sb.append(" login ");
-    sb.append(accessTokenInfo.username());
-    sb.append(" password ");
-    sb.append(accessTokenInfo.accessToken());
-    return sb.toString();
-  }
-
-  private static String getCookie(OAuthTokenInfo accessTokenInfo) {
-    StringBuilder sb = new StringBuilder();
-    sb.append(accessTokenInfo.resourceHost());
-    sb.append("\tFALSE\t/\tTRUE\t");
-    sb.append(getExpiresAtSeconds(accessTokenInfo));
-    sb.append("\tgit-");
-    sb.append(accessTokenInfo.username());
-    sb.append('\t');
-    sb.append(accessTokenInfo.accessToken());
-    if (accessTokenInfo.providerId() != null) {
-      sb.append('@').append(accessTokenInfo.providerId());
-    }
-    return sb.toString();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPasswordScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPasswordScreen.java
deleted file mode 100644
index 5dd7530..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPasswordScreen.java
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.GerritUiExtensionPoint;
-import com.google.gerrit.client.api.ExtensionPanel;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.NativeString;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.i18n.client.LocaleInfo;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.clippy.client.CopyableLabel;
-
-public class MyPasswordScreen extends SettingsScreen {
-  private CopyableLabel password;
-  private Button generatePassword;
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-
-    String url = Gerrit.info().auth().httpPasswordUrl();
-    if (url != null) {
-      Anchor link = new Anchor();
-      link.setText(Util.C.linkObtainPassword());
-      link.setHref(url);
-      link.setTarget("_blank");
-      add(link);
-      return;
-    }
-
-    password = new CopyableLabel(Util.C.revokePassword());
-    password.addStyleName(Gerrit.RESOURCES.css().accountPassword());
-
-    generatePassword = new Button(Util.C.buttonGeneratePassword());
-    generatePassword.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            doGeneratePassword();
-          }
-        });
-
-    final Grid userInfo = new Grid(2, 2);
-    final CellFormatter fmt = userInfo.getCellFormatter();
-    userInfo.setStyleName(Gerrit.RESOURCES.css().infoBlock());
-    userInfo.addStyleName(Gerrit.RESOURCES.css().accountInfoBlock());
-    add(userInfo);
-
-    row(userInfo, 0, Util.C.userName(), new UsernameField());
-    row(userInfo, 1, Util.C.password(), password);
-
-    fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().topmost());
-    fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().topmost());
-    fmt.addStyleName(1, 0, Gerrit.RESOURCES.css().bottomheader());
-
-    final FlowPanel buttons = new FlowPanel();
-    buttons.add(generatePassword);
-    add(buttons);
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    ExtensionPanel extensionPanel =
-        createExtensionPoint(GerritUiExtensionPoint.PASSWORD_SCREEN_BOTTOM);
-    extensionPanel.addStyleName(Gerrit.RESOURCES.css().extensionPanel());
-    add(extensionPanel);
-
-    if (password == null) {
-      display();
-      return;
-    }
-
-    enableUI(false);
-    AccountApi.getUsername(
-        "self",
-        new GerritCallback<NativeString>() {
-          @Override
-          public void onSuccess(NativeString user) {
-            Gerrit.getUserAccount().username(user.asString());
-            enableUI(true);
-            display();
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            if (RestApi.isNotFound(caught)) {
-              Gerrit.getUserAccount().username(null);
-              display();
-            } else {
-              super.onFailure(caught);
-            }
-          }
-        });
-  }
-
-  private void display(String pass) {
-    password.setText(pass != null ? pass : "");
-    password.setVisible(pass != null);
-    enableUI(true);
-  }
-
-  private void row(Grid info, int row, String name, Widget field) {
-    final CellFormatter fmt = info.getCellFormatter();
-    if (LocaleInfo.getCurrentLocale().isRTL()) {
-      info.setText(row, 1, name);
-      info.setWidget(row, 0, field);
-      fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().header());
-    } else {
-      info.setText(row, 0, name);
-      info.setWidget(row, 1, field);
-      fmt.addStyleName(row, 0, Gerrit.RESOURCES.css().header());
-    }
-  }
-
-  private void doGeneratePassword() {
-    if (Gerrit.getUserAccount().username() != null) {
-      enableUI(false);
-      AccountApi.generateHttpPassword(
-          "self",
-          new GerritCallback<NativeString>() {
-            @Override
-            public void onSuccess(NativeString newPassword) {
-              display(newPassword.asString());
-            }
-
-            @Override
-            public void onFailure(Throwable caught) {
-              enableUI(true);
-            }
-          });
-    }
-  }
-
-  private void enableUI(boolean on) {
-    on &= Gerrit.getUserAccount().username() != null;
-
-    generatePassword.setEnabled(on);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPreferencesScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPreferencesScreen.java
deleted file mode 100644
index afb8718..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPreferencesScreen.java
+++ /dev/null
@@ -1,515 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import static com.google.gerrit.extensions.client.GeneralPreferencesInfo.DEFAULT_PAGESIZE;
-import static com.google.gerrit.extensions.client.GeneralPreferencesInfo.PAGESIZE_CHOICES;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.GerritUiExtensionPoint;
-import com.google.gerrit.client.StringListPanel;
-import com.google.gerrit.client.api.ExtensionPanel;
-import com.google.gerrit.client.config.ConfigServerApi;
-import com.google.gerrit.client.info.GeneralPreferences;
-import com.google.gerrit.client.info.TopMenuItem;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gerrit.client.ui.OnEditEnabler;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.ReviewCategoryStrategy;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.i18n.client.DateTimeFormat;
-import com.google.gwt.i18n.client.LocaleInfo;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.ListBox;
-import com.google.gwtexpui.user.client.UserAgent;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-
-public class MyPreferencesScreen extends SettingsScreen {
-  private CheckBox showSiteHeader;
-  private CheckBox useFlashClipboard;
-  private CheckBox highlightAssigneeInChangeTable;
-  private CheckBox relativeDateInChangeTable;
-  private CheckBox sizeBarInChangeTable;
-  private CheckBox legacycidInChangeTable;
-  private CheckBox muteCommonPathPrefixes;
-  private CheckBox signedOffBy;
-  private CheckBox publishCommentsOnPush;
-  private CheckBox workInProgressByDefault;
-  private ListBox maximumPageSize;
-  private ListBox dateFormat;
-  private ListBox timeFormat;
-  private ListBox reviewCategoryStrategy;
-  private ListBox diffView;
-  private ListBox emailStrategy;
-  private ListBox emailFormat;
-  private ListBox defaultBaseForMerges;
-  private StringListPanel myMenus;
-  private Button save;
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-
-    showSiteHeader = new CheckBox(Util.C.showSiteHeader());
-    useFlashClipboard = new CheckBox(Util.C.useFlashClipboard());
-    maximumPageSize = new ListBox();
-    for (int v : PAGESIZE_CHOICES) {
-      maximumPageSize.addItem(Util.M.rowsPerPage(v), String.valueOf(v));
-    }
-
-    reviewCategoryStrategy = new ListBox();
-    reviewCategoryStrategy.addItem(
-        Util.C.messageShowInReviewCategoryNone(),
-        GeneralPreferencesInfo.ReviewCategoryStrategy.NONE.name());
-    reviewCategoryStrategy.addItem(
-        Util.C.messageShowInReviewCategoryName(),
-        GeneralPreferencesInfo.ReviewCategoryStrategy.NAME.name());
-    reviewCategoryStrategy.addItem(
-        Util.C.messageShowInReviewCategoryEmail(),
-        GeneralPreferencesInfo.ReviewCategoryStrategy.EMAIL.name());
-    reviewCategoryStrategy.addItem(
-        Util.C.messageShowInReviewCategoryUsername(),
-        GeneralPreferencesInfo.ReviewCategoryStrategy.USERNAME.name());
-    reviewCategoryStrategy.addItem(
-        Util.C.messageShowInReviewCategoryAbbrev(),
-        GeneralPreferencesInfo.ReviewCategoryStrategy.ABBREV.name());
-
-    emailStrategy = new ListBox();
-    emailStrategy.addItem(
-        Util.C.messageCCMeOnMyComments(),
-        GeneralPreferencesInfo.EmailStrategy.CC_ON_OWN_COMMENTS.name());
-    emailStrategy.addItem(
-        Util.C.messageEnabled(), GeneralPreferencesInfo.EmailStrategy.ENABLED.name());
-    emailStrategy.addItem(
-        Util.C.messageDisabled(), GeneralPreferencesInfo.EmailStrategy.DISABLED.name());
-
-    emailFormat = new ListBox();
-    emailFormat.addItem(
-        Util.C.messagePlaintextOnly(), GeneralPreferencesInfo.EmailFormat.PLAINTEXT.name());
-    emailFormat.addItem(
-        Util.C.messageHtmlPlaintext(), GeneralPreferencesInfo.EmailFormat.HTML_PLAINTEXT.name());
-
-    defaultBaseForMerges = new ListBox();
-    defaultBaseForMerges.addItem(
-        Util.C.autoMerge(), GeneralPreferencesInfo.DefaultBase.AUTO_MERGE.name());
-    defaultBaseForMerges.addItem(
-        Util.C.firstParent(), GeneralPreferencesInfo.DefaultBase.FIRST_PARENT.name());
-
-    diffView = new ListBox();
-    diffView.addItem(
-        com.google.gerrit.client.changes.Util.C.sideBySide(),
-        GeneralPreferencesInfo.DiffView.SIDE_BY_SIDE.name());
-    diffView.addItem(
-        com.google.gerrit.client.changes.Util.C.unifiedDiff(),
-        GeneralPreferencesInfo.DiffView.UNIFIED_DIFF.name());
-
-    Date now = new Date();
-    dateFormat = new ListBox();
-    for (GeneralPreferencesInfo.DateFormat fmt : GeneralPreferencesInfo.DateFormat.values()) {
-      StringBuilder r = new StringBuilder();
-      r.append(DateTimeFormat.getFormat(fmt.getShortFormat()).format(now));
-      r.append(" ; ");
-      r.append(DateTimeFormat.getFormat(fmt.getLongFormat()).format(now));
-      dateFormat.addItem(r.toString(), fmt.name());
-    }
-
-    timeFormat = new ListBox();
-    for (GeneralPreferencesInfo.TimeFormat fmt : GeneralPreferencesInfo.TimeFormat.values()) {
-      StringBuilder r = new StringBuilder();
-      r.append(DateTimeFormat.getFormat(fmt.getFormat()).format(now));
-      timeFormat.addItem(r.toString(), fmt.name());
-    }
-
-    FlowPanel dateTimePanel = new FlowPanel();
-
-    final int labelIdx;
-    final int fieldIdx;
-    if (LocaleInfo.getCurrentLocale().isRTL()) {
-      labelIdx = 1;
-      fieldIdx = 0;
-      dateTimePanel.add(timeFormat);
-      dateTimePanel.add(dateFormat);
-    } else {
-      labelIdx = 0;
-      fieldIdx = 1;
-      dateTimePanel.add(dateFormat);
-      dateTimePanel.add(timeFormat);
-    }
-    highlightAssigneeInChangeTable = new CheckBox(Util.C.highlightAssigneeInChangeTable());
-    relativeDateInChangeTable = new CheckBox(Util.C.showRelativeDateInChangeTable());
-    sizeBarInChangeTable = new CheckBox(Util.C.showSizeBarInChangeTable());
-    legacycidInChangeTable = new CheckBox(Util.C.showLegacycidInChangeTable());
-    muteCommonPathPrefixes = new CheckBox(Util.C.muteCommonPathPrefixes());
-    signedOffBy = new CheckBox(Util.C.signedOffBy());
-    publishCommentsOnPush = new CheckBox(Util.C.publishCommentsOnPush());
-    workInProgressByDefault = new CheckBox(Util.C.workInProgressByDefault());
-
-    boolean flashClippy = !UserAgent.hasJavaScriptClipboard() && UserAgent.Flash.isInstalled();
-    final Grid formGrid = new Grid(16 + (flashClippy ? 1 : 0), 2);
-
-    int row = 0;
-
-    formGrid.setText(row, labelIdx, Util.C.reviewCategoryLabel());
-    formGrid.setWidget(row, fieldIdx, reviewCategoryStrategy);
-    row++;
-
-    formGrid.setText(row, labelIdx, Util.C.maximumPageSizeFieldLabel());
-    formGrid.setWidget(row, fieldIdx, maximumPageSize);
-    row++;
-
-    formGrid.setText(row, labelIdx, Util.C.dateFormatLabel());
-    formGrid.setWidget(row, fieldIdx, dateTimePanel);
-    row++;
-
-    formGrid.setText(row, labelIdx, Util.C.emailFieldLabel());
-    formGrid.setWidget(row, fieldIdx, emailStrategy);
-    row++;
-
-    formGrid.setText(row, labelIdx, Util.C.emailFormatFieldLabel());
-    formGrid.setWidget(row, fieldIdx, emailFormat);
-    row++;
-
-    formGrid.setText(row, labelIdx, Util.C.defaultBaseForMerges());
-    formGrid.setWidget(row, fieldIdx, defaultBaseForMerges);
-    row++;
-
-    formGrid.setText(row, labelIdx, Util.C.diffViewLabel());
-    formGrid.setWidget(row, fieldIdx, diffView);
-    row++;
-
-    formGrid.setText(row, labelIdx, "");
-    formGrid.setWidget(row, fieldIdx, showSiteHeader);
-    row++;
-
-    formGrid.setText(row, labelIdx, "");
-    formGrid.setWidget(row, fieldIdx, highlightAssigneeInChangeTable);
-    row++;
-
-    formGrid.setText(row, labelIdx, "");
-    formGrid.setWidget(row, fieldIdx, relativeDateInChangeTable);
-    row++;
-
-    formGrid.setText(row, labelIdx, "");
-    formGrid.setWidget(row, fieldIdx, sizeBarInChangeTable);
-    row++;
-
-    formGrid.setText(row, labelIdx, "");
-    formGrid.setWidget(row, fieldIdx, legacycidInChangeTable);
-    row++;
-
-    formGrid.setText(row, labelIdx, "");
-    formGrid.setWidget(row, fieldIdx, muteCommonPathPrefixes);
-    row++;
-
-    formGrid.setText(row, labelIdx, "");
-    formGrid.setWidget(row, fieldIdx, signedOffBy);
-    row++;
-
-    formGrid.setText(row, labelIdx, "");
-    formGrid.setWidget(row, fieldIdx, publishCommentsOnPush);
-    row++;
-
-    formGrid.setText(row, labelIdx, "");
-    formGrid.setWidget(row, fieldIdx, workInProgressByDefault);
-    row++;
-
-    if (flashClippy) {
-      formGrid.setText(row, labelIdx, "");
-      formGrid.setWidget(row, fieldIdx, useFlashClipboard);
-    }
-
-    add(formGrid);
-
-    save = new Button(Util.C.buttonSaveChanges());
-    save.setEnabled(false);
-    save.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            doSave();
-          }
-        });
-
-    myMenus = new MyMenuPanel(save);
-    add(myMenus);
-
-    add(save);
-
-    final OnEditEnabler e = new OnEditEnabler(save);
-    e.listenTo(showSiteHeader);
-    e.listenTo(useFlashClipboard);
-    e.listenTo(maximumPageSize);
-    e.listenTo(dateFormat);
-    e.listenTo(timeFormat);
-    e.listenTo(highlightAssigneeInChangeTable);
-    e.listenTo(relativeDateInChangeTable);
-    e.listenTo(sizeBarInChangeTable);
-    e.listenTo(legacycidInChangeTable);
-    e.listenTo(muteCommonPathPrefixes);
-    e.listenTo(signedOffBy);
-    e.listenTo(publishCommentsOnPush);
-    e.listenTo(workInProgressByDefault);
-    e.listenTo(diffView);
-    e.listenTo(reviewCategoryStrategy);
-    e.listenTo(emailStrategy);
-    e.listenTo(emailFormat);
-    e.listenTo(defaultBaseForMerges);
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    ExtensionPanel extensionPanel =
-        createExtensionPoint(GerritUiExtensionPoint.PREFERENCES_SCREEN_BOTTOM);
-    extensionPanel.addStyleName(Gerrit.RESOURCES.css().extensionPanel());
-    add(extensionPanel);
-
-    AccountApi.self()
-        .view("preferences")
-        .get(
-            new ScreenLoadCallback<GeneralPreferences>(this) {
-              @Override
-              public void preDisplay(GeneralPreferences prefs) {
-                display(prefs);
-              }
-            });
-  }
-
-  private void enable(boolean on) {
-    showSiteHeader.setEnabled(on);
-    useFlashClipboard.setEnabled(on);
-    maximumPageSize.setEnabled(on);
-    dateFormat.setEnabled(on);
-    timeFormat.setEnabled(on);
-    highlightAssigneeInChangeTable.setEnabled(on);
-    relativeDateInChangeTable.setEnabled(on);
-    sizeBarInChangeTable.setEnabled(on);
-    legacycidInChangeTable.setEnabled(on);
-    muteCommonPathPrefixes.setEnabled(on);
-    signedOffBy.setEnabled(on);
-    publishCommentsOnPush.setEnabled(on);
-    workInProgressByDefault.setEnabled(on);
-    reviewCategoryStrategy.setEnabled(on);
-    diffView.setEnabled(on);
-    emailStrategy.setEnabled(on);
-    emailFormat.setEnabled(on);
-    defaultBaseForMerges.setEnabled(on);
-  }
-
-  private void display(GeneralPreferences p) {
-    showSiteHeader.setValue(p.showSiteHeader());
-    useFlashClipboard.setValue(p.useFlashClipboard());
-    setListBox(maximumPageSize, DEFAULT_PAGESIZE, p.changesPerPage());
-    setListBox(
-        dateFormat,
-        GeneralPreferencesInfo.DateFormat.STD, //
-        p.dateFormat());
-    setListBox(
-        timeFormat,
-        GeneralPreferencesInfo.TimeFormat.HHMM_12, //
-        p.timeFormat());
-    highlightAssigneeInChangeTable.setValue(p.highlightAssigneeInChangeTable());
-    relativeDateInChangeTable.setValue(p.relativeDateInChangeTable());
-    sizeBarInChangeTable.setValue(p.sizeBarInChangeTable());
-    legacycidInChangeTable.setValue(p.legacycidInChangeTable());
-    muteCommonPathPrefixes.setValue(p.muteCommonPathPrefixes());
-    signedOffBy.setValue(p.signedOffBy());
-    publishCommentsOnPush.setValue(p.publishCommentsOnPush());
-    workInProgressByDefault.setValue(p.workInProgressByDefault());
-    setListBox(
-        reviewCategoryStrategy,
-        GeneralPreferencesInfo.ReviewCategoryStrategy.NONE,
-        p.reviewCategoryStrategy());
-    setListBox(diffView, GeneralPreferencesInfo.DiffView.SIDE_BY_SIDE, p.diffView());
-    setListBox(emailStrategy, GeneralPreferencesInfo.EmailStrategy.ENABLED, p.emailStrategy());
-    setListBox(emailFormat, GeneralPreferencesInfo.EmailFormat.HTML_PLAINTEXT, p.emailFormat());
-    setListBox(
-        defaultBaseForMerges,
-        GeneralPreferencesInfo.DefaultBase.FIRST_PARENT,
-        p.defaultBaseForMerges());
-    display(p.my());
-  }
-
-  private void display(JsArray<TopMenuItem> items) {
-    List<List<String>> values = new ArrayList<>();
-    for (TopMenuItem item : Natives.asList(items)) {
-      values.add(Arrays.asList(item.getName(), item.getUrl()));
-    }
-    myMenus.display(values);
-  }
-
-  private void setListBox(ListBox f, int defaultValue, int currentValue) {
-    setListBox(f, String.valueOf(defaultValue), String.valueOf(currentValue));
-  }
-
-  private <T extends Enum<?>> void setListBox(final ListBox f, T defaultValue, T currentValue) {
-    setListBox(
-        f,
-        defaultValue != null ? defaultValue.name() : "",
-        currentValue != null ? currentValue.name() : "");
-  }
-
-  private void setListBox(ListBox f, String defaultValue, String currentValue) {
-    final int n = f.getItemCount();
-    for (int i = 0; i < n; i++) {
-      if (f.getValue(i).equals(currentValue)) {
-        f.setSelectedIndex(i);
-        return;
-      }
-    }
-    if (!currentValue.equals(defaultValue)) {
-      setListBox(f, defaultValue, defaultValue);
-    }
-  }
-
-  private int getListBox(ListBox f, int defaultValue) {
-    final int idx = f.getSelectedIndex();
-    if (0 <= idx) {
-      return Short.parseShort(f.getValue(idx));
-    }
-    return defaultValue;
-  }
-
-  private <T extends Enum<?>> T getListBox(ListBox f, T defaultValue, T[] all) {
-    final int idx = f.getSelectedIndex();
-    if (0 <= idx) {
-      String v = f.getValue(idx);
-      if ("".equals(v)) {
-        return defaultValue;
-      }
-      for (T t : all) {
-        if (t.name().equals(v)) {
-          return t;
-        }
-      }
-    }
-    return defaultValue;
-  }
-
-  private void doSave() {
-    GeneralPreferences p = GeneralPreferences.create();
-    p.showSiteHeader(showSiteHeader.getValue());
-    p.useFlashClipboard(useFlashClipboard.getValue());
-    p.changesPerPage(getListBox(maximumPageSize, DEFAULT_PAGESIZE));
-    p.dateFormat(
-        getListBox(
-            dateFormat,
-            GeneralPreferencesInfo.DateFormat.STD,
-            GeneralPreferencesInfo.DateFormat.values()));
-    p.timeFormat(
-        getListBox(
-            timeFormat,
-            GeneralPreferencesInfo.TimeFormat.HHMM_12,
-            GeneralPreferencesInfo.TimeFormat.values()));
-    p.highlightAssigneeInChangeTable(highlightAssigneeInChangeTable.getValue());
-    p.relativeDateInChangeTable(relativeDateInChangeTable.getValue());
-    p.sizeBarInChangeTable(sizeBarInChangeTable.getValue());
-    p.legacycidInChangeTable(legacycidInChangeTable.getValue());
-    p.muteCommonPathPrefixes(muteCommonPathPrefixes.getValue());
-    p.signedOffBy(signedOffBy.getValue());
-    p.publishCommentsOnPush(publishCommentsOnPush.getValue());
-    p.workInProgressByDefault(workInProgressByDefault.getValue());
-    p.reviewCategoryStrategy(
-        getListBox(
-            reviewCategoryStrategy, ReviewCategoryStrategy.NONE, ReviewCategoryStrategy.values()));
-    p.diffView(
-        getListBox(
-            diffView,
-            GeneralPreferencesInfo.DiffView.SIDE_BY_SIDE,
-            GeneralPreferencesInfo.DiffView.values()));
-
-    p.emailStrategy(
-        getListBox(
-            emailStrategy,
-            GeneralPreferencesInfo.EmailStrategy.ENABLED,
-            GeneralPreferencesInfo.EmailStrategy.values()));
-
-    p.emailFormat(
-        getListBox(
-            emailFormat,
-            GeneralPreferencesInfo.EmailFormat.HTML_PLAINTEXT,
-            GeneralPreferencesInfo.EmailFormat.values()));
-
-    p.defaultBaseForMerges(
-        getListBox(
-            defaultBaseForMerges,
-            GeneralPreferencesInfo.DefaultBase.FIRST_PARENT,
-            GeneralPreferencesInfo.DefaultBase.values()));
-
-    List<TopMenuItem> items = new ArrayList<>();
-    for (List<String> v : myMenus.getValues()) {
-      items.add(TopMenuItem.create(v.get(0), v.get(1)));
-    }
-    p.setMyMenus(items);
-
-    enable(false);
-    save.setEnabled(false);
-
-    AccountApi.self()
-        .view("preferences")
-        .put(
-            p,
-            new GerritCallback<GeneralPreferences>() {
-              @Override
-              public void onSuccess(GeneralPreferences prefs) {
-                Gerrit.setUserPreferences(prefs);
-                enable(true);
-                display(prefs);
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {
-                enable(true);
-                save.setEnabled(true);
-                super.onFailure(caught);
-              }
-            });
-  }
-
-  private class MyMenuPanel extends StringListPanel {
-    MyMenuPanel(Button save) {
-      super(Util.C.myMenu(), Arrays.asList(Util.C.myMenuName(), Util.C.myMenuUrl()), save, false);
-
-      setInfo(Util.C.myMenuInfo());
-
-      Button resetButton = new Button(Util.C.myMenuReset());
-      resetButton.addClickHandler(
-          new ClickHandler() {
-            @Override
-            public void onClick(ClickEvent event) {
-              ConfigServerApi.defaultPreferences(
-                  new GerritCallback<GeneralPreferences>() {
-                    @Override
-                    public void onSuccess(GeneralPreferences p) {
-                      MyPreferencesScreen.this.display(p.my());
-                      widget.setEnabled(true);
-                    }
-                  });
-            }
-          });
-      buttonPanel.add(resetButton);
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyProfileScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyProfileScreen.java
deleted file mode 100644
index 0275948..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyProfileScreen.java
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import static com.google.gerrit.client.FormatUtil.mediumFormat;
-
-import com.google.gerrit.client.AvatarImage;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.GerritUiExtensionPoint;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.rpc.NativeString;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gwt.i18n.client.LocaleInfo;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.VerticalPanel;
-
-public class MyProfileScreen extends SettingsScreen {
-  private AvatarImage avatar;
-  private Anchor changeAvatar;
-  private int labelIdx;
-  private int fieldIdx;
-  private Grid info;
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-
-    HorizontalPanel h = new HorizontalPanel();
-    add(h);
-
-    if (Gerrit.info().plugin().hasAvatars()) {
-      VerticalPanel v = new VerticalPanel();
-      v.addStyleName(Gerrit.RESOURCES.css().avatarInfoPanel());
-      h.add(v);
-      avatar = new AvatarImage();
-      v.add(avatar);
-      changeAvatar = new Anchor(Util.C.changeAvatar(), "", "_blank");
-      changeAvatar.setVisible(false);
-      v.add(changeAvatar);
-    }
-
-    if (LocaleInfo.getCurrentLocale().isRTL()) {
-      labelIdx = 1;
-      fieldIdx = 0;
-    } else {
-      labelIdx = 0;
-      fieldIdx = 1;
-    }
-
-    info = new Grid((Gerrit.info().auth().siteHasUsernames() ? 1 : 0) + 4, 2);
-    info.setStyleName(Gerrit.RESOURCES.css().infoBlock());
-    info.addStyleName(Gerrit.RESOURCES.css().accountInfoBlock());
-    h.add(info);
-
-    int row = 0;
-    if (Gerrit.info().auth().siteHasUsernames()) {
-      infoRow(row++, Util.C.userName());
-    }
-    infoRow(row++, Util.C.fullName());
-    infoRow(row++, Util.C.preferredEmail());
-    infoRow(row++, Util.C.registeredOn());
-    infoRow(row++, Util.C.accountId());
-
-    final CellFormatter fmt = info.getCellFormatter();
-    fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().topmost());
-    fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().topmost());
-    fmt.addStyleName(row - 1, 0, Gerrit.RESOURCES.css().bottomheader());
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    add(createExtensionPoint(GerritUiExtensionPoint.PROFILE_SCREEN_BOTTOM));
-    display(Gerrit.getUserAccount());
-    display();
-  }
-
-  private void infoRow(int row, String name) {
-    info.setText(row, labelIdx, name);
-    info.getCellFormatter().addStyleName(row, 0, Gerrit.RESOURCES.css().header());
-  }
-
-  void display(AccountInfo account) {
-    if (Gerrit.info().plugin().hasAvatars()) {
-      avatar.setAccount(account, 93, false);
-      new RestApi("/accounts/")
-          .id("self")
-          .view("avatar.change.url")
-          .get(
-              new AsyncCallback<NativeString>() {
-                @Override
-                public void onSuccess(NativeString changeUrl) {
-                  changeAvatar.setHref(changeUrl.asString());
-                  changeAvatar.setVisible(true);
-                }
-
-                @Override
-                public void onFailure(Throwable caught) {}
-              });
-    }
-
-    int row = 0;
-    if (Gerrit.info().auth().siteHasUsernames()) {
-      info.setWidget(row++, fieldIdx, new UsernameField());
-    }
-    info.setText(row++, fieldIdx, account.name());
-    info.setText(row++, fieldIdx, account.email());
-    info.setText(row++, fieldIdx, mediumFormat(account.registeredOn()));
-    info.setText(row, fieldIdx, Integer.toString(account._accountId()));
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MySshKeysScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MySshKeysScreen.java
deleted file mode 100644
index 6ba63aa..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MySshKeysScreen.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-public class MySshKeysScreen extends SettingsScreen {
-  private SshPanel panel;
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    panel =
-        new SshPanel() {
-          @Override
-          void display() {
-            MySshKeysScreen.this.display();
-          }
-        };
-    add(panel);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyWatchedProjectsScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyWatchedProjectsScreen.java
deleted file mode 100644
index f29b573..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyWatchedProjectsScreen.java
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.ui.HintTextBox;
-import com.google.gerrit.client.ui.ProjectListPopup;
-import com.google.gerrit.client.ui.ProjectNameSuggestOracle;
-import com.google.gerrit.client.ui.RemoteSuggestBox;
-import com.google.gerrit.common.PageLinks;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.event.logical.shared.SelectionEvent;
-import com.google.gwt.event.logical.shared.SelectionHandler;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-
-public class MyWatchedProjectsScreen extends SettingsScreen {
-  private Button addNew;
-  private RemoteSuggestBox nameBox;
-  private HintTextBox filterTxt;
-  private MyWatchesTable watchesTab;
-  private Button browse;
-  private Button delSel;
-  private Grid grid;
-  private ProjectListPopup projectsPopup;
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    createWidgets();
-
-    /* top table */
-    grid = new Grid(2, 2);
-    grid.setStyleName(Gerrit.RESOURCES.css().infoBlock());
-    grid.setText(0, 0, Util.C.watchedProjectName());
-    final HorizontalPanel hp = new HorizontalPanel();
-    hp.add(nameBox);
-    hp.add(browse);
-    grid.setWidget(0, 1, hp);
-
-    grid.setText(1, 0, Util.C.watchedProjectFilter());
-    grid.setWidget(1, 1, filterTxt);
-
-    final CellFormatter fmt = grid.getCellFormatter();
-    fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().topmost());
-    fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().topmost());
-    fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().header());
-    fmt.addStyleName(1, 0, Gerrit.RESOURCES.css().header());
-    fmt.addStyleName(1, 0, Gerrit.RESOURCES.css().bottomheader());
-
-    final FlowPanel fp = new FlowPanel();
-    fp.setStyleName(Gerrit.RESOURCES.css().addWatchPanel());
-    fp.add(grid);
-    fp.add(addNew);
-    add(fp);
-
-    /* bottom table */
-    add(watchesTab);
-    add(delSel);
-
-    /* popup */
-    projectsPopup =
-        new ProjectListPopup() {
-          @Override
-          protected void onMovePointerTo(String projectName) {
-            // prevent user input from being overwritten by simply poping up
-            if (!projectsPopup.isPoppingUp() || "".equals(nameBox.getText())) {
-              nameBox.setText(projectName);
-            }
-          }
-
-          @Override
-          protected void openRow(String projectName) {
-            nameBox.setText(projectName);
-            doAddNew();
-          }
-        };
-    projectsPopup.initPopup(Util.C.projects(), PageLinks.SETTINGS_PROJECTS);
-  }
-
-  protected void createWidgets() {
-    nameBox = new RemoteSuggestBox(new ProjectNameSuggestOracle());
-    nameBox.setVisibleLength(50);
-    nameBox.setHintText(Util.C.defaultProjectName());
-    nameBox.addSelectionHandler(
-        new SelectionHandler<String>() {
-          @Override
-          public void onSelection(SelectionEvent<String> event) {
-            doAddNew();
-          }
-        });
-
-    filterTxt = new HintTextBox();
-    filterTxt.setVisibleLength(50);
-    filterTxt.setHintText(Util.C.defaultFilter());
-    filterTxt.addKeyPressHandler(
-        new KeyPressHandler() {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
-              doAddNew();
-            }
-          }
-        });
-
-    addNew = new Button(Util.C.buttonWatchProject());
-    addNew.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            doAddNew();
-          }
-        });
-
-    browse = new Button(Util.C.buttonBrowseProjects());
-    browse.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            int top = grid.getAbsoluteTop() - 50; // under page header
-            // Try to place it to the right of everything else, but not
-            // right justified
-            int left =
-                5
-                    + Math.max(
-                        grid.getAbsoluteLeft() + grid.getOffsetWidth(),
-                        watchesTab.getAbsoluteLeft() + watchesTab.getOffsetWidth());
-            projectsPopup.setPreferredCoordinates(top, left);
-            projectsPopup.displayPopup();
-          }
-        });
-
-    watchesTab = new MyWatchesTable();
-
-    delSel = new Button(Util.C.buttonDeleteSshKey());
-    delSel.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            watchesTab.deleteChecked();
-          }
-        });
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    populateWatches();
-  }
-
-  @Override
-  protected void onUnload() {
-    super.onUnload();
-    projectsPopup.closePopup();
-  }
-
-  protected void doAddNew() {
-    final String projectName = nameBox.getText().trim();
-    if ("".equals(projectName)) {
-      return;
-    }
-
-    addNew.setEnabled(false);
-    nameBox.setEnabled(false);
-    filterTxt.setEnabled(false);
-
-    final ProjectWatchInfo projectWatchInfo = JavaScriptObject.createObject().cast();
-    projectWatchInfo.project(projectName);
-    projectWatchInfo.filter(filterTxt.getText());
-
-    AccountApi.updateWatchedProject(
-        "self",
-        projectWatchInfo,
-        new GerritCallback<JsArray<ProjectWatchInfo>>() {
-          @Override
-          public void onSuccess(JsArray<ProjectWatchInfo> watchedProjects) {
-            addNew.setEnabled(true);
-            nameBox.setEnabled(true);
-            filterTxt.setEnabled(true);
-
-            nameBox.setText("");
-            watchesTab.insertWatch(projectWatchInfo);
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            addNew.setEnabled(true);
-            nameBox.setEnabled(true);
-            filterTxt.setEnabled(true);
-            super.onFailure(caught);
-          }
-        });
-  }
-
-  protected void populateWatches() {
-    AccountApi.getWatchedProjects(
-        "self",
-        new GerritCallback<JsArray<ProjectWatchInfo>>() {
-          @Override
-          public void onSuccess(JsArray<ProjectWatchInfo> watchedProjects) {
-            watchesTab.display(watchedProjects);
-            display();
-          }
-        });
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyWatchesTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyWatchesTable.java
deleted file mode 100644
index 0a61b2d..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyWatchesTable.java
+++ /dev/null
@@ -1,193 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.FancyFlexTable;
-import com.google.gerrit.client.ui.ProjectLink;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Label;
-import java.util.HashSet;
-import java.util.Set;
-
-public class MyWatchesTable extends FancyFlexTable<ProjectWatchInfo> {
-
-  public MyWatchesTable() {
-    table.setWidth("");
-    table.insertRow(1);
-    table.setText(0, 2, Util.C.watchedProjectName());
-    table.setText(0, 3, Util.C.watchedProjectColumnEmailNotifications());
-
-    final FlexCellFormatter fmt = table.getFlexCellFormatter();
-    fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().iconHeader());
-    fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader());
-    fmt.addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader());
-    fmt.setRowSpan(0, 0, 2);
-    fmt.setRowSpan(0, 1, 2);
-    fmt.setRowSpan(0, 2, 2);
-    fmt.getElement(0, 3).setPropertyString("align", "center");
-
-    fmt.setColSpan(0, 3, 5);
-    table.setText(1, 0, Util.C.watchedProjectColumnNewChanges());
-    table.setText(1, 1, Util.C.watchedProjectColumnNewPatchSets());
-    table.setText(1, 2, Util.C.watchedProjectColumnAllComments());
-    table.setText(1, 3, Util.C.watchedProjectColumnSubmittedChanges());
-    table.setText(1, 4, Util.C.watchedProjectColumnAbandonedChanges());
-    fmt.addStyleName(1, 0, Gerrit.RESOURCES.css().dataHeader());
-    fmt.addStyleName(1, 1, Gerrit.RESOURCES.css().dataHeader());
-    fmt.addStyleName(1, 2, Gerrit.RESOURCES.css().dataHeader());
-    fmt.addStyleName(1, 3, Gerrit.RESOURCES.css().dataHeader());
-    fmt.addStyleName(1, 4, Gerrit.RESOURCES.css().dataHeader());
-  }
-
-  public void deleteChecked() {
-    final Set<ProjectWatchInfo> infos = getCheckedProjectWatchInfos();
-    if (!infos.isEmpty()) {
-      AccountApi.deleteWatchedProjects(
-          "self",
-          infos,
-          new GerritCallback<JsArray<ProjectWatchInfo>>() {
-            @Override
-            public void onSuccess(JsArray<ProjectWatchInfo> watchedProjects) {
-              remove(infos);
-            }
-          });
-    }
-  }
-
-  protected void remove(Set<ProjectWatchInfo> infos) {
-    for (int row = 1; row < table.getRowCount(); ) {
-      final ProjectWatchInfo k = getRowItem(row);
-      if (k != null && infos.contains(k)) {
-        table.removeRow(row);
-      } else {
-        row++;
-      }
-    }
-  }
-
-  protected Set<ProjectWatchInfo> getCheckedProjectWatchInfos() {
-    final Set<ProjectWatchInfo> infos = new HashSet<>();
-    for (int row = 1; row < table.getRowCount(); row++) {
-      final ProjectWatchInfo k = getRowItem(row);
-      if (k != null && ((CheckBox) table.getWidget(row, 1)).getValue()) {
-        infos.add(k);
-      }
-    }
-    return infos;
-  }
-
-  public void insertWatch(ProjectWatchInfo k) {
-    final String newName = k.project();
-    int row = 1;
-    for (; row < table.getRowCount(); row++) {
-      final ProjectWatchInfo i = getRowItem(row);
-      if (i != null && i.project().compareTo(newName) >= 0) {
-        break;
-      }
-    }
-
-    table.insertRow(row);
-    applyDataRowStyle(row);
-    populate(row, k);
-  }
-
-  public void display(JsArray<ProjectWatchInfo> result) {
-    while (2 < table.getRowCount()) {
-      table.removeRow(table.getRowCount() - 1);
-    }
-
-    for (ProjectWatchInfo info : Natives.asList(result)) {
-      final int row = table.getRowCount();
-      table.insertRow(row);
-      applyDataRowStyle(row);
-      populate(row, info);
-    }
-  }
-
-  protected void populate(int row, ProjectWatchInfo info) {
-    final FlowPanel fp = new FlowPanel();
-    fp.add(new ProjectLink(info.project(), new Project.NameKey(info.project())));
-    if (info.filter() != null) {
-      Label filter = new Label(info.filter());
-      filter.setStyleName(Gerrit.RESOURCES.css().watchedProjectFilter());
-      fp.add(filter);
-    }
-
-    table.setWidget(row, 1, new CheckBox());
-    table.setWidget(row, 2, fp);
-
-    addNotifyButton(ProjectWatchInfo.Type.NEW_CHANGES, info, row, 3);
-    addNotifyButton(ProjectWatchInfo.Type.NEW_PATCHSETS, info, row, 4);
-    addNotifyButton(ProjectWatchInfo.Type.ALL_COMMENTS, info, row, 5);
-    addNotifyButton(ProjectWatchInfo.Type.SUBMITTED_CHANGES, info, row, 6);
-    addNotifyButton(ProjectWatchInfo.Type.ABANDONED_CHANGES, info, row, 7);
-
-    final FlexCellFormatter fmt = table.getFlexCellFormatter();
-    fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().iconCell());
-    fmt.addStyleName(row, 2, Gerrit.RESOURCES.css().dataCell());
-    fmt.addStyleName(row, 3, Gerrit.RESOURCES.css().dataCell());
-    fmt.addStyleName(row, 4, Gerrit.RESOURCES.css().dataCell());
-    fmt.addStyleName(row, 5, Gerrit.RESOURCES.css().dataCell());
-    fmt.addStyleName(row, 6, Gerrit.RESOURCES.css().dataCell());
-    fmt.addStyleName(row, 7, Gerrit.RESOURCES.css().dataCell());
-
-    setRowItem(row, info);
-  }
-
-  protected void addNotifyButton(
-      final ProjectWatchInfo.Type type, ProjectWatchInfo info, int row, int col) {
-    final CheckBox cbox = new CheckBox();
-
-    cbox.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            final Boolean oldVal = info.notify(type);
-            info.notify(type, cbox.getValue());
-            cbox.setEnabled(false);
-
-            AccountApi.updateWatchedProject(
-                "self",
-                info,
-                new GerritCallback<JsArray<ProjectWatchInfo>>() {
-                  @Override
-                  public void onSuccess(JsArray<ProjectWatchInfo> watchedProjects) {
-                    cbox.setEnabled(true);
-                  }
-
-                  @Override
-                  public void onFailure(Throwable caught) {
-                    cbox.setEnabled(true);
-                    info.notify(type, oldVal);
-                    cbox.setValue(oldVal);
-                    super.onFailure(caught);
-                  }
-                });
-          }
-        });
-
-    cbox.setValue(info.notify(type));
-    table.setWidget(row, col, cbox);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/NewAgreementScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/NewAgreementScreen.java
deleted file mode 100644
index 7c90884..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/NewAgreementScreen.java
+++ /dev/null
@@ -1,258 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.client.ErrorDialog;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.info.AgreementInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.NativeString;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.AccountScreen;
-import com.google.gerrit.client.ui.OnEditEnabler;
-import com.google.gerrit.client.ui.SmallHeading;
-import com.google.gerrit.common.PageLinks;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.http.client.Request;
-import com.google.gwt.http.client.RequestBuilder;
-import com.google.gwt.http.client.RequestCallback;
-import com.google.gwt.http.client.RequestException;
-import com.google.gwt.http.client.Response;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.FormPanel;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.InlineLabel;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.Panel;
-import com.google.gwt.user.client.ui.RadioButton;
-import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwtexpui.globalkey.client.NpTextBox;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-public class NewAgreementScreen extends AccountScreen {
-  private final String nextToken;
-  private Set<String> mySigned;
-  private List<AgreementInfo> available;
-  private AgreementInfo current;
-
-  private VerticalPanel radios;
-
-  private Panel agreementGroup;
-  private HTML agreementHtml;
-
-  private Panel finalGroup;
-  private NpTextBox yesIAgreeBox;
-  private Button submit;
-
-  public NewAgreementScreen() {
-    this(null);
-  }
-
-  public NewAgreementScreen(String token) {
-    nextToken = token != null ? token : PageLinks.SETTINGS_AGREEMENTS;
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    AccountApi.getAgreements(
-        "self",
-        new GerritCallback<JsArray<AgreementInfo>>() {
-          @Override
-          public void onSuccess(JsArray<AgreementInfo> result) {
-            if (isAttached()) {
-              mySigned = new HashSet<>();
-              for (AgreementInfo info : Natives.asList(result)) {
-                mySigned.add(info.name());
-              }
-              postRPC();
-            }
-          }
-        });
-
-    available = Gerrit.info().auth().contributorAgreements();
-    postRPC();
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    setPageTitle(Util.C.newAgreement());
-
-    final FlowPanel formBody = new FlowPanel();
-    radios = new VerticalPanel();
-    formBody.add(radios);
-
-    agreementGroup = new FlowPanel();
-    agreementGroup.add(new SmallHeading(Util.C.newAgreementReviewLegalHeading()));
-
-    agreementHtml = new HTML();
-    agreementHtml.setStyleName(Gerrit.RESOURCES.css().contributorAgreementLegal());
-    agreementGroup.add(agreementHtml);
-    formBody.add(agreementGroup);
-
-    finalGroup = new VerticalPanel();
-    finalGroup.add(new SmallHeading(Util.C.newAgreementCompleteHeading()));
-    final FlowPanel fp = new FlowPanel();
-    yesIAgreeBox = new NpTextBox();
-    yesIAgreeBox.setVisibleLength(Util.C.newAgreementIAGREE().length() + 8);
-    yesIAgreeBox.setMaxLength(Util.C.newAgreementIAGREE().length());
-    fp.add(yesIAgreeBox);
-    fp.add(new InlineLabel(Util.M.enterIAGREE(Util.C.newAgreementIAGREE())));
-    finalGroup.add(fp);
-    submit = new Button(Util.C.buttonSubmitNewAgreement());
-    submit.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            doSign();
-          }
-        });
-    finalGroup.add(submit);
-    formBody.add(finalGroup);
-    new OnEditEnabler(submit, yesIAgreeBox);
-
-    final FormPanel form = new FormPanel();
-    form.add(formBody);
-    add(form);
-  }
-
-  private void postRPC() {
-    if (mySigned != null && available != null) {
-      renderSelf();
-      display();
-    }
-  }
-
-  private void renderSelf() {
-    current = null;
-    agreementGroup.setVisible(false);
-    finalGroup.setVisible(false);
-    radios.clear();
-
-    final SmallHeading hdr = new SmallHeading();
-    if (available.isEmpty()) {
-      hdr.setText(Util.C.newAgreementNoneAvailable());
-    } else {
-      hdr.setText(Util.C.newAgreementSelectTypeHeading());
-    }
-    radios.add(hdr);
-
-    for (AgreementInfo cla : available) {
-      final RadioButton r = new RadioButton("cla_id", cla.name());
-      r.addStyleName(Gerrit.RESOURCES.css().contributorAgreementButton());
-      radios.add(r);
-
-      if (mySigned.contains(cla.name())) {
-        r.setEnabled(false);
-        final Label l = new Label(Util.C.newAgreementAlreadySubmitted());
-        l.setStyleName(Gerrit.RESOURCES.css().contributorAgreementAlreadySubmitted());
-        radios.add(l);
-      } else {
-        r.addClickHandler(
-            new ClickHandler() {
-              @Override
-              public void onClick(ClickEvent event) {
-                showCLA(cla);
-              }
-            });
-      }
-
-      if (cla.description() != null && !cla.description().equals("")) {
-        final Label l = new Label(cla.description());
-        l.setStyleName(Gerrit.RESOURCES.css().contributorAgreementShortDescription());
-        radios.add(l);
-      }
-    }
-  }
-
-  private void doSign() {
-    submit.setEnabled(false);
-
-    if (current == null || !Util.C.newAgreementIAGREE().equalsIgnoreCase(yesIAgreeBox.getText())) {
-      yesIAgreeBox.setText("");
-      yesIAgreeBox.setFocus(true);
-      return;
-    }
-    doEnterAgreement();
-  }
-
-  private void doEnterAgreement() {
-    AccountApi.enterAgreement(
-        "self",
-        current.name(),
-        new GerritCallback<NativeString>() {
-          @Override
-          public void onSuccess(NativeString result) {
-            Gerrit.display(nextToken);
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            yesIAgreeBox.setText("");
-            super.onFailure(caught);
-          }
-        });
-  }
-
-  private void showCLA(AgreementInfo cla) {
-    current = cla;
-    String url = cla.url();
-    if (url != null && url.length() > 0) {
-      agreementGroup.setVisible(true);
-      agreementHtml.setText(Gerrit.C.rpcStatusWorking());
-      if (!url.startsWith("http:") && !url.startsWith("https:")) {
-        url = GWT.getHostPageBaseURL() + url;
-      }
-      final RequestBuilder rb = new RequestBuilder(RequestBuilder.GET, url);
-      rb.setCallback(
-          new RequestCallback() {
-            @Override
-            public void onError(Request request, Throwable exception) {
-              new ErrorDialog(exception).center();
-            }
-
-            @Override
-            public void onResponseReceived(Request request, Response response) {
-              final String ct = response.getHeader("Content-Type");
-              if (response.getStatusCode() == 200
-                  && ct != null
-                  && (ct.equals("text/html") || ct.startsWith("text/html;"))) {
-                agreementHtml.setHTML(response.getText());
-              } else {
-                new ErrorDialog(response.getStatusText()).center();
-              }
-            }
-          });
-      try {
-        rb.send();
-      } catch (RequestException e) {
-        new ErrorDialog(e).show();
-      }
-    } else {
-      agreementGroup.setVisible(false);
-    }
-
-    finalGroup.setVisible(cla.autoVerifyGroup() != null);
-    yesIAgreeBox.setText("");
-    submit.setEnabled(false);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ProjectWatchInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ProjectWatchInfo.java
deleted file mode 100644
index fab25ae..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ProjectWatchInfo.java
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package com.google.gerrit.client.account;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class ProjectWatchInfo extends JavaScriptObject {
-
-  public enum Type {
-    NEW_CHANGES,
-    NEW_PATCHSETS,
-    ALL_COMMENTS,
-    SUBMITTED_CHANGES,
-    ABANDONED_CHANGES
-  }
-
-  public final native String project() /*-{ return this.project; }-*/;
-
-  public final native String filter() /*-{ return this.filter; }-*/;
-
-  public final native void project(String s) /*-{ this.project = s; }-*/;
-
-  public final native void filter(String s) /*-{ this.filter = s; }-*/;
-
-  public final void notify(ProjectWatchInfo.Type t, Boolean b) {
-    if (t == ProjectWatchInfo.Type.NEW_CHANGES) {
-      notifyNewChanges(b.booleanValue());
-    } else if (t == Type.NEW_PATCHSETS) {
-      notifyNewPatchSets(b.booleanValue());
-    } else if (t == Type.ALL_COMMENTS) {
-      notifyAllComments(b.booleanValue());
-    } else if (t == Type.SUBMITTED_CHANGES) {
-      notifySubmittedChanges(b.booleanValue());
-    } else if (t == Type.ABANDONED_CHANGES) {
-      notifyAbandonedChanges(b.booleanValue());
-    }
-  }
-
-  public final Boolean notify(ProjectWatchInfo.Type t) {
-    boolean b = false;
-    if (t == ProjectWatchInfo.Type.NEW_CHANGES) {
-      b = notifyNewChanges();
-    } else if (t == Type.NEW_PATCHSETS) {
-      b = notifyNewPatchSets();
-    } else if (t == Type.ALL_COMMENTS) {
-      b = notifyAllComments();
-    } else if (t == Type.SUBMITTED_CHANGES) {
-      b = notifySubmittedChanges();
-    } else if (t == Type.ABANDONED_CHANGES) {
-      b = notifyAbandonedChanges();
-    }
-    return Boolean.valueOf(b);
-  }
-
-  private native boolean
-      notifyNewChanges() /*-{ return this['notify_new_changes'] ? true : false; }-*/;
-
-  private native boolean
-      notifyNewPatchSets() /*-{ return this['notify_new_patch_sets'] ? true : false; }-*/;
-
-  private native boolean
-      notifyAllComments() /*-{ return this['notify_all_comments'] ? true : false; }-*/;
-
-  private native boolean
-      notifySubmittedChanges() /*-{ return this['notify_submitted_changes'] ? true : false; }-*/;
-
-  private native boolean
-      notifyAbandonedChanges() /*-{ return this['notify_abandoned_changes'] ? true : false; }-*/;
-
-  private native void notifyNewChanges(
-      boolean b) /*-{ this['notify_new_changes'] = b ? true : null; }-*/;
-
-  private native void notifyNewPatchSets(
-      boolean b) /*-{ this['notify_new_patch_sets'] = b ? true : null; }-*/;
-
-  private native void notifyAllComments(
-      boolean b) /*-{ this['notify_all_comments'] = b ? true : null; }-*/;
-
-  private native void notifySubmittedChanges(
-      boolean b) /*-{ this['notify_submitted_changes'] = b ? true : null; }-*/;
-
-  private native void notifyAbandonedChanges(
-      boolean b) /*-{ this['notify_abandoned_changes'] = b ? true : null; }-*/;
-
-  protected ProjectWatchInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/RegisterScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/RegisterScreen.java
deleted file mode 100644
index 29de14a..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/RegisterScreen.java
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.ui.AccountScreen;
-import com.google.gerrit.client.ui.InlineHyperlink;
-import com.google.gerrit.client.ui.SmallHeading;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.extensions.client.AccountFieldName;
-import com.google.gwt.i18n.client.LocaleInfo;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.FormPanel;
-import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
-
-public class RegisterScreen extends AccountScreen {
-  private final String nextToken;
-
-  public RegisterScreen(String next) {
-    nextToken = next;
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    display();
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    setPageTitle(Util.C.welcomeToGerritCodeReview());
-
-    final FlowPanel formBody = new FlowPanel();
-
-    final FlowPanel contactGroup = new FlowPanel();
-    contactGroup.setStyleName(Gerrit.RESOURCES.css().registerScreenSection());
-    contactGroup.add(new SmallHeading(Util.C.welcomeReviewContact()));
-    final HTML whereFrom = new HTML(Util.C.welcomeContactFrom());
-    whereFrom.setStyleName(Gerrit.RESOURCES.css().registerScreenExplain());
-    contactGroup.add(whereFrom);
-    contactGroup.add(
-        new ContactPanelShort() {
-          @Override
-          protected void display(AccountInfo account) {
-            super.display(account);
-
-            if ("".equals(nameTxt.getText())) {
-              // No name? Encourage the user to provide us something.
-              //
-              nameTxt.setFocus(true);
-              save.setEnabled(true);
-            }
-          }
-        });
-    formBody.add(contactGroup);
-
-    if (Gerrit.getUserAccount().username() == null
-        && Gerrit.info().auth().canEdit(AccountFieldName.USER_NAME)) {
-      final FlowPanel fp = new FlowPanel();
-      fp.setStyleName(Gerrit.RESOURCES.css().registerScreenSection());
-      fp.add(new SmallHeading(Util.C.welcomeUsernameHeading()));
-
-      final Grid userInfo = new Grid(1, 2);
-      final CellFormatter fmt = userInfo.getCellFormatter();
-      userInfo.setStyleName(Gerrit.RESOURCES.css().infoBlock());
-      userInfo.addStyleName(Gerrit.RESOURCES.css().accountInfoBlock());
-      fp.add(userInfo);
-
-      fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().topmost());
-      fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().topmost());
-      fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().bottomheader());
-
-      UsernameField field = new UsernameField();
-      if (LocaleInfo.getCurrentLocale().isRTL()) {
-        userInfo.setText(0, 1, Util.C.userName());
-        userInfo.setWidget(0, 0, field);
-        fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().header());
-      } else {
-        userInfo.setText(0, 0, Util.C.userName());
-        userInfo.setWidget(0, 1, field);
-        fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().header());
-      }
-
-      formBody.add(fp);
-    }
-
-    if (Gerrit.info().hasSshd()) {
-      final FlowPanel sshKeyGroup = new FlowPanel();
-      sshKeyGroup.setStyleName(Gerrit.RESOURCES.css().registerScreenSection());
-      sshKeyGroup.add(new SmallHeading(Util.C.welcomeSshKeyHeading()));
-      final HTML whySshKey = new HTML(Util.C.welcomeSshKeyText());
-      whySshKey.setStyleName(Gerrit.RESOURCES.css().registerScreenExplain());
-      sshKeyGroup.add(whySshKey);
-      sshKeyGroup.add(
-          new SshPanel() {
-            {
-              setKeyTableVisible(false);
-            }
-          });
-      formBody.add(sshKeyGroup);
-    }
-
-    final FlowPanel choices = new FlowPanel();
-    choices.setStyleName(Gerrit.RESOURCES.css().registerScreenNextLinks());
-    if (Gerrit.info().auth().useContributorAgreements()) {
-      final FlowPanel agreementGroup = new FlowPanel();
-      agreementGroup.setStyleName(Gerrit.RESOURCES.css().registerScreenSection());
-      agreementGroup.add(new SmallHeading(Util.C.welcomeAgreementHeading()));
-      final HTML whyAgreement = new HTML(Util.C.welcomeAgreementText());
-      whyAgreement.setStyleName(Gerrit.RESOURCES.css().registerScreenExplain());
-      agreementGroup.add(whyAgreement);
-
-      choices.add(new InlineHyperlink(Util.C.newAgreement(), PageLinks.SETTINGS_NEW_AGREEMENT));
-      choices.add(new InlineHyperlink(Util.C.welcomeAgreementLater(), nextToken));
-      formBody.add(agreementGroup);
-    } else {
-      choices.add(new InlineHyperlink(Util.C.welcomeContinue(), nextToken));
-    }
-    formBody.add(choices);
-
-    final FormPanel form = new FormPanel();
-    form.add(formBody);
-    add(form);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SettingsScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SettingsScreen.java
deleted file mode 100644
index a948595..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SettingsScreen.java
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.GerritUiExtensionPoint;
-import com.google.gerrit.client.api.ExtensionPanel;
-import com.google.gerrit.client.api.ExtensionSettingsScreen;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.MenuScreen;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.extensions.client.GitBasicAuthPolicy;
-import java.util.HashSet;
-import java.util.Set;
-
-public abstract class SettingsScreen extends MenuScreen {
-  private final Set<String> allMenuNames;
-  private final Set<String> ambiguousMenuNames;
-
-  public SettingsScreen() {
-    setRequiresSignIn(true);
-
-    allMenuNames = new HashSet<>();
-    ambiguousMenuNames = new HashSet<>();
-
-    linkByGerrit(Util.C.tabAccountSummary(), PageLinks.SETTINGS);
-    linkByGerrit(Util.C.tabPreferences(), PageLinks.SETTINGS_PREFERENCES);
-    linkByGerrit(Util.C.tabDiffPreferences(), PageLinks.SETTINGS_DIFF_PREFERENCES);
-    linkByGerrit(Util.C.tabEditPreferences(), PageLinks.SETTINGS_EDIT_PREFERENCES);
-    linkByGerrit(Util.C.tabWatchedProjects(), PageLinks.SETTINGS_PROJECTS);
-    linkByGerrit(Util.C.tabContactInformation(), PageLinks.SETTINGS_CONTACT);
-    if (Gerrit.info().hasSshd()) {
-      linkByGerrit(Util.C.tabSshKeys(), PageLinks.SETTINGS_SSHKEYS);
-    }
-    if (Gerrit.info().auth().isHttpPasswordSettingsEnabled()) {
-      linkByGerrit(Util.C.tabHttpAccess(), PageLinks.SETTINGS_HTTP_PASSWORD);
-    }
-    if (Gerrit.info().auth().isOAuth()
-        && Gerrit.info().auth().gitBasicAuthPolicy() == GitBasicAuthPolicy.OAUTH) {
-      linkByGerrit(Util.C.tabOAuthToken(), PageLinks.SETTINGS_OAUTH_TOKEN);
-    }
-    if (Gerrit.info().gerrit().editGpgKeys()) {
-      linkByGerrit(Util.C.tabGpgKeys(), PageLinks.SETTINGS_GPGKEYS);
-    }
-    linkByGerrit(Util.C.tabWebIdentities(), PageLinks.SETTINGS_WEBIDENT);
-    linkByGerrit(Util.C.tabMyGroups(), PageLinks.SETTINGS_MYGROUPS);
-    if (Gerrit.info().auth().useContributorAgreements()) {
-      linkByGerrit(Util.C.tabAgreements(), PageLinks.SETTINGS_AGREEMENTS);
-    }
-
-    for (String pluginName : ExtensionSettingsScreen.Definition.plugins()) {
-      for (ExtensionSettingsScreen.Definition def :
-          Natives.asList(ExtensionSettingsScreen.Definition.get(pluginName))) {
-        if (!allMenuNames.add(def.getMenu())) {
-          ambiguousMenuNames.add(def.getMenu());
-        }
-      }
-    }
-
-    for (String pluginName : ExtensionSettingsScreen.Definition.plugins()) {
-      for (ExtensionSettingsScreen.Definition def :
-          Natives.asList(ExtensionSettingsScreen.Definition.get(pluginName))) {
-        linkByPlugin(pluginName, def.getMenu(), PageLinks.toSettings(pluginName, def.getPath()));
-      }
-    }
-  }
-
-  private void linkByGerrit(String text, String target) {
-    allMenuNames.add(text);
-    link(text, target);
-  }
-
-  private void linkByPlugin(String pluginName, String text, String target) {
-    if (ambiguousMenuNames.contains(text)) {
-      text += " (" + pluginName + ")";
-    }
-    link(text, target);
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    setPageTitle(Util.C.settingsHeading());
-  }
-
-  protected ExtensionPanel createExtensionPoint(GerritUiExtensionPoint extensionPoint) {
-    ExtensionPanel extensionPanel = new ExtensionPanel(extensionPoint);
-    extensionPanel.putObject(GerritUiExtensionPoint.Key.ACCOUNT_INFO, Gerrit.getUserAccount());
-    return extensionPanel;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshHostKeyPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshHostKeyPanel.java
deleted file mode 100644
index 2dfc2ed..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshHostKeyPanel.java
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.ui.SmallHeading;
-import com.google.gerrit.common.data.SshHostKey;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwtexpui.clippy.client.CopyableLabel;
-
-class SshHostKeyPanel extends Composite {
-  SshHostKeyPanel(SshHostKey info) {
-    final FlowPanel body = new FlowPanel();
-    body.setStyleName(Gerrit.RESOURCES.css().sshHostKeyPanel());
-    body.add(new SmallHeading(Util.C.sshHostKeyTitle()));
-    {
-      final Label fpLbl = new Label(Util.C.sshHostKeyFingerprint());
-      fpLbl.setStyleName(Gerrit.RESOURCES.css().sshHostKeyPanelHeading());
-      body.add(fpLbl);
-      final Label fpVal = new Label(info.getFingerprint());
-      fpVal.setStyleName(Gerrit.RESOURCES.css().sshHostKeyPanelFingerprintData());
-      body.add(fpVal);
-    }
-    {
-      final HTML hdr = new HTML(Util.C.sshHostKeyKnownHostEntry());
-      hdr.setStyleName(Gerrit.RESOURCES.css().sshHostKeyPanelHeading());
-      body.add(hdr);
-
-      final CopyableLabel lbl;
-      lbl = new CopyableLabel(info.getHostIdent() + " " + info.getHostKey());
-      lbl.setPreviewText(SshPanel.elide(lbl.getText(), 80));
-      lbl.addStyleName(Gerrit.RESOURCES.css().sshHostKeyPanelKnownHostEntry());
-      body.add(lbl);
-    }
-    initWidget(body);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshKeyInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshKeyInfo.java
deleted file mode 100644
index 23b3d2d..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshKeyInfo.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class SshKeyInfo extends JavaScriptObject {
-  public final native int seq() /*-{ return this.seq || 0; }-*/;
-
-  public final native String sshPublicKey() /*-{ return this.ssh_public_key; }-*/;
-
-  public final native String encodedKey() /*-{ return this.encoded_key; }-*/;
-
-  public final native String algorithm() /*-{ return this.algorithm; }-*/;
-
-  public final native String comment() /*-{ return this.comment; }-*/;
-
-  public final native boolean isValid() /*-{ return this['valid'] ? true : false; }-*/;
-
-  protected SshKeyInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshPanel.java
deleted file mode 100644
index 6a8b44d..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshPanel.java
+++ /dev/null
@@ -1,387 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.client.ErrorDialog;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.VoidResult;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.ComplexDisclosurePanel;
-import com.google.gerrit.client.ui.FancyFlexTable;
-import com.google.gerrit.client.ui.SmallHeading;
-import com.google.gerrit.common.data.SshHostKey;
-import com.google.gerrit.common.errors.InvalidSshKeyException;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.logical.shared.ValueChangeHandler;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.HasHorizontalAlignment;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.Panel;
-import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwtexpui.clippy.client.CopyableLabel;
-import com.google.gwtexpui.globalkey.client.NpTextArea;
-import com.google.gwtjsonrpc.client.RemoteJsonException;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-
-class SshPanel extends Composite {
-  private SshKeyTable keys;
-
-  private Button showAddKeyBlock;
-  private Panel addKeyBlock;
-  private Button closeAddKeyBlock;
-  private Button clearNew;
-  private Button addNew;
-  private NpTextArea addTxt;
-  private Button deleteKey;
-
-  private Panel serverKeys;
-
-  private int loadCount;
-
-  SshPanel() {
-    final FlowPanel body = new FlowPanel();
-
-    showAddKeyBlock = new Button(Util.C.buttonShowAddSshKey());
-    showAddKeyBlock.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            showAddKeyBlock(true);
-          }
-        });
-
-    keys = new SshKeyTable();
-    body.add(keys);
-    {
-      final FlowPanel fp = new FlowPanel();
-      deleteKey = new Button(Util.C.buttonDeleteSshKey());
-      deleteKey.setEnabled(false);
-      deleteKey.addClickHandler(
-          new ClickHandler() {
-            @Override
-            public void onClick(ClickEvent event) {
-              keys.deleteChecked();
-            }
-          });
-      fp.add(deleteKey);
-      fp.add(showAddKeyBlock);
-      body.add(fp);
-    }
-
-    addKeyBlock = new VerticalPanel();
-    addKeyBlock.setVisible(false);
-    addKeyBlock.setStyleName(Gerrit.RESOURCES.css().addSshKeyPanel());
-    addKeyBlock.add(new SmallHeading(Util.C.addSshKeyPanelHeader()));
-
-    final ComplexDisclosurePanel addSshKeyHelp =
-        new ComplexDisclosurePanel(Util.C.addSshKeyHelpTitle(), false);
-    addSshKeyHelp.setContent(new HTML(Util.C.addSshKeyHelp()));
-    addKeyBlock.add(addSshKeyHelp);
-
-    addTxt = new NpTextArea();
-    addTxt.setVisibleLines(12);
-    addTxt.setCharacterWidth(80);
-    addTxt.setSpellCheck(false);
-    addKeyBlock.add(addTxt);
-
-    final HorizontalPanel buttons = new HorizontalPanel();
-    addKeyBlock.add(buttons);
-
-    clearNew = new Button(Util.C.buttonClearSshKeyInput());
-    clearNew.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            addTxt.setText("");
-            addTxt.setFocus(true);
-          }
-        });
-    buttons.add(clearNew);
-
-    addNew = new Button(Util.C.buttonAddSshKey());
-    addNew.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            doAddNew();
-          }
-        });
-    buttons.add(addNew);
-
-    closeAddKeyBlock = new Button(Util.C.buttonCloseAddSshKey());
-    closeAddKeyBlock.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            showAddKeyBlock(false);
-          }
-        });
-    buttons.add(closeAddKeyBlock);
-    buttons.setCellWidth(closeAddKeyBlock, "100%");
-    buttons.setCellHorizontalAlignment(closeAddKeyBlock, HasHorizontalAlignment.ALIGN_RIGHT);
-
-    body.add(addKeyBlock);
-
-    serverKeys = new FlowPanel();
-    body.add(serverKeys);
-
-    initWidget(body);
-  }
-
-  void setKeyTableVisible(boolean on) {
-    keys.setVisible(on);
-    deleteKey.setVisible(on);
-    closeAddKeyBlock.setVisible(on);
-  }
-
-  void doAddNew() {
-    final String txt = addTxt.getText();
-    if (txt != null && txt.length() > 0) {
-      addNew.setEnabled(false);
-      AccountApi.addSshKey(
-          "self",
-          txt,
-          new GerritCallback<SshKeyInfo>() {
-            @Override
-            public void onSuccess(SshKeyInfo k) {
-              addNew.setEnabled(true);
-              addTxt.setText("");
-              keys.addOneKey(k);
-              if (!keys.isVisible()) {
-                showAddKeyBlock(false);
-                setKeyTableVisible(true);
-                keys.updateDeleteButton();
-              }
-            }
-
-            @Override
-            public void onFailure(Throwable caught) {
-              addNew.setEnabled(true);
-
-              if (isInvalidSshKey(caught)) {
-                new ErrorDialog(Util.C.invalidSshKeyError()).center();
-
-              } else {
-                super.onFailure(caught);
-              }
-            }
-
-            private boolean isInvalidSshKey(Throwable caught) {
-              if (caught instanceof InvalidSshKeyException) {
-                return true;
-              }
-              return caught instanceof RemoteJsonException
-                  && InvalidSshKeyException.MESSAGE.equals(caught.getMessage());
-            }
-          });
-    }
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    refreshSshKeys();
-    Gerrit.SYSTEM_SVC.daemonHostKeys(
-        new GerritCallback<List<SshHostKey>>() {
-          @Override
-          public void onSuccess(List<SshHostKey> result) {
-            serverKeys.clear();
-            for (SshHostKey keyInfo : result) {
-              serverKeys.add(new SshHostKeyPanel(keyInfo));
-            }
-            if (++loadCount == 2) {
-              display();
-            }
-          }
-        });
-  }
-
-  private void refreshSshKeys() {
-    AccountApi.getSshKeys(
-        "self",
-        new GerritCallback<JsArray<SshKeyInfo>>() {
-          @Override
-          public void onSuccess(JsArray<SshKeyInfo> result) {
-            keys.display(Natives.asList(result));
-            if (result.length() == 0 && keys.isVisible()) {
-              showAddKeyBlock(true);
-            }
-            if (++loadCount == 2) {
-              display();
-            }
-          }
-        });
-  }
-
-  void display() {}
-
-  private void showAddKeyBlock(boolean show) {
-    showAddKeyBlock.setVisible(!show);
-    addKeyBlock.setVisible(show);
-  }
-
-  private class SshKeyTable extends FancyFlexTable<SshKeyInfo> {
-    private ValueChangeHandler<Boolean> updateDeleteHandler;
-
-    SshKeyTable() {
-      table.setWidth("");
-      table.setText(0, 2, Util.C.sshKeyStatus());
-      table.setText(0, 3, Util.C.sshKeyAlgorithm());
-      table.setText(0, 4, Util.C.sshKeyKey());
-      table.setText(0, 5, Util.C.sshKeyComment());
-
-      final FlexCellFormatter fmt = table.getFlexCellFormatter();
-      fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().iconHeader());
-      fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader());
-      fmt.addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader());
-      fmt.addStyleName(0, 4, Gerrit.RESOURCES.css().dataHeader());
-      fmt.addStyleName(0, 5, Gerrit.RESOURCES.css().dataHeader());
-
-      updateDeleteHandler =
-          new ValueChangeHandler<Boolean>() {
-            @Override
-            public void onValueChange(ValueChangeEvent<Boolean> event) {
-              updateDeleteButton();
-            }
-          };
-    }
-
-    void deleteChecked() {
-      final HashSet<Integer> sequenceNumbers = new HashSet<>();
-      for (int row = 1; row < table.getRowCount(); row++) {
-        final SshKeyInfo k = getRowItem(row);
-        if (k != null && ((CheckBox) table.getWidget(row, 1)).getValue()) {
-          sequenceNumbers.add(k.seq());
-        }
-      }
-      if (sequenceNumbers.isEmpty()) {
-        updateDeleteButton();
-      } else {
-        deleteKey.setEnabled(false);
-        AccountApi.deleteSshKeys(
-            "self",
-            sequenceNumbers,
-            new GerritCallback<VoidResult>() {
-              @Override
-              public void onSuccess(VoidResult result) {
-                for (int row = 1; row < table.getRowCount(); ) {
-                  final SshKeyInfo k = getRowItem(row);
-                  if (k != null && sequenceNumbers.contains(k.seq())) {
-                    table.removeRow(row);
-                  } else {
-                    row++;
-                  }
-                }
-                if (table.getRowCount() == 1) {
-                  display(Collections.<SshKeyInfo>emptyList());
-                } else {
-                  updateDeleteButton();
-                }
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {
-                refreshSshKeys();
-                updateDeleteButton();
-                super.onFailure(caught);
-              }
-            });
-      }
-    }
-
-    void display(List<SshKeyInfo> result) {
-      if (result.isEmpty()) {
-        setKeyTableVisible(false);
-        showAddKeyBlock(true);
-      } else {
-        while (1 < table.getRowCount()) {
-          table.removeRow(table.getRowCount() - 1);
-        }
-        for (SshKeyInfo k : result) {
-          addOneKey(k);
-        }
-        setKeyTableVisible(true);
-        deleteKey.setEnabled(false);
-      }
-    }
-
-    void addOneKey(SshKeyInfo k) {
-      final FlexCellFormatter fmt = table.getFlexCellFormatter();
-      final int row = table.getRowCount();
-      table.insertRow(row);
-      applyDataRowStyle(row);
-
-      final CheckBox sel = new CheckBox();
-      sel.addValueChangeHandler(updateDeleteHandler);
-
-      table.setWidget(row, 1, sel);
-      if (k.isValid()) {
-        table.setText(row, 2, "");
-        fmt.removeStyleName(
-            row,
-            2, //
-            Gerrit.RESOURCES.css().sshKeyPanelInvalid());
-      } else {
-        table.setText(row, 2, Util.C.sshKeyInvalid());
-        fmt.addStyleName(row, 2, Gerrit.RESOURCES.css().sshKeyPanelInvalid());
-      }
-      table.setText(row, 3, k.algorithm());
-
-      CopyableLabel keyLabel = new CopyableLabel(k.sshPublicKey());
-      keyLabel.setPreviewText(elide(k.encodedKey(), 40));
-      table.setWidget(row, 4, keyLabel);
-
-      table.setText(row, 5, k.comment());
-
-      fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().iconCell());
-      fmt.addStyleName(row, 4, Gerrit.RESOURCES.css().sshKeyPanelEncodedKey());
-      for (int c = 2; c <= 5; c++) {
-        fmt.addStyleName(row, c, Gerrit.RESOURCES.css().dataCell());
-      }
-
-      setRowItem(row, k);
-    }
-
-    void updateDeleteButton() {
-      boolean on = false;
-      for (int row = 1; row < table.getRowCount(); row++) {
-        CheckBox sel = (CheckBox) table.getWidget(row, 1);
-        if (sel.getValue()) {
-          on = true;
-          break;
-        }
-      }
-      deleteKey.setEnabled(on);
-    }
-  }
-
-  static String elide(String s, int len) {
-    if (s == null || s.length() < len || len <= 10) {
-      return s;
-    }
-    return s.substring(0, len - 10) + "..." + s.substring(s.length() - 10);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernameField.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernameField.java
deleted file mode 100644
index 4fdd067..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernameField.java
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.client.ConfirmationCallback;
-import com.google.gerrit.client.ConfirmationDialog;
-import com.google.gerrit.client.ErrorDialog;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.NativeString;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.client.ui.OnEditEnabler;
-import com.google.gerrit.extensions.client.AccountFieldName;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwtexpui.clippy.client.CopyableLabel;
-import com.google.gwtexpui.globalkey.client.NpTextBox;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-
-class UsernameField extends Composite {
-  // If these regular expressions are modified the same modifications should be done to the
-  // corresponding regular expressions in the
-  // com.google.gerrit.server.account.externalids.ExternalId class.
-  private static final String USER_NAME_PATTERN_FIRST_REGEX = "[a-zA-Z0-9]";
-  private static final String USER_NAME_PATTERN_REST_REGEX = "[a-zA-Z0-9.!#$%&’*+=?^_`\\{|\\}~@-]";
-
-  private CopyableLabel userNameLbl;
-  private NpTextBox userNameTxt;
-  private Button setUserName;
-
-  UsernameField() {
-    String user = Gerrit.getUserAccount().username();
-    userNameLbl = new CopyableLabel(user != null ? user : "");
-    userNameLbl.setStyleName(Gerrit.RESOURCES.css().accountUsername());
-
-    if (user != null || !canEditUserName()) {
-      initWidget(userNameLbl);
-
-    } else {
-      final FlowPanel body = new FlowPanel();
-      initWidget(body);
-      setStyleName(Gerrit.RESOURCES.css().usernameField());
-
-      userNameTxt = new NpTextBox();
-      userNameTxt.addKeyPressHandler(new UserNameValidator());
-      userNameTxt.addStyleName(Gerrit.RESOURCES.css().accountUsername());
-      userNameTxt.setVisibleLength(16);
-      userNameTxt.addKeyPressHandler(
-          new KeyPressHandler() {
-            @Override
-            public void onKeyPress(KeyPressEvent event) {
-              if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
-                confirmSetUserName();
-              }
-            }
-          });
-
-      setUserName = new Button(Util.C.buttonSetUserName());
-      setUserName.setVisible(canEditUserName());
-      setUserName.setEnabled(false);
-      setUserName.addClickHandler(
-          new ClickHandler() {
-            @Override
-            public void onClick(ClickEvent event) {
-              confirmSetUserName();
-            }
-          });
-      new OnEditEnabler(setUserName, userNameTxt);
-
-      userNameLbl.setVisible(false);
-      body.add(userNameLbl);
-      body.add(userNameTxt);
-      body.add(setUserName);
-    }
-  }
-
-  private boolean canEditUserName() {
-    return Gerrit.info().auth().canEdit(AccountFieldName.USER_NAME);
-  }
-
-  private void confirmSetUserName() {
-    new ConfirmationDialog(
-            Util.C.confirmSetUserNameTitle(),
-            new SafeHtmlBuilder().append(Util.C.confirmSetUserName()),
-            new ConfirmationCallback() {
-              @Override
-              public void onOk() {
-                doSetUserName();
-              }
-            })
-        .center();
-  }
-
-  private void doSetUserName() {
-    if (!canEditUserName()) {
-      return;
-    }
-
-    enableUI(false);
-
-    String newName = userNameTxt.getText();
-    if ("".equals(newName)) {
-      newName = null;
-    }
-    final String newUserName = newName;
-
-    AccountApi.setUsername(
-        "self",
-        newUserName,
-        new GerritCallback<NativeString>() {
-          @Override
-          public void onSuccess(NativeString result) {
-            Gerrit.getUserAccount().username(newUserName);
-            userNameLbl.setText(newUserName);
-            userNameLbl.setVisible(true);
-            userNameTxt.setVisible(false);
-            setUserName.setVisible(false);
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            enableUI(true);
-            if (RestApi.isExpected(422 /* Unprocessable Entity */)) {
-              new ErrorDialog(Util.C.invalidUserName()).center();
-            } else {
-              super.onFailure(caught);
-            }
-          }
-        });
-  }
-
-  private void enableUI(boolean on) {
-    userNameTxt.setEnabled(on);
-    setUserName.setEnabled(on);
-  }
-
-  private static final class UserNameValidator implements KeyPressHandler {
-    @Override
-    public void onKeyPress(KeyPressEvent event) {
-      final char code = event.getCharCode();
-      final int nativeCode = event.getNativeEvent().getKeyCode();
-      switch (nativeCode) {
-        case KeyCodes.KEY_ALT:
-        case KeyCodes.KEY_BACKSPACE:
-        case KeyCodes.KEY_CTRL:
-        case KeyCodes.KEY_DELETE:
-        case KeyCodes.KEY_DOWN:
-        case KeyCodes.KEY_END:
-        case KeyCodes.KEY_ENTER:
-        case KeyCodes.KEY_ESCAPE:
-        case KeyCodes.KEY_HOME:
-        case KeyCodes.KEY_LEFT:
-        case KeyCodes.KEY_PAGEDOWN:
-        case KeyCodes.KEY_PAGEUP:
-        case KeyCodes.KEY_RIGHT:
-        case KeyCodes.KEY_SHIFT:
-        case KeyCodes.KEY_TAB:
-        case KeyCodes.KEY_UP:
-          // Allow these, even if one of their assigned codes is
-          // identical to an ASCII character we do not want to
-          // allow in the box.
-          //
-          // We still want to let the user move around the input box
-          // with their arrow keys, or to move between fields using tab.
-          // Invalid characters introduced will be caught through the
-          // server's own validation of the input data.
-          //
-          break;
-
-        default:
-          final TextBox box = (TextBox) event.getSource();
-          final String re;
-          if (box.getCursorPos() == 0) {
-            re = USER_NAME_PATTERN_FIRST_REGEX;
-          } else {
-            re = USER_NAME_PATTERN_REST_REGEX;
-          }
-          if (!String.valueOf(code).matches("^" + re + "$")) {
-            event.preventDefault();
-            event.stopPropagation();
-          }
-      }
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/Util.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/Util.java
deleted file mode 100644
index 1c4870c..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/Util.java
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.common.data.ProjectAdminService;
-import com.google.gwt.core.client.GWT;
-import com.google.gwtjsonrpc.client.JsonUtil;
-
-public class Util {
-  public static final AccountConstants C = GWT.create(AccountConstants.class);
-  public static final AccountMessages M = GWT.create(AccountMessages.class);
-  public static final ProjectAdminService PROJECT_SVC;
-
-  static {
-    PROJECT_SVC = GWT.create(ProjectAdminService.class);
-    JsonUtil.bind(PROJECT_SVC, "rpc/ProjectAdminService");
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ValidateEmailScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ValidateEmailScreen.java
deleted file mode 100644
index b66f108..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ValidateEmailScreen.java
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.account;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.VoidResult;
-import com.google.gerrit.client.config.ConfigServerApi;
-import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gerrit.client.ui.AccountScreen;
-import com.google.gerrit.common.PageLinks;
-
-public class ValidateEmailScreen extends AccountScreen {
-  private final String magicToken;
-
-  public ValidateEmailScreen(String magicToken) {
-    this.magicToken = magicToken;
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    setPageTitle(Util.C.settingsHeading());
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    ConfigServerApi.confirmEmail(
-        magicToken,
-        new ScreenLoadCallback<VoidResult>(this) {
-          @Override
-          protected void preDisplay(VoidResult result) {}
-
-          @Override
-          protected void postDisplay() {
-            Gerrit.display(PageLinks.SETTINGS_CONTACT);
-          }
-        });
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/actions/ActionButton.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/actions/ActionButton.java
deleted file mode 100644
index 85937db..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/actions/ActionButton.java
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.actions;
-
-import com.google.gerrit.client.api.ActionContext;
-import com.google.gerrit.client.api.ChangeGlue;
-import com.google.gerrit.client.api.EditGlue;
-import com.google.gerrit.client.api.ProjectGlue;
-import com.google.gerrit.client.api.RevisionGlue;
-import com.google.gerrit.client.info.ActionInfo;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.ChangeInfo.EditInfo;
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.client.projects.BranchInfo;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-
-public class ActionButton extends Button implements ClickHandler {
-  private final Project.NameKey project;
-  private final BranchInfo branch;
-  private final ChangeInfo change;
-  private final EditInfo edit;
-  private final RevisionInfo revision;
-  private final ActionInfo action;
-  private ActionContext ctx;
-
-  public ActionButton(Project.NameKey project, ActionInfo action) {
-    this(project, null, null, null, null, action);
-  }
-
-  public ActionButton(Project.NameKey project, BranchInfo branch, ActionInfo action) {
-    this(project, branch, null, null, null, action);
-  }
-
-  public ActionButton(ChangeInfo change, ActionInfo action) {
-    this(null, null, change, null, null, action);
-  }
-
-  public ActionButton(ChangeInfo change, RevisionInfo revision, ActionInfo action) {
-    this(null, null, change, null, revision, action);
-  }
-
-  private ActionButton(
-      Project.NameKey project,
-      BranchInfo branch,
-      ChangeInfo change,
-      EditInfo edit,
-      RevisionInfo revision,
-      ActionInfo action) {
-    super(new SafeHtmlBuilder().openDiv().append(action.label()).closeDiv());
-    setStyleName("");
-    setTitle(action.title());
-    setEnabled(action.enabled());
-    addClickHandler(this);
-
-    this.project = project;
-    this.branch = branch;
-    this.change = change;
-    this.edit = edit;
-    this.revision = revision;
-    this.action = action;
-  }
-
-  @Override
-  public void onClick(ClickEvent event) {
-    if (ctx != null && ctx.has_popup()) {
-      ctx.hide();
-      ctx = null;
-      return;
-    }
-
-    if (revision != null) {
-      RevisionGlue.onAction(change, revision, action, this);
-    } else if (edit != null) {
-      EditGlue.onAction(change, edit, action, this);
-    } else if (change != null) {
-      ChangeGlue.onAction(change, action, this);
-    } else if (branch != null) {
-      ProjectGlue.onAction(project, branch, action, this);
-    } else if (project != null) {
-      ProjectGlue.onAction(project, action, this);
-    }
-  }
-
-  @Override
-  public void onUnload() {
-    if (ctx != null) {
-      if (ctx.has_popup()) {
-        ctx.hide();
-      }
-      ctx = null;
-    }
-    super.onUnload();
-  }
-
-  public void link(ActionContext ctx) {
-    this.ctx = ctx;
-  }
-
-  public void unlink() {
-    ctx = null;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccessSectionEditor.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccessSectionEditor.java
deleted file mode 100644
index 7bd8b82..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccessSectionEditor.java
+++ /dev/null
@@ -1,295 +0,0 @@
-// Copyright (C) 2011 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import static java.util.stream.Collectors.toCollection;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.common.data.AccessSection;
-import com.google.gerrit.common.data.LabelType;
-import com.google.gerrit.common.data.Permission;
-import com.google.gerrit.common.data.ProjectAccess;
-import com.google.gerrit.common.data.RefConfigSection;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;
-import com.google.gwt.dom.client.DivElement;
-import com.google.gwt.dom.client.SpanElement;
-import com.google.gwt.dom.client.Style.Display;
-import com.google.gwt.editor.client.Editor;
-import com.google.gwt.editor.client.EditorDelegate;
-import com.google.gwt.editor.client.ValueAwareEditor;
-import com.google.gwt.editor.client.adapters.EditorSource;
-import com.google.gwt.editor.client.adapters.ListEditor;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.MouseOutEvent;
-import com.google.gwt.event.dom.client.MouseOverEvent;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.logical.shared.ValueChangeHandler;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.ValueListBox;
-import java.util.ArrayList;
-import java.util.List;
-
-public class AccessSectionEditor extends Composite
-    implements Editor<AccessSection>, ValueAwareEditor<AccessSection> {
-  interface Binder extends UiBinder<HTMLPanel, AccessSectionEditor> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  @UiField ValueEditor<String> name;
-
-  @UiField FlowPanel permissionContainer;
-  ListEditor<Permission, PermissionEditor> permissions;
-
-  @UiField DivElement addContainer;
-
-  @UiField(provided = true)
-  @Editor.Ignore
-  ValueListBox<String> permissionSelector;
-
-  @UiField SpanElement deletedName;
-
-  @UiField Anchor deleteSection;
-
-  @UiField DivElement normal;
-  @UiField DivElement deleted;
-
-  @UiField SpanElement sectionType;
-  @UiField SpanElement sectionName;
-
-  private final ProjectAccess projectAccess;
-  private AccessSection value;
-  private boolean editing;
-  private boolean readOnly;
-  private boolean isDeleted;
-
-  public AccessSectionEditor(ProjectAccess access) {
-    projectAccess = access;
-    permissionSelector = new ValueListBox<>(new PermissionNameRenderer(access.getCapabilities()));
-    permissionSelector.addValueChangeHandler(
-        new ValueChangeHandler<String>() {
-          @Override
-          public void onValueChange(ValueChangeEvent<String> event) {
-            if (!AdminConstants.I.addPermission().equals(event.getValue())) {
-              onAddPermission(event.getValue());
-            }
-          }
-        });
-
-    initWidget(uiBinder.createAndBindUi(this));
-    permissions = ListEditor.of(new PermissionEditorSource());
-  }
-
-  @UiHandler("deleteSection")
-  void onDeleteHover(@SuppressWarnings("unused") MouseOverEvent event) {
-    normal.addClassName(AdminResources.I.css().deleteSectionHover());
-  }
-
-  @UiHandler("deleteSection")
-  void onDeleteNonHover(@SuppressWarnings("unused") MouseOutEvent event) {
-    normal.removeClassName(AdminResources.I.css().deleteSectionHover());
-  }
-
-  @UiHandler("deleteSection")
-  void onDeleteSection(@SuppressWarnings("unused") ClickEvent event) {
-    isDeleted = true;
-
-    if (name.isVisible() && RefConfigSection.isValid(name.getValue())) {
-      deletedName.setInnerText(AdminMessages.I.deletedReference(name.getValue()));
-    } else {
-      String name = AdminConstants.I.sectionNames().get(value.getName());
-      if (name == null) {
-        name = value.getName();
-      }
-      deletedName.setInnerText(AdminMessages.I.deletedSection(name));
-    }
-
-    normal.getStyle().setDisplay(Display.NONE);
-    deleted.getStyle().setDisplay(Display.BLOCK);
-  }
-
-  @UiHandler("undoDelete")
-  void onUndoDelete(@SuppressWarnings("unused") ClickEvent event) {
-    isDeleted = false;
-    deleted.getStyle().setDisplay(Display.NONE);
-    normal.getStyle().setDisplay(Display.BLOCK);
-  }
-
-  void onAddPermission(String varName) {
-    int idx = permissions.getList().size();
-
-    Permission p = value.getPermission(varName, true);
-    permissions.getList().add(p);
-
-    PermissionEditor e = permissions.getEditors().get(idx);
-    e.beginAddRule();
-
-    rebuildPermissionSelector();
-  }
-
-  void editRefPattern() {
-    name.edit();
-    Scheduler.get()
-        .scheduleDeferred(
-            new ScheduledCommand() {
-              @Override
-              public void execute() {
-                name.setFocus(true);
-              }
-            });
-  }
-
-  void enableEditing() {
-    readOnly = false;
-    addContainer.getStyle().setDisplay(Display.BLOCK);
-    rebuildPermissionSelector();
-  }
-
-  boolean isDeleted() {
-    return isDeleted;
-  }
-
-  @Override
-  public void setValue(AccessSection value) {
-    sortPermissions(value);
-
-    this.value = value;
-    this.readOnly = !editing || !(projectAccess.isOwnerOf(value) || projectAccess.canUpload());
-
-    name.setEnabled(!readOnly);
-    deleteSection.setVisible(!readOnly);
-
-    if (RefConfigSection.isValid(value.getName())) {
-      name.setVisible(true);
-      name.setIgnoreEditorValue(false);
-      sectionType.setInnerText(AdminConstants.I.sectionTypeReference());
-
-    } else {
-      name.setVisible(false);
-      name.setIgnoreEditorValue(true);
-
-      String name = AdminConstants.I.sectionNames().get(value.getName());
-      if (name != null) {
-        sectionType.setInnerText(name);
-        sectionName.getStyle().setDisplay(Display.NONE);
-      } else {
-        sectionType.setInnerText(AdminConstants.I.sectionTypeSection());
-        sectionName.setInnerText(value.getName());
-        sectionName.getStyle().clearDisplay();
-      }
-    }
-
-    if (readOnly) {
-      addContainer.getStyle().setDisplay(Display.NONE);
-    } else {
-      enableEditing();
-    }
-  }
-
-  private void sortPermissions(AccessSection accessSection) {
-    accessSection.setPermissions(
-        accessSection.getPermissions().stream().sorted().collect(toCollection(ArrayList::new)));
-  }
-
-  void setEditing(boolean editing) {
-    this.editing = editing;
-  }
-
-  private void rebuildPermissionSelector() {
-    List<String> perms = new ArrayList<>();
-
-    if (AccessSection.GLOBAL_CAPABILITIES.equals(value.getName())) {
-      for (String varName : projectAccess.getCapabilities().keySet()) {
-        addPermission(varName, perms);
-      }
-    } else if (RefConfigSection.isValid(value.getName())) {
-      for (LabelType t : projectAccess.getLabelTypes().getLabelTypes()) {
-        addPermission(Permission.forLabel(t.getName()), perms);
-      }
-      for (LabelType t : projectAccess.getLabelTypes().getLabelTypes()) {
-        addPermission(Permission.forLabelAs(t.getName()), perms);
-      }
-      for (String varName : AdminConstants.I.permissionNames().keySet()) {
-        addPermission(varName, perms);
-      }
-    }
-    if (perms.isEmpty()) {
-      addContainer.getStyle().setDisplay(Display.NONE);
-    } else {
-      addContainer.getStyle().setDisplay(Display.BLOCK);
-      perms.add(0, AdminConstants.I.addPermission());
-      permissionSelector.setValue(AdminConstants.I.addPermission());
-      permissionSelector.setAcceptableValues(perms);
-    }
-  }
-
-  private void addPermission(String permissionName, List<String> permissionList) {
-    if (value.getPermission(permissionName) != null) {
-      return;
-    }
-    if (Gerrit.info().gerrit().isAllProjects(projectAccess.getProjectName())
-        && !Permission.canBeOnAllProjects(value.getName(), permissionName)) {
-      return;
-    }
-    permissionList.add(permissionName);
-  }
-
-  @Override
-  public void flush() {
-    List<Permission> src = permissions.getList();
-    List<Permission> keep = new ArrayList<>(src.size());
-
-    for (int i = 0; i < src.size(); i++) {
-      PermissionEditor e = (PermissionEditor) permissionContainer.getWidget(i);
-      if (!e.isDeleted()) {
-        keep.add(src.get(i));
-      }
-    }
-    value.setPermissions(keep);
-  }
-
-  @Override
-  public void onPropertyChange(String... paths) {}
-
-  @Override
-  public void setDelegate(EditorDelegate<AccessSection> delegate) {}
-
-  private class PermissionEditorSource extends EditorSource<PermissionEditor> {
-    @Override
-    public PermissionEditor create(int index) {
-      PermissionEditor subEditor =
-          new PermissionEditor(projectAccess, readOnly, value, projectAccess.getLabelTypes());
-      permissionContainer.insert(subEditor, index);
-      return subEditor;
-    }
-
-    @Override
-    public void dispose(PermissionEditor subEditor) {
-      subEditor.removeFromParent();
-    }
-
-    @Override
-    public void setIndex(PermissionEditor subEditor, int index) {
-      permissionContainer.insert(subEditor, index);
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccessSectionEditor.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccessSectionEditor.ui.xml
deleted file mode 100644
index 3710265..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccessSectionEditor.ui.xml
+++ /dev/null
@@ -1,157 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2011 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-  xmlns:ui='urn:ui:com.google.gwt.uibinder'
-  xmlns:g='urn:import:com.google.gwt.user.client.ui'
-  xmlns:e='urn:import:com.google.gwt.editor.ui.client'
-  xmlns:my='urn:import:com.google.gerrit.client.admin'
-  ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
-  ui:generateKeys='com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator'
-  ui:generateLocales='default,en'
-  >
-<ui:with field='res' type='com.google.gerrit.client.admin.AdminResources'/>
-<ui:style gss='false'>
-  @eval selectionColor com.google.gerrit.client.Gerrit.getTheme().selectionColor;
-  @eval trimColor com.google.gerrit.client.Gerrit.getTheme().trimColor;
-
-  .panel {
-    width: 50em;
-    position: relative;
-  }
-
-  .content {
-    margin-top: 4px;
-    margin-bottom: 4px;
-    padding-bottom: 2px;
-  }
-
-  .normal {
-    background-color: trimColor;
-  }
-
-  .deleted {
-    padding-left: 7px;
-    padding-bottom: 2px;
-  }
-
-  .header {
-    padding-left: 5px;
-    padding-right: 5px;
-  }
-  .headerText {
-    vertical-align: top;
-    white-space: nowrap;
-    font-weight: bold;
-  }
-  .headerTable {
-    border: 0;
-    width: 100%;
-    padding-right: 40px;
-  }
-
-  .header:hover {
-    background-color: selectionColor;
-  }
-
-  .name {
-    width: 100%;
-  }
-  .nameEdit {
-    width: 100%;
-  }
-
-  .permissionList {
-    margin-left: 5px;
-    margin-right: 5px;
-    margin-bottom: 5px;
-  }
-
-  .addContainer {
-    padding-left: 16px;
-    padding-right: 16px;
-    font-size: 80%;
-  }
-  .addContainer:hover {
-    background-color: selectionColor;
-  }
-
-  .deleteIcon {
-    position: absolute;
-    top: 5px;
-    right: 17px;
-  }
-
-  .undoIcon {
-    position: absolute;
-    top: 2px;
-    right: 17px;
-  }
-</ui:style>
-
-<g:HTMLPanel styleName='{style.panel}'>
-<div ui:field='normal' class='{style.normal} {style.content}'>
-  <div class='{style.header}'>
-    <table class='{style.headerTable}'><tr>
-      <td class='{style.headerText}'>
-        <span ui:field='sectionType'/>
-      </td>
-      <td width='100%'>
-        <my:ValueEditor
-            ui:field='name'
-            addStyleNames='{style.name}'
-            editTitle='Edit reference pattern'>
-          <ui:attribute name='editTitle'/>
-          <my:editor>
-            <my:RefPatternBox styleName='{style.nameEdit}'/>
-          </my:editor>
-        </my:ValueEditor>
-        <span ui:field='sectionName' class='{style.name}'/>
-      </td>
-    </tr></table>
-
-    <g:Anchor
-        ui:field='deleteSection'
-        href='javascript:void'
-        styleName='{style.deleteIcon} {res.css.deleteIcon}'
-        title='Delete this section (and nested rules)'>
-      <ui:attribute name='title'/>
-    </g:Anchor>
-  </div>
-
-  <g:FlowPanel
-      ui:field='permissionContainer'
-      styleName='{style.permissionList}'/>
-  <div ui:field='addContainer' class='{style.addContainer}'>
-    <g:ValueListBox ui:field='permissionSelector'/>
-  </div>
-</div>
-
-<div
-    ui:field='deleted'
-    class='{style.deleted} {res.css.deleted}'
-    style='display: none'>
-  <span ui:field='deletedName'/>
-  <g:Anchor
-      ui:field='undoDelete'
-      href='javascript:void'
-      styleName='{style.undoIcon} {res.css.undoIcon}'
-      title='Undo deletion'>
-    <ui:attribute name='title'/>
-  </g:Anchor>
-</div>
-</g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupAuditLogScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupAuditLogScreen.java
deleted file mode 100644
index 5e38a14..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupAuditLogScreen.java
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import static com.google.gerrit.client.FormatUtil.mediumFormat;
-import static com.google.gerrit.client.FormatUtil.name;
-
-import com.google.gerrit.client.Dispatcher;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.groups.GroupApi;
-import com.google.gerrit.client.groups.GroupAuditEventInfo;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.info.GroupInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.FancyFlexTable;
-import com.google.gerrit.client.ui.Hyperlink;
-import com.google.gerrit.client.ui.SmallHeading;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
-import java.util.List;
-
-public class AccountGroupAuditLogScreen extends AccountGroupScreen {
-  private AuditEventTable auditEventTable;
-
-  public AccountGroupAuditLogScreen(GroupInfo toShow, String token) {
-    super(toShow, token);
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    add(new SmallHeading(AdminConstants.I.headingAuditLog()));
-    auditEventTable = new AuditEventTable();
-    add(auditEventTable);
-  }
-
-  @Override
-  protected void display(GroupInfo group, boolean canModify) {
-    GroupApi.getAuditLog(
-        group.getGroupUUID(),
-        new GerritCallback<JsArray<GroupAuditEventInfo>>() {
-          @Override
-          public void onSuccess(JsArray<GroupAuditEventInfo> result) {
-            auditEventTable.display(Natives.asList(result));
-          }
-        });
-  }
-
-  private static class AuditEventTable extends FancyFlexTable<GroupAuditEventInfo> {
-    AuditEventTable() {
-      table.setText(0, 1, AdminConstants.I.columnDate());
-      table.setText(0, 2, AdminConstants.I.columnType());
-      table.setText(0, 3, AdminConstants.I.columnMember());
-      table.setText(0, 4, AdminConstants.I.columnByUser());
-
-      FlexCellFormatter fmt = table.getFlexCellFormatter();
-      fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().dataHeader());
-      fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader());
-      fmt.addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader());
-      fmt.addStyleName(0, 4, Gerrit.RESOURCES.css().dataHeader());
-    }
-
-    void display(List<GroupAuditEventInfo> auditEvents) {
-      while (1 < table.getRowCount()) {
-        table.removeRow(table.getRowCount() - 1);
-      }
-
-      for (GroupAuditEventInfo auditEvent : auditEvents) {
-        int row = table.getRowCount();
-        table.insertRow(row);
-        applyDataRowStyle(row);
-        populate(row, auditEvent);
-      }
-    }
-
-    void populate(int row, GroupAuditEventInfo auditEvent) {
-      FlexCellFormatter fmt = table.getFlexCellFormatter();
-      table.setText(row, 1, mediumFormat(auditEvent.date()));
-
-      switch (auditEvent.type()) {
-        case ADD_USER:
-        case ADD_GROUP:
-          table.setText(row, 2, AdminConstants.I.typeAdded());
-          break;
-        case REMOVE_USER:
-        case REMOVE_GROUP:
-          table.setText(row, 2, AdminConstants.I.typeRemoved());
-          break;
-      }
-
-      switch (auditEvent.type()) {
-        case ADD_USER:
-        case REMOVE_USER:
-          table.setText(row, 3, formatAccount(auditEvent.memberAsUser()));
-          break;
-        case ADD_GROUP:
-        case REMOVE_GROUP:
-          GroupInfo member = auditEvent.memberAsGroup();
-          if (AccountGroup.isInternalGroup(member.getGroupUUID())) {
-            table.setWidget(
-                row,
-                3,
-                new Hyperlink(formatGroup(member), Dispatcher.toGroup(member.getGroupUUID())));
-            fmt.getElement(row, 3).setTitle(null);
-          } else if (member.url() != null) {
-            Anchor a = new Anchor();
-            a.setText(formatGroup(member));
-            a.setHref(member.url());
-            a.setTitle("UUID " + member.getGroupUUID().get());
-            table.setWidget(row, 3, a);
-            fmt.getElement(row, 3).setTitle(null);
-          } else {
-            table.setText(row, 3, formatGroup(member));
-            fmt.getElement(row, 3).setTitle("UUID " + member.getGroupUUID().get());
-          }
-          break;
-      }
-
-      table.setText(row, 4, formatAccount(auditEvent.user()));
-
-      fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().dataCell());
-      fmt.addStyleName(row, 2, Gerrit.RESOURCES.css().dataCell());
-      fmt.addStyleName(row, 3, Gerrit.RESOURCES.css().dataCell());
-      fmt.addStyleName(row, 4, Gerrit.RESOURCES.css().dataCell());
-
-      setRowItem(row, auditEvent);
-    }
-  }
-
-  private static String formatAccount(AccountInfo account) {
-    StringBuilder b = new StringBuilder();
-    b.append(name(account));
-    b.append(" (");
-    b.append(account._accountId());
-    b.append(")");
-    return b.toString();
-  }
-
-  private static String formatGroup(GroupInfo group) {
-    return group.name() != null && !group.name().isEmpty()
-        ? group.name()
-        : group.getGroupUUID().get();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupInfoScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupInfoScreen.java
deleted file mode 100644
index 34a1ac9..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupInfoScreen.java
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.VoidResult;
-import com.google.gerrit.client.groups.GroupApi;
-import com.google.gerrit.client.info.GroupInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.ui.AccountGroupSuggestOracle;
-import com.google.gerrit.client.ui.OnEditEnabler;
-import com.google.gerrit.client.ui.RemoteSuggestBox;
-import com.google.gerrit.client.ui.SmallHeading;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwtexpui.clippy.client.CopyableLabel;
-import com.google.gwtexpui.globalkey.client.NpTextArea;
-import com.google.gwtexpui.globalkey.client.NpTextBox;
-
-public class AccountGroupInfoScreen extends AccountGroupScreen {
-  private CopyableLabel groupUUIDLabel;
-
-  private NpTextBox groupNameTxt;
-  private Button saveName;
-
-  private RemoteSuggestBox ownerTxt;
-  private Button saveOwner;
-
-  private NpTextArea descTxt;
-  private Button saveDesc;
-
-  private CheckBox visibleToAllCheckBox;
-  private Button saveGroupOptions;
-
-  public AccountGroupInfoScreen(GroupInfo toShow, String token) {
-    super(toShow, token);
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    initUUID();
-    initName();
-    initOwner();
-    initDescription();
-    initGroupOptions();
-  }
-
-  private void enableForm(boolean canModify) {
-    groupNameTxt.setEnabled(canModify);
-    ownerTxt.setEnabled(canModify);
-    descTxt.setEnabled(canModify);
-    visibleToAllCheckBox.setEnabled(canModify);
-  }
-
-  private void initUUID() {
-    final VerticalPanel groupUUIDPanel = new VerticalPanel();
-    groupUUIDPanel.setStyleName(Gerrit.RESOURCES.css().groupUUIDPanel());
-    groupUUIDPanel.add(new SmallHeading(AdminConstants.I.headingGroupUUID()));
-    groupUUIDLabel = new CopyableLabel("");
-    groupUUIDPanel.add(groupUUIDLabel);
-    add(groupUUIDPanel);
-  }
-
-  private void initName() {
-    final VerticalPanel groupNamePanel = new VerticalPanel();
-    groupNamePanel.setStyleName(Gerrit.RESOURCES.css().groupNamePanel());
-    groupNameTxt = new NpTextBox();
-    groupNameTxt.setStyleName(Gerrit.RESOURCES.css().groupNameTextBox());
-    groupNameTxt.setVisibleLength(60);
-    groupNamePanel.add(groupNameTxt);
-
-    saveName = new Button(AdminConstants.I.buttonRenameGroup());
-    saveName.setEnabled(false);
-    saveName.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            final String newName = groupNameTxt.getText().trim();
-            GroupApi.renameGroup(
-                getGroupUUID(),
-                newName,
-                new GerritCallback<com.google.gerrit.client.VoidResult>() {
-                  @Override
-                  public void onSuccess(com.google.gerrit.client.VoidResult result) {
-                    saveName.setEnabled(false);
-                    setPageTitle(AdminMessages.I.group(newName));
-                    groupNameTxt.setText(newName);
-                    if (getGroupUUID().equals(getOwnerGroupUUID())) {
-                      ownerTxt.setText(newName);
-                    }
-                  }
-                });
-          }
-        });
-    groupNamePanel.add(saveName);
-    add(groupNamePanel);
-  }
-
-  private void initOwner() {
-    final VerticalPanel ownerPanel = new VerticalPanel();
-    ownerPanel.setStyleName(Gerrit.RESOURCES.css().groupOwnerPanel());
-    ownerPanel.add(new SmallHeading(AdminConstants.I.headingOwner()));
-
-    final AccountGroupSuggestOracle accountGroupOracle = new AccountGroupSuggestOracle();
-    ownerTxt = new RemoteSuggestBox(accountGroupOracle);
-    ownerTxt.setStyleName(Gerrit.RESOURCES.css().groupOwnerTextBox());
-    ownerTxt.setVisibleLength(60);
-    ownerPanel.add(ownerTxt);
-
-    saveOwner = new Button(AdminConstants.I.buttonChangeGroupOwner());
-    saveOwner.setEnabled(false);
-    saveOwner.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            final String newOwner = ownerTxt.getText().trim();
-            if (newOwner.length() > 0) {
-              AccountGroup.UUID ownerUuid = accountGroupOracle.getUUID(newOwner);
-              String ownerId = ownerUuid != null ? ownerUuid.get() : newOwner;
-              GroupApi.setGroupOwner(
-                  getGroupUUID(),
-                  ownerId,
-                  new GerritCallback<GroupInfo>() {
-                    @Override
-                    public void onSuccess(GroupInfo result) {
-                      updateOwnerGroup(result);
-                      saveOwner.setEnabled(false);
-                    }
-                  });
-            }
-          }
-        });
-    ownerPanel.add(saveOwner);
-    add(ownerPanel);
-  }
-
-  private void initDescription() {
-    final VerticalPanel vp = new VerticalPanel();
-    vp.setStyleName(Gerrit.RESOURCES.css().groupDescriptionPanel());
-    vp.add(new SmallHeading(AdminConstants.I.headingDescription()));
-
-    descTxt = new NpTextArea();
-    descTxt.setVisibleLines(6);
-    descTxt.setCharacterWidth(60);
-    vp.add(descTxt);
-
-    saveDesc = new Button(AdminConstants.I.buttonSaveDescription());
-    saveDesc.setEnabled(false);
-    saveDesc.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            final String txt = descTxt.getText().trim();
-            GroupApi.setGroupDescription(
-                getGroupUUID(),
-                txt,
-                new GerritCallback<VoidResult>() {
-                  @Override
-                  public void onSuccess(VoidResult result) {
-                    saveDesc.setEnabled(false);
-                  }
-                });
-          }
-        });
-    vp.add(saveDesc);
-    add(vp);
-  }
-
-  private void initGroupOptions() {
-    final VerticalPanel groupOptionsPanel = new VerticalPanel();
-
-    final VerticalPanel vp = new VerticalPanel();
-    vp.setStyleName(Gerrit.RESOURCES.css().groupOptionsPanel());
-    vp.add(new SmallHeading(AdminConstants.I.headingGroupOptions()));
-
-    visibleToAllCheckBox = new CheckBox(AdminConstants.I.isVisibleToAll());
-    vp.add(visibleToAllCheckBox);
-    groupOptionsPanel.add(vp);
-
-    saveGroupOptions = new Button(AdminConstants.I.buttonSaveGroupOptions());
-    saveGroupOptions.setEnabled(false);
-    saveGroupOptions.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            GroupApi.setGroupOptions(
-                getGroupUUID(),
-                visibleToAllCheckBox.getValue(),
-                new GerritCallback<VoidResult>() {
-                  @Override
-                  public void onSuccess(VoidResult result) {
-                    saveGroupOptions.setEnabled(false);
-                  }
-                });
-          }
-        });
-    groupOptionsPanel.add(saveGroupOptions);
-
-    add(groupOptionsPanel);
-
-    final OnEditEnabler enabler = new OnEditEnabler(saveGroupOptions);
-    enabler.listenTo(visibleToAllCheckBox);
-  }
-
-  @Override
-  protected void display(GroupInfo group, boolean canModify) {
-    groupUUIDLabel.setText(group.getGroupUUID().get());
-    groupNameTxt.setText(group.name());
-    ownerTxt.setText(
-        group.owner() != null
-            ? group.owner()
-            : AdminMessages.I.deletedReference(group.getOwnerUUID().get()));
-    descTxt.setText(group.description());
-    visibleToAllCheckBox.setValue(group.options().isVisibleToAll());
-    setMembersTabVisible(AccountGroup.isInternalGroup(group.getGroupUUID()));
-
-    enableForm(canModify);
-    saveName.setVisible(canModify);
-    saveOwner.setVisible(canModify);
-    saveDesc.setVisible(canModify);
-    saveGroupOptions.setVisible(canModify);
-    new OnEditEnabler(saveDesc, descTxt);
-    new OnEditEnabler(saveName, groupNameTxt);
-    new OnEditEnabler(saveOwner, ownerTxt.getTextBox());
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupMembersScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupMembersScreen.java
deleted file mode 100644
index 6eaab5d..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupMembersScreen.java
+++ /dev/null
@@ -1,436 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import static java.util.Comparator.comparing;
-
-import com.google.gerrit.client.Dispatcher;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.VoidResult;
-import com.google.gerrit.client.groups.GroupApi;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.info.GroupInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.AccountGroupSuggestOracle;
-import com.google.gerrit.client.ui.AccountLinkPanel;
-import com.google.gerrit.client.ui.AccountSuggestOracle;
-import com.google.gerrit.client.ui.AddMemberBox;
-import com.google.gerrit.client.ui.FancyFlexTable;
-import com.google.gerrit.client.ui.Hyperlink;
-import com.google.gerrit.client.ui.SmallHeading;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Panel;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.List;
-
-public class AccountGroupMembersScreen extends AccountGroupScreen {
-
-  private MemberTable members;
-  private IncludeTable includes;
-
-  private Panel memberPanel;
-  private AddMemberBox addMemberBox;
-  private Button delMember;
-
-  private Panel includePanel;
-  private AddMemberBox addIncludeBox;
-  private Button delInclude;
-
-  private FlowPanel noMembersInfo;
-  private AccountGroupSuggestOracle accountGroupSuggestOracle;
-
-  public AccountGroupMembersScreen(GroupInfo toShow, String token) {
-    super(toShow, token);
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    initMemberList();
-    initIncludeList();
-    initNoMembersInfo();
-  }
-
-  private void enableForm(boolean canModify) {
-    addMemberBox.setEnabled(canModify);
-    members.setEnabled(canModify);
-    addIncludeBox.setEnabled(canModify);
-    includes.setEnabled(canModify);
-  }
-
-  private void initMemberList() {
-    addMemberBox =
-        new AddMemberBox(
-            AdminConstants.I.buttonAddGroupMember(),
-            AdminConstants.I.defaultAccountName(),
-            new AccountSuggestOracle());
-
-    addMemberBox.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            doAddNewMember();
-          }
-        });
-
-    members = new MemberTable();
-    members.addStyleName(Gerrit.RESOURCES.css().groupMembersTable());
-
-    delMember = new Button(AdminConstants.I.buttonDeleteGroupMembers());
-    delMember.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            members.deleteChecked();
-          }
-        });
-
-    memberPanel = new FlowPanel();
-    memberPanel.add(new SmallHeading(AdminConstants.I.headingMembers()));
-    memberPanel.add(addMemberBox);
-    memberPanel.add(members);
-    memberPanel.add(delMember);
-    add(memberPanel);
-  }
-
-  private void initIncludeList() {
-    accountGroupSuggestOracle = new AccountGroupSuggestOracle();
-    addIncludeBox =
-        new AddMemberBox(
-            AdminConstants.I.buttonAddIncludedGroup(),
-            AdminConstants.I.defaultAccountGroupName(),
-            accountGroupSuggestOracle);
-
-    addIncludeBox.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            doAddNewInclude();
-          }
-        });
-
-    includes = new IncludeTable();
-    includes.addStyleName(Gerrit.RESOURCES.css().groupIncludesTable());
-
-    delInclude = new Button(AdminConstants.I.buttonDeleteIncludedGroup());
-    delInclude.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            includes.deleteChecked();
-          }
-        });
-
-    includePanel = new FlowPanel();
-    includePanel.add(new SmallHeading(AdminConstants.I.headingIncludedGroups()));
-    includePanel.add(addIncludeBox);
-    includePanel.add(includes);
-    includePanel.add(delInclude);
-    add(includePanel);
-  }
-
-  private void initNoMembersInfo() {
-    noMembersInfo = new FlowPanel();
-    noMembersInfo.setVisible(false);
-    noMembersInfo.add(new SmallHeading(AdminConstants.I.noMembersInfo()));
-    add(noMembersInfo);
-  }
-
-  @Override
-  protected void display(GroupInfo group, boolean canModify) {
-    if (AccountGroup.isInternalGroup(group.getGroupUUID())) {
-      members.display(Natives.asList(group.members()));
-      includes.display(Natives.asList(group.includes()));
-    } else {
-      memberPanel.setVisible(false);
-      includePanel.setVisible(false);
-      noMembersInfo.setVisible(true);
-    }
-
-    enableForm(canModify);
-    delMember.setVisible(canModify);
-    delInclude.setVisible(canModify);
-  }
-
-  void doAddNewMember() {
-    final String nameEmail = addMemberBox.getText();
-    if (nameEmail.length() == 0) {
-      return;
-    }
-
-    addMemberBox.setEnabled(false);
-    GroupApi.addMember(
-        getGroupUUID(),
-        nameEmail,
-        new GerritCallback<AccountInfo>() {
-          @Override
-          public void onSuccess(AccountInfo memberInfo) {
-            addMemberBox.setEnabled(true);
-            addMemberBox.setText("");
-            members.insert(memberInfo);
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            addMemberBox.setEnabled(true);
-            super.onFailure(caught);
-          }
-        });
-  }
-
-  void doAddNewInclude() {
-    String groupName = addIncludeBox.getText();
-    if (groupName.length() == 0) {
-      return;
-    }
-
-    AccountGroup.UUID uuid = accountGroupSuggestOracle.getUUID(groupName);
-    if (uuid == null) {
-      return;
-    }
-
-    addIncludeBox.setEnabled(false);
-    GroupApi.addIncludedGroup(
-        getGroupUUID(),
-        uuid.get(),
-        new GerritCallback<GroupInfo>() {
-          @Override
-          public void onSuccess(GroupInfo result) {
-            addIncludeBox.setEnabled(true);
-            addIncludeBox.setText("");
-            includes.insert(result);
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            addIncludeBox.setEnabled(true);
-            super.onFailure(caught);
-          }
-        });
-  }
-
-  private class MemberTable extends FancyFlexTable<AccountInfo> {
-    private boolean enabled = true;
-
-    MemberTable() {
-      table.setText(0, 2, AdminConstants.I.columnMember());
-      table.setText(0, 3, AdminConstants.I.columnEmailAddress());
-
-      final FlexCellFormatter fmt = table.getFlexCellFormatter();
-      fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().iconHeader());
-      fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader());
-      fmt.addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader());
-    }
-
-    void setEnabled(boolean enabled) {
-      this.enabled = enabled;
-      for (int row = 1; row < table.getRowCount(); row++) {
-        final AccountInfo i = getRowItem(row);
-        if (i != null) {
-          ((CheckBox) table.getWidget(row, 1)).setEnabled(enabled);
-        }
-      }
-    }
-
-    void deleteChecked() {
-      final HashSet<Integer> ids = new HashSet<>();
-      for (int row = 1; row < table.getRowCount(); row++) {
-        final AccountInfo i = getRowItem(row);
-        if (i != null && ((CheckBox) table.getWidget(row, 1)).getValue()) {
-          ids.add(i._accountId());
-        }
-      }
-      if (!ids.isEmpty()) {
-        GroupApi.removeMembers(
-            getGroupUUID(),
-            ids,
-            new GerritCallback<VoidResult>() {
-              @Override
-              public void onSuccess(VoidResult result) {
-                for (int row = 1; row < table.getRowCount(); ) {
-                  final AccountInfo i = getRowItem(row);
-                  if (i != null && ids.contains(i._accountId())) {
-                    table.removeRow(row);
-                  } else {
-                    row++;
-                  }
-                }
-              }
-            });
-      }
-    }
-
-    void display(List<AccountInfo> result) {
-      while (1 < table.getRowCount()) {
-        table.removeRow(table.getRowCount() - 1);
-      }
-
-      for (AccountInfo i : result) {
-        final int row = table.getRowCount();
-        table.insertRow(row);
-        applyDataRowStyle(row);
-        populate(row, i);
-      }
-    }
-
-    void insert(AccountInfo info) {
-      Comparator<AccountInfo> c =
-          comparing((AccountInfo a) -> nullToEmpty(a.name()))
-              .thenComparing(a -> nullToEmpty(a.email()))
-              .thenComparing(AccountInfo::_accountId);
-      int insertPos = getInsertRow(c, info);
-      if (insertPos >= 0) {
-        table.insertRow(insertPos);
-        applyDataRowStyle(insertPos);
-        populate(insertPos, info);
-      }
-    }
-
-    void populate(int row, AccountInfo i) {
-      CheckBox checkBox = new CheckBox();
-      table.setWidget(row, 1, checkBox);
-      checkBox.setEnabled(enabled);
-      table.setWidget(row, 2, AccountLinkPanel.create(i));
-      table.setText(row, 3, i.email());
-
-      final FlexCellFormatter fmt = table.getFlexCellFormatter();
-      fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().iconCell());
-      fmt.addStyleName(row, 2, Gerrit.RESOURCES.css().dataCell());
-      fmt.addStyleName(row, 3, Gerrit.RESOURCES.css().dataCell());
-
-      setRowItem(row, i);
-    }
-  }
-
-  private class IncludeTable extends FancyFlexTable<GroupInfo> {
-    private boolean enabled = true;
-
-    IncludeTable() {
-      table.setText(0, 2, AdminConstants.I.columnGroupName());
-      table.setText(0, 3, AdminConstants.I.columnGroupDescription());
-
-      final FlexCellFormatter fmt = table.getFlexCellFormatter();
-      fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().iconHeader());
-      fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader());
-      fmt.addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader());
-    }
-
-    void setEnabled(boolean enabled) {
-      this.enabled = enabled;
-      for (int row = 1; row < table.getRowCount(); row++) {
-        final GroupInfo i = getRowItem(row);
-        if (i != null) {
-          ((CheckBox) table.getWidget(row, 1)).setEnabled(enabled);
-        }
-      }
-    }
-
-    void deleteChecked() {
-      final HashSet<AccountGroup.UUID> ids = new HashSet<>();
-      for (int row = 1; row < table.getRowCount(); row++) {
-        final GroupInfo i = getRowItem(row);
-        if (i != null && ((CheckBox) table.getWidget(row, 1)).getValue()) {
-          ids.add(i.getGroupUUID());
-        }
-      }
-      if (!ids.isEmpty()) {
-        GroupApi.removeIncludedGroups(
-            getGroupUUID(),
-            ids,
-            new GerritCallback<VoidResult>() {
-              @Override
-              public void onSuccess(VoidResult result) {
-                for (int row = 1; row < table.getRowCount(); ) {
-                  final GroupInfo i = getRowItem(row);
-                  if (i != null && ids.contains(i.getGroupUUID())) {
-                    table.removeRow(row);
-                  } else {
-                    row++;
-                  }
-                }
-              }
-            });
-      }
-    }
-
-    void display(List<GroupInfo> list) {
-      while (1 < table.getRowCount()) {
-        table.removeRow(table.getRowCount() - 1);
-      }
-
-      for (GroupInfo i : list) {
-        final int row = table.getRowCount();
-        table.insertRow(row);
-        applyDataRowStyle(row);
-        populate(row, i);
-      }
-    }
-
-    void insert(GroupInfo info) {
-      Comparator<GroupInfo> c =
-          comparing((GroupInfo g) -> nullToEmpty(g.name())).thenComparing(GroupInfo::getGroupUUID);
-      int insertPos = getInsertRow(c, info);
-      if (insertPos >= 0) {
-        table.insertRow(insertPos);
-        applyDataRowStyle(insertPos);
-        populate(insertPos, info);
-      }
-    }
-
-    void populate(int row, GroupInfo i) {
-      final FlexCellFormatter fmt = table.getFlexCellFormatter();
-
-      AccountGroup.UUID uuid = i.getGroupUUID();
-      CheckBox checkBox = new CheckBox();
-      table.setWidget(row, 1, checkBox);
-      checkBox.setEnabled(enabled);
-      if (AccountGroup.isInternalGroup(uuid)) {
-        table.setWidget(row, 2, new Hyperlink(i.name(), Dispatcher.toGroup(uuid)));
-        fmt.getElement(row, 2).setTitle(null);
-        table.setText(row, 3, i.description());
-      } else if (i.url() != null) {
-        Anchor a = new Anchor();
-        a.setText(i.name());
-        a.setHref(i.url());
-        a.setTitle("UUID " + uuid.get());
-        table.setWidget(row, 2, a);
-        fmt.getElement(row, 2).setTitle(null);
-      } else {
-        table.setText(row, 2, i.name());
-        fmt.getElement(row, 2).setTitle("UUID " + uuid.get());
-      }
-
-      fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().iconCell());
-      fmt.addStyleName(row, 2, Gerrit.RESOURCES.css().dataCell());
-      fmt.addStyleName(row, 3, Gerrit.RESOURCES.css().dataCell());
-
-      setRowItem(row, i);
-    }
-  }
-
-  // Like Guava's Strings#nullToEmpty, which can't be used in GWT UI code.
-  private static String nullToEmpty(String str) {
-    return str == null ? "" : str;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupScreen.java
deleted file mode 100644
index b67213b..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupScreen.java
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (C) 2011 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import static com.google.gerrit.client.Dispatcher.toGroup;
-
-import com.google.gerrit.client.groups.GroupApi;
-import com.google.gerrit.client.info.GroupInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.ui.MenuScreen;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-
-public abstract class AccountGroupScreen extends MenuScreen {
-  public static final String INFO = "info";
-  public static final String MEMBERS = "members";
-  public static final String AUDIT_LOG = "audit-log";
-
-  private final GroupInfo group;
-  private final String token;
-  private final String membersTabToken;
-  private final String auditLogTabToken;
-
-  public AccountGroupScreen(GroupInfo toShow, String token) {
-    setRequiresSignIn(true);
-
-    this.group = toShow;
-    this.token = token;
-    this.membersTabToken = getTabToken(token, MEMBERS);
-    this.auditLogTabToken = getTabToken(token, AUDIT_LOG);
-
-    link(AdminConstants.I.groupTabGeneral(), getTabToken(token, INFO));
-    link(
-        AdminConstants.I.groupTabMembers(),
-        membersTabToken,
-        AccountGroup.isInternalGroup(group.getGroupUUID()));
-  }
-
-  private String getTabToken(String token, String tab) {
-    if (token.startsWith("/admin/groups/uuid-")) {
-      return toGroup(group.getGroupUUID(), tab);
-    }
-    return toGroup(group.getGroupId(), tab);
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    setPageTitle(AdminMessages.I.group(group.name()));
-    display();
-    GroupApi.isGroupOwner(
-        group.name(),
-        new GerritCallback<Boolean>() {
-          @Override
-          public void onSuccess(Boolean result) {
-            if (result) {
-              link(
-                  AdminConstants.I.groupTabAuditLog(),
-                  auditLogTabToken,
-                  AccountGroup.isInternalGroup(group.getGroupUUID()));
-              setToken(token);
-            }
-            display(group, result);
-          }
-        });
-  }
-
-  protected abstract void display(GroupInfo group, boolean canModify);
-
-  protected AccountGroup.UUID getGroupUUID() {
-    return group.getGroupUUID();
-  }
-
-  protected void updateOwnerGroup(GroupInfo ownerGroup) {
-    group.setOwnerUUID(ownerGroup.getGroupUUID());
-    group.owner(ownerGroup.name());
-  }
-
-  protected AccountGroup.UUID getOwnerGroupUUID() {
-    return group.getOwnerUUID();
-  }
-
-  protected void setMembersTabVisible(boolean visible) {
-    setLinkVisible(membersTabToken, visible);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java
deleted file mode 100644
index 9def3b3..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java
+++ /dev/null
@@ -1,293 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.i18n.client.Constants;
-import java.util.Map;
-
-public interface AdminConstants extends Constants {
-  AdminConstants I = GWT.create(AdminConstants.class);
-
-  String defaultAccountName();
-
-  String defaultAccountGroupName();
-
-  String defaultBranchName();
-
-  String defaultTagName();
-
-  String defaultRevisionSpec();
-
-  String annotation();
-
-  String buttonDeleteIncludedGroup();
-
-  String buttonAddIncludedGroup();
-
-  String buttonDeleteGroupMembers();
-
-  String buttonAddGroupMember();
-
-  String buttonSaveDescription();
-
-  String buttonRenameGroup();
-
-  String buttonCreateGroup();
-
-  String buttonCreateProject();
-
-  String buttonChangeGroupOwner();
-
-  String buttonChangeGroupType();
-
-  String buttonSelectGroup();
-
-  String buttonSaveChanges();
-
-  String checkBoxEmptyCommit();
-
-  String checkBoxPermissionsOnly();
-
-  String useContentMerge();
-
-  String useContributorAgreements();
-
-  String useSignedOffBy();
-
-  String createNewChangeForAllNotInTarget();
-
-  String enableSignedPush();
-
-  String requireSignedPush();
-
-  String requireChangeID();
-
-  String rejectImplicitMerges();
-
-  String privateByDefault();
-
-  String workInProgressByDefault();
-
-  String enableReviewerByEmail();
-
-  String matchAuthorToCommitterDate();
-
-  String headingMaxObjectSizeLimit();
-
-  String headingGroupOptions();
-
-  String isVisibleToAll();
-
-  String buttonSaveGroupOptions();
-
-  String suggestedGroupLabel();
-
-  String parentSuggestions();
-
-  String buttonBrowseProjects();
-
-  String projects();
-
-  String projectRepoBrowser();
-
-  String headingGroupUUID();
-
-  String headingOwner();
-
-  String headingDescription();
-
-  String headingProjectOptions();
-
-  String headingProjectCommands();
-
-  String headingCommands();
-
-  String headingMembers();
-
-  String headingIncludedGroups();
-
-  String noMembersInfo();
-
-  String headingExternalGroup();
-
-  String headingCreateGroup();
-
-  String headingParentProjectName();
-
-  String columnProjectName();
-
-  String headingAgreements();
-
-  String headingAuditLog();
-
-  String headingProjectSubmitType();
-
-  String projectSubmitType_INHERIT();
-
-  String projectSubmitType_FAST_FORWARD_ONLY();
-
-  String projectSubmitType_MERGE_ALWAYS();
-
-  String projectSubmitType_MERGE_IF_NECESSARY();
-
-  String projectSubmitType_REBASE_IF_NECESSARY();
-
-  String projectSubmitType_REBASE_ALWAYS();
-
-  String projectSubmitType_CHERRY_PICK();
-
-  String headingProjectState();
-
-  String projectState_ACTIVE();
-
-  String projectState_READ_ONLY();
-
-  String projectState_HIDDEN();
-
-  String columnMember();
-
-  String columnEmailAddress();
-
-  String columnGroupName();
-
-  String columnGroupDescription();
-
-  String columnGroupType();
-
-  String columnGroupNotifications();
-
-  String columnGroupVisibleToAll();
-
-  String columnDate();
-
-  String columnType();
-
-  String columnByUser();
-
-  String typeAdded();
-
-  String typeRemoved();
-
-  String columnBranchName();
-
-  String columnBranchRevision();
-
-  String columnTagName();
-
-  String columnTagRevision();
-
-  String columnTagAnnotation();
-
-  String initialRevision();
-
-  String revision();
-
-  String buttonAddBranch();
-
-  String buttonDeleteBranch();
-
-  String buttonAddTag();
-
-  String buttonDeleteTag();
-
-  String saveHeadButton();
-
-  String cancelHeadButton();
-
-  String groupItemHelp();
-
-  String groupListTitle();
-
-  String groupFilter();
-
-  String createGroupTitle();
-
-  String groupTabGeneral();
-
-  String groupTabMembers();
-
-  String groupTabAuditLog();
-
-  String projectListTitle();
-
-  String projectFilter();
-
-  String createProjectTitle();
-
-  String projectListQueryLink();
-
-  String plugins();
-
-  String pluginEnabled();
-
-  String pluginDisabled();
-
-  String pluginSettingsToolTip();
-
-  String columnPluginName();
-
-  String columnPluginSettings();
-
-  String columnPluginVersion();
-
-  String columnPluginStatus();
-
-  String noGroupSelected();
-
-  String errorNoMatchingGroups();
-
-  String errorNoGitRepository();
-
-  String addPermission();
-
-  Map<String, String> permissionNames();
-
-  String refErrorEmpty();
-
-  String refErrorBeginSlash();
-
-  String refErrorDoubleSlash();
-
-  String refErrorNoSpace();
-
-  String refErrorPrintable();
-
-  String errorsMustBeFixed();
-
-  String sectionTypeReference();
-
-  String sectionTypeSection();
-
-  Map<String, String> sectionNames();
-
-  String pagedListPrev();
-
-  String pagedListNext();
-
-  String buttonCreate();
-
-  String buttonCreateDescription();
-
-  String buttonCreateChange();
-
-  String buttonCreateChangeDescription();
-
-  String buttonEditConfig();
-
-  String buttonEditConfigDescription();
-
-  String editConfigMessage();
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
deleted file mode 100644
index 7901f33..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
+++ /dev/null
@@ -1,204 +0,0 @@
-defaultAccountName = Name or Email
-defaultAccountGroupName = Group Name
-defaultBranchName = Branch Name
-defaultTagName = Tag Name
-defaultRevisionSpec = Revision (Branch or SHA-1)
-annotation = Annotation (optional)
-
-buttonDeleteIncludedGroup = Delete
-buttonAddIncludedGroup = Add
-buttonDeleteGroupMembers = Delete
-buttonAddGroupMember = Add
-buttonRenameGroup = Rename Group
-buttonSaveDescription = Save Description
-buttonCreateGroup = Create Group
-buttonCreateProject = Create Project
-buttonChangeGroupOwner = Change Owner
-buttonChangeGroupType = Change Type
-buttonSelectGroup = Select
-buttonSaveChanges = Save Changes
-checkBoxEmptyCommit = Create initial empty commit
-checkBoxPermissionsOnly = Only serve as parent for other projects
-buttonBrowseProjects = Browse
-projects = All projects
-projectRepoBrowser = Repository Browser
-useContentMerge = Allow content merges
-useContributorAgreements = Require a valid contributor agreement to upload
-useSignedOffBy = Require <code>Signed-off-by</code> in commit message
-createNewChangeForAllNotInTarget = Create a new change for every commit not in the target branch
-enableSignedPush = Enable signed push
-requireSignedPush = Require signed push
-requireChangeID = Require <code>Change-Id</code> in commit message
-rejectImplicitMerges = Reject implicit merges when changes are pushed for review
-privateByDefault = Set all new changes private by default
-workInProgressByDefault = Set all new changes work-in-progress by default
-headingMaxObjectSizeLimit = Maximum Git object size limit
-headingGroupOptions = Group Options
-isVisibleToAll = Make group visible to all registered users.
-buttonSaveGroupOptions = Save Group Options
-suggestedGroupLabel = group
-headingParentProjectName = Rights Inherit From
-parentSuggestions = Parent Suggestion
-columnProjectName = Project Name
-enableReviewerByEmail = Enable adding unregistered users as reviewers and CCs on changes
-matchAuthorToCommitterDate = Match authored date with committer date upon submit
-
-headingGroupUUID = Group UUID
-headingOwner = Owners
-headingDescription = Description
-headingProjectOptions = Project Options
-headingProjectCommands = Project Commands
-headingCommands = Commands
-headingMembers = Members
-headingIncludedGroups = Included Groups
-noMembersInfo = Group Members can only be viewed for Gerrit internal groups. For external groups and Gerrit system groups the members cannot be displayed.
-headingExternalGroup = Selected External Group
-headingCreateGroup = Create New Group
-headingAgreements = Contributor Agreements
-headingAuditLog = Audit Log
-
-headingProjectSubmitType = Submit Type
-projectSubmitType_INHERIT = Inherit
-projectSubmitType_FAST_FORWARD_ONLY = Fast Forward Only
-projectSubmitType_MERGE_IF_NECESSARY = Merge if Necessary
-projectSubmitType_REBASE_ALWAYS = Rebase Always
-projectSubmitType_REBASE_IF_NECESSARY = Rebase if Necessary
-projectSubmitType_MERGE_ALWAYS = Always Merge
-projectSubmitType_CHERRY_PICK = Cherry Pick
-
-headingProjectState = State
-projectState_ACTIVE = Active
-projectState_READ_ONLY = Read Only
-projectState_HIDDEN = Hidden
-
-columnMember = Member
-columnEmailAddress = Email Address
-columnGroupName = Group Name
-columnGroupDescription = Description
-columnGroupType = Group Type
-columnGroupNotifications = Email Only Authors
-columnGroupVisibleToAll = Visible To All
-
-columnDate = Date
-columnType = Type
-columnByUser = By User
-
-typeAdded = Added
-typeRemoved = Removed
-
-columnBranchName = Branch Name
-columnBranchRevision = Revision
-columnTagName = Tag Name
-columnTagRevision = Revision
-columnTagAnnotation = Annotation
-initialRevision = Initial Revision
-revision = Revision
-buttonAddBranch = Create Branch
-buttonAddTag = Create Tag
-buttonDeleteBranch = Delete
-buttonDeleteTag = Delete
-saveHeadButton = Save
-cancelHeadButton = Cancel
-
-groupItemHelp = group
-
-groupListTitle = Groups
-groupFilter = Filter
-createGroupTitle = Create Group
-groupTabGeneral = General
-groupTabMembers = Members
-groupTabAuditLog = Audit Log
-projectListTitle = Projects
-projectFilter = Filter
-createProjectTitle = Create Project
-projectListQueryLink = Search for changes on this project
-
-plugins = Plugins
-pluginEnabled = Enabled
-pluginDisabled = Disabled
-pluginSettingsToolTip = Plugin Settings
-columnPluginName = Plugin Name
-columnPluginSettings = Settings
-columnPluginVersion = Version
-columnPluginStatus = Status
-
-noGroupSelected = (No group selected)
-errorNoMatchingGroups = No Matching Groups
-errorNoGitRepository = No Git Repository
-
-pagedListPrev = &#x21e6;Prev
-pagedListNext = Next&#x21e8;
-
-addPermission = Add Permission ...
-
-# Permission Names
-permissionNames = \
-	abandon, \
-	addPatchSet, \
-	create, \
-	createTag, \
-	createSignedTag, \
-	delete, \
-	deleteChanges, \
-	deleteOwnChanges, \
-	editAssignee, \
-	editHashtags, \
-	editTopicName, \
-	forgeAuthor, \
-	forgeCommitter, \
-	forgeServerAsCommitter, \
-	owner, \
-	push, \
-	pushMerge, \
-	read, \
-	rebase, \
-	removeReviewer, \
-	submit, \
-	submitAs, \
-	viewPrivateChanges
-
-abandon = Abandon
-addPatchSet = Add Patch Set
-create = Create Reference
-createTag = Create Annotated Tag
-createSignedTag = Create Signed Tag
-delete = Delete Reference
-deleteChanges = Delete Changes
-deleteOwnChanges = Delete Own Changes
-editAssignee = Edit Assignee
-editHashtags = Edit Hashtags
-editTopicName = Edit Topic Name
-forgeAuthor = Forge Author Identity
-forgeCommitter = Forge Committer Identity
-forgeServerAsCommitter = Forge Server Identity
-owner = Owner
-push = Push
-pushMerge = Push Merge Commit
-read = Read
-rebase = Rebase
-removeReviewer = Remove Reviewer
-submit = Submit
-submitAs = Submit (On Behalf Of)
-viewPrivateChanges = View Private Changes
-
-refErrorEmpty = Reference must be supplied
-refErrorBeginSlash = Reference must not start with '/'
-refErrorDoubleSlash = References cannot contain '//'
-refErrorNoSpace = References cannot contain spaces
-refErrorPrintable = References may contain only printable characters
-errorsMustBeFixed = Errors must be fixed before committing changes.
-
-# Section Names
-sectionTypeReference = Reference:
-sectionTypeSection = Section:
-sectionNames = \
-  GLOBAL_CAPABILITIES
-GLOBAL_CAPABILITIES = Global Capabilities
-
-buttonCreate = Create
-buttonCreateDescription = Insert the description of the change.
-buttonCreateChange = Create Change
-buttonCreateChangeDescription = Create change directly in the browser.
-buttonEditConfig = Edit Config
-buttonEditConfigDescription = Creates a change to edit the project configuration in the browser.
-editConfigMessage = Edit Project Config
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminCss.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminCss.java
deleted file mode 100644
index 53b2e72..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminCss.java
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (C) 2011 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import com.google.gwt.resources.client.CssResource;
-
-public interface AdminCss extends CssResource {
-  String deleteIcon();
-
-  String undoIcon();
-
-  String deleted();
-
-  String deletedBorder();
-
-  String deleteSectionHover();
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.java
deleted file mode 100644
index 7b18a39..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.java
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.i18n.client.Messages;
-
-public interface AdminMessages extends Messages {
-  AdminMessages I = GWT.create(AdminMessages.class);
-
-  String group(String name);
-
-  String label(String name);
-
-  String labelAs(String name);
-
-  String project(String name);
-
-  String deletedGroup(int id);
-
-  String deletedReference(String name);
-
-  String deletedSection(String name);
-
-  String effectiveMaxObjectSizeLimit(String effectiveMaxObjectSizeLimit);
-
-  String noMaxObjectSizeLimit();
-
-  String pluginProjectOptionsTitle(String pluginName);
-
-  String pluginProjectInheritedValue(String value);
-
-  String pluginProjectInheritedListValue(String value);
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.properties
deleted file mode 100644
index c9aa987..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.properties
+++ /dev/null
@@ -1,13 +0,0 @@
-group = Group {0}
-label = Label {0}
-labelAs = Label {0} (On Behalf Of)
-project = Project {0}
-deletedGroup = Deleted Group {0}
-deletedReference = Reference {0} was deleted
-deletedSection = Section {0} was deleted
-effectiveMaxObjectSizeLimit = effective: {0} bytes
-noMaxObjectSizeLimit = No max object size limit is set.
-pluginProjectOptionsTitle = {0} Plugin Options
-pluginProjectOptionsTitle = {0} Plugin
-pluginProjectInheritedValue = inherited: {0}
-pluginProjectInheritedListValue = INHERIT ({0})
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminResources.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminResources.java
deleted file mode 100644
index dfbfbb6..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminResources.java
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (C) 2011 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.resources.client.ClientBundle;
-import com.google.gwt.resources.client.ImageResource;
-
-public interface AdminResources extends ClientBundle {
-  AdminResources I = GWT.create(AdminResources.class);
-
-  @Source("admin.css")
-  AdminCss css();
-
-  /** unknown origin TODO replace icons */
-  @Source("deleteNormal.png")
-  ImageResource deleteNormal();
-
-  @Source("deleteHover.png")
-  ImageResource deleteHover();
-
-  /** silk icons (CC-BY3.0): http://famfamfam.com/lab/icons/silk/ */
-  @Source("arrow_undo.png")
-  ImageResource undoNormal();
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/CreateChangeAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/CreateChangeAction.java
deleted file mode 100644
index 611db85..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/CreateChangeAction.java
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.ui.CreateChangeDialog;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.PopupPanel;
-
-class CreateChangeAction {
-  static void call(Button b, String project) {
-    // TODO Replace CreateChangeDialog with a nicer looking display.
-    b.setEnabled(false);
-    new CreateChangeDialog(new Project.NameKey(project)) {
-      {
-        sendButton.setText(AdminConstants.I.buttonCreate());
-        message.setText(AdminConstants.I.buttonCreateDescription());
-      }
-
-      @Override
-      public void onSend() {
-        ChangeApi.createChange(
-            project,
-            getDestinationBranch(),
-            getDestinationTopic(),
-            message.getText(),
-            null,
-            new GerritCallback<ChangeInfo>() {
-              @Override
-              public void onSuccess(ChangeInfo result) {
-                sent = true;
-                hide();
-                Gerrit.display(PageLinks.toChange(result.projectNameKey(), result.legacyId()));
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {
-                enableButtons(true);
-                super.onFailure(caught);
-              }
-            });
-      }
-
-      @Override
-      public void onClose(CloseEvent<PopupPanel> event) {
-        super.onClose(event);
-        b.setEnabled(true);
-      }
-    }.center();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/CreateGroupScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/CreateGroupScreen.java
deleted file mode 100644
index 6914ee9..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/CreateGroupScreen.java
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import static com.google.gerrit.common.data.GlobalCapability.CREATE_GROUP;
-
-import com.google.gerrit.client.Dispatcher;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.NotFoundScreen;
-import com.google.gerrit.client.account.AccountCapabilities;
-import com.google.gerrit.client.groups.GroupApi;
-import com.google.gerrit.client.info.GroupInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.ui.OnEditEnabler;
-import com.google.gerrit.client.ui.Screen;
-import com.google.gerrit.client.ui.SmallHeading;
-import com.google.gerrit.common.PageLinks;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.History;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwtexpui.globalkey.client.NpTextBox;
-
-public class CreateGroupScreen extends Screen {
-
-  private NpTextBox addTxt;
-  private Button addNew;
-
-  public CreateGroupScreen() {
-    super();
-    setRequiresSignIn(true);
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    AccountCapabilities.all(
-        new GerritCallback<AccountCapabilities>() {
-          @Override
-          public void onSuccess(AccountCapabilities ac) {
-            if (ac.canPerform(CREATE_GROUP)) {
-              display();
-            } else {
-              Gerrit.display(PageLinks.ADMIN_CREATE_GROUP, new NotFoundScreen());
-            }
-          }
-        },
-        CREATE_GROUP);
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    setPageTitle(AdminConstants.I.createGroupTitle());
-    addCreateGroupPanel();
-  }
-
-  @Override
-  public void onShowView() {
-    super.onShowView();
-    if (addTxt != null) {
-      addTxt.setFocus(true);
-    }
-  }
-
-  private void addCreateGroupPanel() {
-    VerticalPanel addPanel = new VerticalPanel();
-    addPanel.setStyleName(Gerrit.RESOURCES.css().addSshKeyPanel());
-    addPanel.add(new SmallHeading(AdminConstants.I.headingCreateGroup()));
-
-    addTxt =
-        new NpTextBox() {
-          @Override
-          public void onBrowserEvent(Event event) {
-            super.onBrowserEvent(event);
-            if (event.getTypeInt() == Event.ONPASTE) {
-              Scheduler.get()
-                  .scheduleDeferred(
-                      new ScheduledCommand() {
-                        @Override
-                        public void execute() {
-                          if (addTxt.getValue().trim().length() != 0) {
-                            addNew.setEnabled(true);
-                          }
-                        }
-                      });
-            }
-          }
-        };
-    addTxt.sinkEvents(Event.ONPASTE);
-
-    addTxt.setVisibleLength(60);
-    addTxt.addKeyPressHandler(
-        new KeyPressHandler() {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
-              doCreateGroup();
-            }
-          }
-        });
-    addPanel.add(addTxt);
-
-    addNew = new Button(AdminConstants.I.buttonCreateGroup());
-    addNew.setEnabled(false);
-    addNew.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            doCreateGroup();
-          }
-        });
-    addPanel.add(addNew);
-    add(addPanel);
-
-    new OnEditEnabler(addNew, addTxt);
-  }
-
-  private void doCreateGroup() {
-    final String newName = addTxt.getText();
-    if (newName == null || newName.length() == 0) {
-      return;
-    }
-
-    addNew.setEnabled(false);
-    GroupApi.createGroup(
-        newName,
-        new GerritCallback<GroupInfo>() {
-          @Override
-          public void onSuccess(GroupInfo result) {
-            History.newItem(Dispatcher.toGroup(result.getGroupId(), AccountGroupScreen.MEMBERS));
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            super.onFailure(caught);
-            addNew.setEnabled(true);
-          }
-        });
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/CreateProjectScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/CreateProjectScreen.java
deleted file mode 100644
index 02b9169..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/CreateProjectScreen.java
+++ /dev/null
@@ -1,306 +0,0 @@
-// Copyright (C) 2011 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import static com.google.gerrit.common.data.GlobalCapability.CREATE_PROJECT;
-
-import com.google.gerrit.client.Dispatcher;
-import com.google.gerrit.client.ErrorDialog;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.NotFoundScreen;
-import com.google.gerrit.client.VoidResult;
-import com.google.gerrit.client.account.AccountCapabilities;
-import com.google.gerrit.client.projects.ProjectApi;
-import com.google.gerrit.client.projects.ProjectInfo;
-import com.google.gerrit.client.projects.ProjectMap;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.ui.OnEditEnabler;
-import com.google.gerrit.client.ui.ProjectListPopup;
-import com.google.gerrit.client.ui.ProjectNameSuggestOracle;
-import com.google.gerrit.client.ui.ProjectsTable;
-import com.google.gerrit.client.ui.RemoteSuggestBox;
-import com.google.gerrit.client.ui.Screen;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.common.ProjectUtil;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.History;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwtexpui.globalkey.client.NpTextBox;
-
-public class CreateProjectScreen extends Screen {
-  private Grid grid;
-  private NpTextBox project;
-  private Button create;
-  private Button browse;
-  private RemoteSuggestBox parent;
-  private CheckBox emptyCommit;
-  private CheckBox permissionsOnly;
-  private ProjectsTable suggestedParentsTab;
-  private ProjectListPopup projectsPopup;
-
-  public CreateProjectScreen() {
-    super();
-    setRequiresSignIn(true);
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    AccountCapabilities.all(
-        new GerritCallback<AccountCapabilities>() {
-          @Override
-          public void onSuccess(AccountCapabilities ac) {
-            if (ac.canPerform(CREATE_PROJECT)) {
-              display();
-            } else {
-              Gerrit.display(PageLinks.ADMIN_CREATE_PROJECT, new NotFoundScreen());
-            }
-          }
-        },
-        CREATE_PROJECT);
-  }
-
-  @Override
-  protected void onUnload() {
-    super.onUnload();
-    projectsPopup.closePopup();
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    setPageTitle(AdminConstants.I.createProjectTitle());
-    addCreateProjectPanel();
-
-    /* popup */
-    projectsPopup =
-        new ProjectListPopup() {
-          @Override
-          protected void onMovePointerTo(String projectName) {
-            // prevent user input from being overwritten by simply poping up
-            if (!projectsPopup.isPoppingUp() || "".equals(parent.getText())) {
-              parent.setText(projectName);
-            }
-          }
-        };
-    projectsPopup.initPopup(AdminConstants.I.projects(), PageLinks.ADMIN_PROJECTS);
-  }
-
-  @Override
-  public void onShowView() {
-    super.onShowView();
-    if (project != null) {
-      project.setFocus(true);
-    }
-  }
-
-  private void addCreateProjectPanel() {
-    final VerticalPanel fp = new VerticalPanel();
-    fp.setStyleName(Gerrit.RESOURCES.css().createProjectPanel());
-
-    initCreateButton();
-    initCreateTxt();
-    initParentBox();
-
-    addGrid(fp);
-
-    emptyCommit = new CheckBox(AdminConstants.I.checkBoxEmptyCommit());
-    emptyCommit.setValue(true);
-    permissionsOnly = new CheckBox(AdminConstants.I.checkBoxPermissionsOnly());
-    fp.add(emptyCommit);
-    fp.add(permissionsOnly);
-    fp.add(create);
-    VerticalPanel vp = new VerticalPanel();
-    vp.add(fp);
-    initSuggestedParents();
-    vp.add(suggestedParentsTab);
-    add(vp);
-  }
-
-  private void initCreateTxt() {
-    project =
-        new NpTextBox() {
-          @Override
-          public void onBrowserEvent(Event event) {
-            super.onBrowserEvent(event);
-            if (event.getTypeInt() == Event.ONPASTE) {
-              Scheduler.get()
-                  .scheduleDeferred(
-                      new ScheduledCommand() {
-                        @Override
-                        public void execute() {
-                          if (project.getValue().trim().length() != 0) {
-                            create.setEnabled(true);
-                          }
-                        }
-                      });
-            }
-          }
-        };
-    project.sinkEvents(Event.ONPASTE);
-    project.setVisibleLength(50);
-    project.addKeyPressHandler(
-        new KeyPressHandler() {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
-              doCreateProject();
-            }
-          }
-        });
-    new OnEditEnabler(create, project);
-  }
-
-  private void initCreateButton() {
-    create = new Button(AdminConstants.I.buttonCreateProject());
-    create.setEnabled(false);
-    create.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            doCreateProject();
-          }
-        });
-
-    browse = new Button(AdminConstants.I.buttonBrowseProjects());
-    browse.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            int top = grid.getAbsoluteTop() - 50; // under page header
-            // Try to place it to the right of everything else, but not
-            // right justified
-            int left =
-                5
-                    + Math.max(
-                        grid.getAbsoluteLeft() + grid.getOffsetWidth(),
-                        suggestedParentsTab.getAbsoluteLeft()
-                            + suggestedParentsTab.getOffsetWidth());
-            projectsPopup.setPreferredCoordinates(top, left);
-            projectsPopup.displayPopup();
-          }
-        });
-  }
-
-  private void initParentBox() {
-    parent = new RemoteSuggestBox(new ProjectNameSuggestOracle());
-    parent.setVisibleLength(50);
-  }
-
-  private void initSuggestedParents() {
-    suggestedParentsTab =
-        new ProjectsTable() {
-          {
-            table.setText(0, 1, AdminConstants.I.parentSuggestions());
-          }
-
-          @Override
-          protected void populate(int row, ProjectInfo k) {
-            populateState(row, k);
-            final Anchor projectLink = new Anchor(k.name());
-            projectLink.addClickHandler(
-                new ClickHandler() {
-
-                  @Override
-                  public void onClick(ClickEvent event) {
-                    parent.setText(getRowItem(row).name());
-                  }
-                });
-
-            table.setWidget(row, ProjectsTable.C_NAME, projectLink);
-            table.setText(row, ProjectsTable.C_DESCRIPTION, k.description());
-
-            setRowItem(row, k);
-          }
-        };
-    suggestedParentsTab.setVisible(false);
-
-    ProjectMap.parentCandidates(
-        new GerritCallback<ProjectMap>() {
-          @Override
-          public void onSuccess(ProjectMap list) {
-            if (!list.isEmpty()) {
-              suggestedParentsTab.setVisible(true);
-              suggestedParentsTab.display(list);
-              suggestedParentsTab.finishDisplay();
-            }
-          }
-        });
-  }
-
-  private void addGrid(VerticalPanel fp) {
-    grid = new Grid(2, 3);
-    grid.setStyleName(Gerrit.RESOURCES.css().infoBlock());
-    grid.setText(0, 0, AdminConstants.I.columnProjectName() + ":");
-    grid.setWidget(0, 1, project);
-    grid.setText(1, 0, AdminConstants.I.headingParentProjectName() + ":");
-    grid.setWidget(1, 1, parent);
-    grid.setWidget(1, 2, browse);
-    fp.add(grid);
-  }
-
-  private void doCreateProject() {
-    final String projectName = project.getText().trim();
-    final String parentName = parent.getText().trim();
-
-    if ("".equals(projectName)) {
-      project.setFocus(true);
-      return;
-    }
-
-    enableForm(false);
-    ProjectApi.createProject(
-        projectName,
-        parentName,
-        emptyCommit.getValue(),
-        permissionsOnly.getValue(),
-        new AsyncCallback<VoidResult>() {
-          @Override
-          public void onSuccess(VoidResult result) {
-            String nameWithoutSuffix = ProjectUtil.stripGitSuffix(projectName);
-            History.newItem(
-                Dispatcher.toProjectAdmin(
-                    new Project.NameKey(nameWithoutSuffix), ProjectScreen.INFO));
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            new ErrorDialog(caught.getMessage()).center();
-            enableForm(true);
-          }
-        });
-  }
-
-  private void enableForm(boolean enabled) {
-    project.setEnabled(enabled);
-    create.setEnabled(enabled);
-    parent.setEnabled(enabled);
-    emptyCommit.setEnabled(enabled);
-    permissionsOnly.setEnabled(enabled);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/EditConfigAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/EditConfigAction.java
deleted file mode 100644
index cb2ca0f..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/EditConfigAction.java
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import com.google.gerrit.client.Dispatcher;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gwt.user.client.ui.Button;
-
-public class EditConfigAction {
-
-  static void call(Button b, Project.NameKey project) {
-    b.setEnabled(false);
-
-    ChangeApi.createChange(
-        project.get(),
-        RefNames.REFS_CONFIG,
-        null,
-        AdminConstants.I.editConfigMessage(),
-        null,
-        new GerritCallback<ChangeInfo>() {
-          @Override
-          public void onSuccess(ChangeInfo result) {
-            Gerrit.display(
-                Dispatcher.toEditScreen(
-                    project, new PatchSet.Id(result.legacyId(), 1), "project.config"));
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            b.setEnabled(true);
-            super.onFailure(caught);
-          }
-        });
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupListScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupListScreen.java
deleted file mode 100644
index b37a680..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupListScreen.java
+++ /dev/null
@@ -1,232 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import static com.google.gerrit.common.PageLinks.ADMIN_GROUPS;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.groups.GroupMap;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.ui.Hyperlink;
-import com.google.gerrit.client.ui.PagingHyperlink;
-import com.google.gerrit.client.ui.Screen;
-import com.google.gerrit.common.PageLinks;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyUpEvent;
-import com.google.gwt.event.dom.client.KeyUpHandler;
-import com.google.gwt.http.client.URL;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwtexpui.globalkey.client.NpTextBox;
-
-public class GroupListScreen extends Screen {
-  private Hyperlink prev;
-  private Hyperlink next;
-  private GroupTable groups;
-  private NpTextBox filterTxt;
-  private int pageSize;
-
-  private String match = "";
-  private int start;
-  private Query query;
-
-  public GroupListScreen() {
-    setRequiresSignIn(true);
-    pageSize = Gerrit.getUserPreferences().changesPerPage();
-  }
-
-  public GroupListScreen(String params) {
-    this();
-    for (String kvPair : params.split("[,;&]")) {
-      String[] kv = kvPair.split("=", 2);
-      if (kv.length != 2 || kv[0].isEmpty()) {
-        continue;
-      }
-
-      if ("filter".equals(kv[0])) {
-        match = URL.decodeQueryString(kv[1]);
-      }
-
-      if ("skip".equals(kv[0]) && URL.decodeQueryString(kv[1]).matches("^[\\d]+")) {
-        start = Integer.parseInt(URL.decodeQueryString(kv[1]));
-      }
-    }
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    query = new Query(match).start(start).run();
-  }
-
-  private void setupNavigationLink(Hyperlink link, String filter, int skip) {
-    link.setTargetHistoryToken(getTokenForScreen(filter, skip));
-    link.setVisible(true);
-  }
-
-  private String getTokenForScreen(String filter, int skip) {
-    String token = ADMIN_GROUPS;
-    if (filter != null && !filter.isEmpty()) {
-      token += "?filter=" + URL.encodeQueryString(filter);
-    }
-    if (skip > 0) {
-      if (token.contains("?filter=")) {
-        token += ",";
-      } else {
-        token += "?";
-      }
-      token += "skip=" + skip;
-    }
-    return token;
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    setPageTitle(AdminConstants.I.groupListTitle());
-    initPageHeader();
-
-    prev = PagingHyperlink.createPrev();
-    prev.setVisible(false);
-
-    next = PagingHyperlink.createNext();
-    next.setVisible(false);
-
-    groups = new GroupTable(PageLinks.ADMIN_GROUPS);
-    add(groups);
-
-    final HorizontalPanel buttons = new HorizontalPanel();
-    buttons.setStyleName(Gerrit.RESOURCES.css().changeTablePrevNextLinks());
-    buttons.add(prev);
-    buttons.add(next);
-    add(buttons);
-  }
-
-  private void initPageHeader() {
-    final HorizontalPanel hp = new HorizontalPanel();
-    hp.setStyleName(Gerrit.RESOURCES.css().projectFilterPanel());
-    final Label filterLabel = new Label(AdminConstants.I.projectFilter());
-    filterLabel.setStyleName(Gerrit.RESOURCES.css().projectFilterLabel());
-    hp.add(filterLabel);
-    filterTxt = new NpTextBox();
-    filterTxt.setValue(match);
-    filterTxt.addKeyUpHandler(
-        new KeyUpHandler() {
-          @Override
-          public void onKeyUp(KeyUpEvent event) {
-            Query q =
-                new Query(filterTxt.getValue())
-                    .open(event.getNativeKeyCode() == KeyCodes.KEY_ENTER);
-            if (match.equals(q.qMatch)) {
-              q.start(start);
-            }
-            if (q.open || !match.equals(q.qMatch)) {
-              if (query == null) {
-                q.run();
-              }
-              query = q;
-            }
-          }
-        });
-    hp.add(filterTxt);
-    add(hp);
-  }
-
-  @Override
-  public void onShowView() {
-    super.onShowView();
-    if (match != null) {
-      filterTxt.setCursorPos(match.length());
-    }
-    filterTxt.setFocus(true);
-  }
-
-  @Override
-  public void registerKeys() {
-    super.registerKeys();
-    groups.setRegisterKeys(true);
-  }
-
-  private class Query {
-    private final String qMatch;
-    private int qStart;
-    private boolean open;
-
-    Query(String match) {
-      this.qMatch = match;
-    }
-
-    Query start(int start) {
-      this.qStart = start;
-      return this;
-    }
-
-    Query open(boolean open) {
-      this.open = open;
-      return this;
-    }
-
-    Query run() {
-      int limit = open ? 1 : pageSize + 1;
-      GroupMap.match(
-          qMatch,
-          limit,
-          qStart,
-          new GerritCallback<GroupMap>() {
-            @Override
-            public void onSuccess(GroupMap result) {
-              if (!isAttached()) {
-                // View has been disposed.
-              } else if (query == Query.this) {
-                query = null;
-                showMap(result);
-              } else {
-                query.run();
-              }
-            }
-          });
-      return this;
-    }
-
-    private void showMap(GroupMap result) {
-      if (open && !result.isEmpty()) {
-        Gerrit.display(PageLinks.toGroup(result.values().get(0).getGroupUUID()));
-        return;
-      }
-
-      setToken(getTokenForScreen(qMatch, qStart));
-      GroupListScreen.this.match = qMatch;
-      GroupListScreen.this.start = qStart;
-
-      if (result.size() <= pageSize) {
-        groups.display(result, qMatch);
-        next.setVisible(false);
-      } else {
-        groups.displaySubset(result, 0, result.size() - 1, qMatch);
-        setupNavigationLink(next, qMatch, qStart + pageSize);
-      }
-
-      if (qStart > 0) {
-        setupNavigationLink(prev, qMatch, qStart - pageSize);
-      } else {
-        prev.setVisible(false);
-      }
-
-      if (!isCurrentView()) {
-        display();
-      }
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupReferenceBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupReferenceBox.java
deleted file mode 100644
index db138a9..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupReferenceBox.java
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright (C) 2011 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import com.google.gerrit.client.ui.AccountGroupSuggestOracle;
-import com.google.gerrit.client.ui.RemoteSuggestBox;
-import com.google.gerrit.common.data.GroupReference;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.editor.client.LeafValueEditor;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.event.logical.shared.HasCloseHandlers;
-import com.google.gwt.event.logical.shared.HasSelectionHandlers;
-import com.google.gwt.event.logical.shared.SelectionEvent;
-import com.google.gwt.event.logical.shared.SelectionHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.Focusable;
-
-public class GroupReferenceBox extends Composite
-    implements LeafValueEditor<GroupReference>,
-        HasSelectionHandlers<GroupReference>,
-        HasCloseHandlers<GroupReferenceBox>,
-        Focusable {
-  private final AccountGroupSuggestOracle oracle;
-  private final RemoteSuggestBox suggestBox;
-
-  public GroupReferenceBox() {
-    oracle = new AccountGroupSuggestOracle();
-    suggestBox = new RemoteSuggestBox(oracle);
-    initWidget(suggestBox);
-
-    suggestBox.addSelectionHandler(
-        new SelectionHandler<String>() {
-          @Override
-          public void onSelection(SelectionEvent<String> event) {
-            SelectionEvent.fire(GroupReferenceBox.this, toValue(event.getSelectedItem()));
-          }
-        });
-    suggestBox.addCloseHandler(
-        new CloseHandler<RemoteSuggestBox>() {
-          @Override
-          public void onClose(CloseEvent<RemoteSuggestBox> event) {
-            suggestBox.setText("");
-            CloseEvent.fire(GroupReferenceBox.this, GroupReferenceBox.this);
-          }
-        });
-  }
-
-  public void setVisibleLength(int len) {
-    suggestBox.setVisibleLength(len);
-  }
-
-  @Override
-  public HandlerRegistration addSelectionHandler(SelectionHandler<GroupReference> handler) {
-    return addHandler(handler, SelectionEvent.getType());
-  }
-
-  @Override
-  public HandlerRegistration addCloseHandler(CloseHandler<GroupReferenceBox> handler) {
-    return addHandler(handler, CloseEvent.getType());
-  }
-
-  @Override
-  public GroupReference getValue() {
-    return toValue(suggestBox.getText());
-  }
-
-  private GroupReference toValue(String name) {
-    if (name != null && !name.isEmpty()) {
-      return new GroupReference(oracle.getUUID(name), name);
-    }
-    return null;
-  }
-
-  @Override
-  public void setValue(GroupReference value) {
-    suggestBox.setText(value != null ? value.getName() : "");
-  }
-
-  @Override
-  public int getTabIndex() {
-    return suggestBox.getTabIndex();
-  }
-
-  @Override
-  public void setTabIndex(int index) {
-    suggestBox.setTabIndex(index);
-  }
-
-  @Override
-  public void setFocus(boolean focused) {
-    suggestBox.setFocus(focused);
-  }
-
-  @Override
-  public void setAccessKey(char key) {
-    suggestBox.setAccessKey(key);
-  }
-
-  public void setProject(Project.NameKey projectName) {
-    oracle.setProject(projectName);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupTable.java
deleted file mode 100644
index be0db41..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupTable.java
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import static java.util.Comparator.comparing;
-
-import com.google.gerrit.client.Dispatcher;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.groups.GroupList;
-import com.google.gerrit.client.groups.GroupMap;
-import com.google.gerrit.client.info.GroupInfo;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.HighlightingInlineHyperlink;
-import com.google.gerrit.client.ui.NavigationTable;
-import com.google.gerrit.client.ui.Util;
-import com.google.gerrit.common.PageLinks;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.user.client.History;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
-import com.google.gwt.user.client.ui.HTMLTable.Cell;
-import com.google.gwt.user.client.ui.Image;
-import java.util.List;
-
-public class GroupTable extends NavigationTable<GroupInfo> {
-  private static final int NUM_COLS = 3;
-
-  public GroupTable() {
-    this(null);
-  }
-
-  public GroupTable(String pointerId) {
-    super(AdminConstants.I.groupItemHelp());
-    setSavePointerId(pointerId);
-
-    table.setText(0, 1, AdminConstants.I.columnGroupName());
-    table.setText(0, 2, AdminConstants.I.columnGroupDescription());
-    table.setText(0, 3, AdminConstants.I.columnGroupVisibleToAll());
-    table.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            final Cell cell = table.getCellForEvent(event);
-            if (cell != null
-                && cell.getCellIndex() != 1
-                && getRowItem(cell.getRowIndex()) != null) {
-              movePointerTo(cell.getRowIndex());
-            }
-          }
-        });
-
-    final FlexCellFormatter fmt = table.getFlexCellFormatter();
-    for (int i = 1; i <= NUM_COLS; i++) {
-      fmt.addStyleName(0, i, Gerrit.RESOURCES.css().dataHeader());
-    }
-  }
-
-  @Override
-  protected Object getRowItemKey(GroupInfo item) {
-    return item.getGroupId();
-  }
-
-  @Override
-  protected void onOpenRow(int row) {
-    GroupInfo groupInfo = getRowItem(row);
-    if (isInteralGroup(groupInfo)) {
-      History.newItem(Dispatcher.toGroup(groupInfo.getGroupId()));
-    } else if (groupInfo.url() != null) {
-      Window.open(groupInfo.url(), "_self", null);
-    }
-  }
-
-  public void display(GroupMap groups, String toHighlight) {
-    display(Natives.asList(groups.values()), toHighlight);
-  }
-
-  public void display(GroupList groups) {
-    display(Natives.asList(groups), null);
-  }
-
-  public void display(List<GroupInfo> list, String toHighlight) {
-    displaySubset(list, toHighlight, 0, list.size());
-  }
-
-  public void displaySubset(GroupMap groups, int fromIndex, int toIndex, String toHighlight) {
-    displaySubset(Natives.asList(groups.values()), toHighlight, fromIndex, toIndex);
-  }
-
-  public void displaySubset(List<GroupInfo> list, String toHighlight, int fromIndex, int toIndex) {
-    while (1 < table.getRowCount()) {
-      table.removeRow(table.getRowCount() - 1);
-    }
-
-    list.sort(comparing(GroupInfo::name));
-    for (GroupInfo group : list.subList(fromIndex, toIndex)) {
-      final int row = table.getRowCount();
-      table.insertRow(row);
-      applyDataRowStyle(row);
-      populate(row, group, toHighlight);
-    }
-  }
-
-  void populate(int row, GroupInfo k, String toHighlight) {
-    if (k.url() != null) {
-      if (isInteralGroup(k)) {
-        table.setWidget(
-            row,
-            1,
-            new HighlightingInlineHyperlink(
-                k.name(), Dispatcher.toGroup(k.getGroupId()), toHighlight));
-      } else {
-        Anchor link = new Anchor();
-        link.setHTML(Util.highlight(k.name(), toHighlight));
-        link.setHref(k.url());
-        table.setWidget(row, 1, link);
-      }
-    } else {
-      table.setHTML(row, 1, Util.highlight(k.name(), toHighlight));
-    }
-    table.setText(row, 2, k.description());
-    if (k.options().isVisibleToAll()) {
-      table.setWidget(row, 3, new Image(Gerrit.RESOURCES.greenCheck()));
-    }
-
-    final FlexCellFormatter fmt = table.getFlexCellFormatter();
-    fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().groupName());
-    for (int i = 1; i <= NUM_COLS; i++) {
-      fmt.addStyleName(row, i, Gerrit.RESOURCES.css().dataCell());
-    }
-
-    setRowItem(row, k);
-  }
-
-  private boolean isInteralGroup(GroupInfo groupInfo) {
-    return groupInfo != null && groupInfo.url().startsWith("#" + PageLinks.ADMIN_GROUPS);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PaginatedProjectScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PaginatedProjectScreen.java
deleted file mode 100644
index 75c3cb6..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PaginatedProjectScreen.java
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.ui.Hyperlink;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.http.client.URL;
-
-abstract class PaginatedProjectScreen extends ProjectScreen {
-  protected int pageSize;
-  protected String match = "";
-  protected int start;
-
-  PaginatedProjectScreen(Project.NameKey toShow) {
-    super(toShow);
-    pageSize = Gerrit.getUserPreferences().changesPerPage();
-  }
-
-  protected void parseToken(String token) {
-    for (String kvPair : token.split("[,;&/?]")) {
-      String[] kv = kvPair.split("=", 2);
-      if (kv.length != 2 || kv[0].isEmpty()) {
-        continue;
-      }
-
-      if ("filter".equals(kv[0])) {
-        match = URL.decodeQueryString(kv[1]);
-      }
-
-      if ("skip".equals(kv[0]) && URL.decodeQueryString(kv[1]).matches("^[\\d]+")) {
-        start = Integer.parseInt(URL.decodeQueryString(kv[1]));
-      }
-    }
-  }
-
-  protected void parseToken() {
-    parseToken(getToken());
-  }
-
-  protected String getTokenForScreen(String filter, int skip) {
-    String token = getScreenToken();
-    if (filter != null && !filter.isEmpty()) {
-      token += "?filter=" + URL.encodeQueryString(filter);
-    }
-    if (skip > 0) {
-      if (token.contains("?filter=")) {
-        token += ",";
-      } else {
-        token += "?";
-      }
-      token += "skip=" + skip;
-    }
-    return token;
-  }
-
-  protected abstract String getScreenToken();
-
-  protected void setupNavigationLink(Hyperlink link, String filter, int skip) {
-    link.setTargetHistoryToken(getTokenForScreen(filter, skip));
-    link.setVisible(true);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionEditor.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionEditor.java
deleted file mode 100644
index 39dadcc..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionEditor.java
+++ /dev/null
@@ -1,329 +0,0 @@
-// Copyright (C) 2011 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import com.google.gerrit.client.ErrorDialog;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.groups.GroupMap;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.common.data.AccessSection;
-import com.google.gerrit.common.data.GlobalCapability;
-import com.google.gerrit.common.data.GroupInfo;
-import com.google.gerrit.common.data.GroupReference;
-import com.google.gerrit.common.data.LabelType;
-import com.google.gerrit.common.data.LabelTypes;
-import com.google.gerrit.common.data.Permission;
-import com.google.gerrit.common.data.PermissionRange;
-import com.google.gerrit.common.data.PermissionRule;
-import com.google.gerrit.common.data.ProjectAccess;
-import com.google.gerrit.common.data.RefConfigSection;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;
-import com.google.gwt.dom.client.DivElement;
-import com.google.gwt.dom.client.Style.Display;
-import com.google.gwt.editor.client.Editor;
-import com.google.gwt.editor.client.EditorDelegate;
-import com.google.gwt.editor.client.ValueAwareEditor;
-import com.google.gwt.editor.client.adapters.EditorSource;
-import com.google.gwt.editor.client.adapters.ListEditor;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.MouseOutEvent;
-import com.google.gwt.event.dom.client.MouseOverEvent;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.SelectionEvent;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.ValueLabel;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-public class PermissionEditor extends Composite
-    implements Editor<Permission>, ValueAwareEditor<Permission> {
-  interface Binder extends UiBinder<HTMLPanel, PermissionEditor> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  @UiField(provided = true)
-  @Path("name")
-  ValueLabel<String> normalName;
-
-  @UiField(provided = true)
-  @Path("name")
-  ValueLabel<String> deletedName;
-
-  @UiField CheckBox exclusiveGroup;
-
-  @UiField FlowPanel ruleContainer;
-  ListEditor<PermissionRule, PermissionRuleEditor> rules;
-
-  @UiField DivElement addContainer;
-  @UiField DivElement addStage1;
-  @UiField DivElement addStage2;
-  @UiField Anchor beginAddRule;
-  @UiField @Editor.Ignore GroupReferenceBox groupToAdd;
-  @UiField Button addRule;
-
-  @UiField Anchor deletePermission;
-
-  @UiField DivElement normal;
-  @UiField DivElement deleted;
-
-  private final Project.NameKey projectName;
-  private final Map<AccountGroup.UUID, GroupInfo> groupInfo;
-  private final boolean readOnly;
-  private final AccessSection section;
-  private final LabelTypes labelTypes;
-  private Permission value;
-  private PermissionRange.WithDefaults validRange;
-  private boolean isDeleted;
-
-  public PermissionEditor(
-      ProjectAccess projectAccess, boolean readOnly, AccessSection section, LabelTypes labelTypes) {
-    this.readOnly = readOnly;
-    this.section = section;
-    this.projectName = projectAccess.getProjectName();
-    this.groupInfo = projectAccess.getGroupInfo();
-    this.labelTypes = labelTypes;
-
-    PermissionNameRenderer nameRenderer =
-        new PermissionNameRenderer(projectAccess.getCapabilities());
-    normalName = new ValueLabel<>(nameRenderer);
-    deletedName = new ValueLabel<>(nameRenderer);
-
-    initWidget(uiBinder.createAndBindUi(this));
-    groupToAdd.setProject(projectName);
-    rules = ListEditor.of(new RuleEditorSource());
-
-    exclusiveGroup.setEnabled(!readOnly);
-    exclusiveGroup.setVisible(RefConfigSection.isValid(section.getName()));
-
-    if (readOnly) {
-      addContainer.removeFromParent();
-      addContainer = null;
-
-      deletePermission.removeFromParent();
-      deletePermission = null;
-    }
-  }
-
-  @UiHandler("deletePermission")
-  void onDeleteHover(@SuppressWarnings("unused") MouseOverEvent event) {
-    addStyleName(AdminResources.I.css().deleteSectionHover());
-  }
-
-  @UiHandler("deletePermission")
-  void onDeleteNonHover(@SuppressWarnings("unused") MouseOutEvent event) {
-    removeStyleName(AdminResources.I.css().deleteSectionHover());
-  }
-
-  @UiHandler("deletePermission")
-  void onDeletePermission(@SuppressWarnings("unused") ClickEvent event) {
-    isDeleted = true;
-    normal.getStyle().setDisplay(Display.NONE);
-    deleted.getStyle().setDisplay(Display.BLOCK);
-  }
-
-  @UiHandler("undoDelete")
-  void onUndoDelete(@SuppressWarnings("unused") ClickEvent event) {
-    isDeleted = false;
-    deleted.getStyle().setDisplay(Display.NONE);
-    normal.getStyle().setDisplay(Display.BLOCK);
-  }
-
-  @UiHandler("beginAddRule")
-  void onBeginAddRule(@SuppressWarnings("unused") ClickEvent event) {
-    beginAddRule();
-  }
-
-  void beginAddRule() {
-    addStage1.getStyle().setDisplay(Display.NONE);
-    addStage2.getStyle().setDisplay(Display.BLOCK);
-
-    Scheduler.get()
-        .scheduleDeferred(
-            new ScheduledCommand() {
-              @Override
-              public void execute() {
-                groupToAdd.setFocus(true);
-              }
-            });
-  }
-
-  @UiHandler("addRule")
-  void onAddGroupByClick(@SuppressWarnings("unused") ClickEvent event) {
-    GroupReference ref = groupToAdd.getValue();
-    if (ref != null) {
-      addGroup(ref);
-    } else {
-      groupToAdd.setFocus(true);
-    }
-  }
-
-  @UiHandler("groupToAdd")
-  void onAddGroupByEnter(SelectionEvent<GroupReference> event) {
-    GroupReference ref = event.getSelectedItem();
-    if (ref != null) {
-      addGroup(ref);
-    }
-  }
-
-  @UiHandler("groupToAdd")
-  void onAbortAddGroup(@SuppressWarnings("unused") CloseEvent<GroupReferenceBox> event) {
-    hideAddGroup();
-  }
-
-  @UiHandler("hideAddGroup")
-  void hideAddGroup(@SuppressWarnings("unused") ClickEvent event) {
-    hideAddGroup();
-  }
-
-  private void hideAddGroup() {
-    addStage1.getStyle().setDisplay(Display.BLOCK);
-    addStage2.getStyle().setDisplay(Display.NONE);
-  }
-
-  private void addGroup(GroupReference ref) {
-    if (ref.getUUID() != null) {
-      if (value.getRule(ref) == null) {
-        PermissionRule newRule = value.getRule(ref, true);
-        if (validRange != null) {
-          int min = validRange.getDefaultMin();
-          int max = validRange.getDefaultMax();
-          newRule.setRange(min, max);
-
-        } else if (GlobalCapability.PRIORITY.equals(value.getName())) {
-          newRule.setAction(PermissionRule.Action.BATCH);
-        }
-
-        rules.getList().add(newRule);
-      }
-      groupToAdd.setValue(null);
-      groupToAdd.setFocus(true);
-
-    } else {
-      // If the oracle didn't get to complete a UUID, resolve it now.
-      //
-      addRule.setEnabled(false);
-      GroupMap.suggestAccountGroupForProject(
-          projectName.get(),
-          ref.getName(),
-          1,
-          new GerritCallback<GroupMap>() {
-            @Override
-            public void onSuccess(GroupMap result) {
-              addRule.setEnabled(true);
-              if (result.values().length() == 1) {
-                addGroup(
-                    new GroupReference(
-                        result.values().get(0).getGroupUUID(), result.values().get(0).name()));
-              } else {
-                groupToAdd.setFocus(true);
-                new ErrorDialog(Gerrit.M.noSuchGroupMessage(ref.getName())).center();
-              }
-            }
-
-            @Override
-            public void onFailure(Throwable caught) {
-              addRule.setEnabled(true);
-              super.onFailure(caught);
-            }
-          });
-    }
-  }
-
-  boolean isDeleted() {
-    return isDeleted;
-  }
-
-  @Override
-  public void setValue(Permission value) {
-    this.value = value;
-
-    if (Permission.hasRange(value.getName())) {
-      LabelType lt = labelTypes.byLabel(value.getLabel());
-      if (lt != null) {
-        validRange =
-            new PermissionRange.WithDefaults(
-                value.getName(),
-                lt.getMin().getValue(),
-                lt.getMax().getValue(),
-                lt.getMin().getValue(),
-                lt.getMax().getValue());
-      }
-    } else if (GlobalCapability.isGlobalCapability(value.getName())) {
-      validRange = GlobalCapability.getRange(value.getName());
-
-    } else {
-      validRange = null;
-    }
-
-    if (Permission.OWNER.equals(value.getName())) {
-      exclusiveGroup.setEnabled(false);
-    } else {
-      exclusiveGroup.setEnabled(!readOnly);
-    }
-  }
-
-  @Override
-  public void flush() {
-    List<PermissionRule> src = rules.getList();
-    List<PermissionRule> keep = new ArrayList<>(src.size());
-
-    for (int i = 0; i < src.size(); i++) {
-      PermissionRuleEditor e = (PermissionRuleEditor) ruleContainer.getWidget(i);
-      if (!e.isDeleted()) {
-        keep.add(src.get(i));
-      }
-    }
-    value.setRules(keep);
-  }
-
-  @Override
-  public void onPropertyChange(String... paths) {}
-
-  @Override
-  public void setDelegate(EditorDelegate<Permission> delegate) {}
-
-  private class RuleEditorSource extends EditorSource<PermissionRuleEditor> {
-    @Override
-    public PermissionRuleEditor create(int index) {
-      PermissionRuleEditor subEditor =
-          new PermissionRuleEditor(readOnly, groupInfo, section, value, validRange);
-      ruleContainer.insert(subEditor, index);
-      return subEditor;
-    }
-
-    @Override
-    public void dispose(PermissionRuleEditor subEditor) {
-      subEditor.removeFromParent();
-    }
-
-    @Override
-    public void setIndex(PermissionRuleEditor subEditor, int index) {
-      ruleContainer.insert(subEditor, index);
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionEditor.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionEditor.ui.xml
deleted file mode 100644
index 00c41dc..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionEditor.ui.xml
+++ /dev/null
@@ -1,146 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2011 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-  xmlns:ui='urn:ui:com.google.gwt.uibinder'
-  xmlns:g='urn:import:com.google.gwt.user.client.ui'
-  xmlns:e='urn:import:com.google.gwt.editor.ui.client'
-  xmlns:my='urn:import:com.google.gerrit.client.admin'
-  ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
-  ui:generateKeys='com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator'
-  ui:generateLocales='default,en'
-  >
-<ui:with field='res' type='com.google.gerrit.client.admin.AdminResources'/>
-<ui:style gss='false'>
-  @eval selectionColor com.google.gerrit.client.Gerrit.getTheme().selectionColor;
-  @eval backgroundColor com.google.gerrit.client.Gerrit.getTheme().backgroundColor;
-
-  .panel {
-    position: relative;
-  }
-
-  .normal {
-    border: 1px solid backgroundColor;
-    margin-top: -1px;
-    margin-bottom: -1px;
-  }
-
-  .header {
-    position: relative;
-    padding-left: 5px;
-    padding-right: 5px;
-    padding-bottom: 1px;
-    white-space: nowrap;
-  }
-
-  .header:hover {
-    background-color: selectionColor;
-  }
-
-  .name {
-    font-style: italic;
-  }
-
-  .exclusiveGroup {
-    position: absolute;
-    top: 0;
-    right: 36px;
-    width: 7em;
-    font-size: 80%;
-  }
-
-  .addContainer {
-    padding-left: 10px;
-    position: relative;
-  }
-  .addContainer:hover {
-    background-color: selectionColor;
-  }
-  .addLink {
-    font-size: 80%;
-  }
-
-  .deleteIcon {
-    position: absolute;
-    top: 1px;
-    right: 12px;
-  }
-</ui:style>
-
-<g:HTMLPanel stylePrimaryName='{style.panel}'>
-<div ui:field='normal' class='{style.normal}'>
-  <div class='{style.header}'>
-    <g:ValueLabel styleName='{style.name}' ui:field='normalName'/>
-    <g:CheckBox
-        ui:field='exclusiveGroup'
-        addStyleNames='{style.exclusiveGroup}'
-        text='Exclusive'>
-      <ui:attribute name='text'/>
-    </g:CheckBox>
-  <g:Anchor
-      ui:field='deletePermission'
-      href='javascript:void'
-      styleName='{style.deleteIcon} {res.css.deleteIcon}'
-      title='Delete this permission (and nested rules)'>
-    <ui:attribute name='title'/>
-  </g:Anchor>
-  </div>
-  <g:FlowPanel ui:field='ruleContainer'/>
-  <div ui:field='addContainer' class='{style.addContainer}'>
-    <div ui:field='addStage1'>
-      <g:Anchor
-          ui:field='beginAddRule'
-          styleName='{style.addLink}'
-          href='javascript:void'
-          text='Add Group'>
-        <ui:attribute name='text'/>
-      </g:Anchor>
-    </div>
-    <div ui:field='addStage2' style='display: none'>
-      <ui:msg>Group Name: <my:GroupReferenceBox
-                                            ui:field='groupToAdd'
-                                            visibleLength='45'/></ui:msg>
-      <g:Button
-          ui:field='addRule'
-          text='Add'>
-        <ui:attribute name='text'/>
-      </g:Button>
-      <g:Anchor
-          ui:field='hideAddGroup'
-          href='javascript:void'
-          styleName='{style.deleteIcon} {res.css.deleteIcon}'
-          title='Cancel additional group'>
-        <ui:attribute name='title'/>
-      </g:Anchor>
-    </div>
-  </div>
-</div>
-
-<div
-    ui:field='deleted'
-    class='{res.css.deleted} {res.css.deletedBorder}'
-    style='display: none'>
-  <ui:msg>Permission <g:ValueLabel styleName='{style.name}' ui:field='deletedName'/> was deleted</ui:msg>
-  <g:Anchor
-      ui:field='undoDelete'
-      href='javascript:void'
-      styleName='{style.deleteIcon} {res.css.undoIcon}'
-      title='Undo deletion'>
-    <ui:attribute name='title'/>
-  </g:Anchor>
-</div>
-</g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionNameRenderer.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionNameRenderer.java
deleted file mode 100644
index ef02bd0..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionNameRenderer.java
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (C) 2011 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import com.google.gerrit.common.data.Permission;
-import com.google.gwt.text.shared.Renderer;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-class PermissionNameRenderer implements Renderer<String> {
-  private static final Map<String, String> permissions;
-
-  static {
-    permissions = new HashMap<>();
-    for (Map.Entry<String, String> e : AdminConstants.I.permissionNames().entrySet()) {
-      permissions.put(e.getKey(), e.getValue());
-      permissions.put(e.getKey().toLowerCase(), e.getValue());
-    }
-  }
-
-  private final Map<String, String> fromServer;
-
-  PermissionNameRenderer(Map<String, String> allFromOutside) {
-    fromServer = allFromOutside;
-  }
-
-  @Override
-  public String render(String varName) {
-    if (Permission.isLabelAs(varName)) {
-      return AdminMessages.I.labelAs(Permission.extractLabel(varName));
-    } else if (Permission.isLabel(varName)) {
-      return AdminMessages.I.label(Permission.extractLabel(varName));
-    }
-
-    String desc = permissions.get(varName);
-    if (desc != null) {
-      return desc;
-    }
-
-    desc = fromServer.get(varName);
-    if (desc != null) {
-      return desc;
-    }
-
-    desc = permissions.get(varName.toLowerCase());
-    if (desc != null) {
-      return desc;
-    }
-
-    desc = fromServer.get(varName.toLowerCase());
-    if (desc != null) {
-      return desc;
-    }
-    return varName;
-  }
-
-  @Override
-  public void render(String object, Appendable appendable) throws IOException {
-    appendable.append(render(object));
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionRuleEditor.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionRuleEditor.java
deleted file mode 100644
index 16dd167..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionRuleEditor.java
+++ /dev/null
@@ -1,258 +0,0 @@
-// Copyright (C) 2011 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import static com.google.gerrit.common.data.Permission.EDIT_TOPIC_NAME;
-import static com.google.gerrit.common.data.Permission.PUSH;
-
-import com.google.gerrit.client.Dispatcher;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.common.data.AccessSection;
-import com.google.gerrit.common.data.GlobalCapability;
-import com.google.gerrit.common.data.GroupInfo;
-import com.google.gerrit.common.data.GroupReference;
-import com.google.gerrit.common.data.Permission;
-import com.google.gerrit.common.data.PermissionRange;
-import com.google.gerrit.common.data.PermissionRule;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.DivElement;
-import com.google.gwt.dom.client.SpanElement;
-import com.google.gwt.dom.client.Style.Display;
-import com.google.gwt.editor.client.Editor;
-import com.google.gwt.editor.client.EditorDelegate;
-import com.google.gwt.editor.client.ValueAwareEditor;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.text.shared.Renderer;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwt.user.client.ui.ValueListBox;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-public class PermissionRuleEditor extends Composite
-    implements Editor<PermissionRule>, ValueAwareEditor<PermissionRule> {
-  interface Binder extends UiBinder<HTMLPanel, PermissionRuleEditor> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  @UiField(provided = true)
-  ValueListBox<PermissionRule.Action> action;
-
-  @UiField(provided = true)
-  RangeBox min;
-
-  @UiField(provided = true)
-  RangeBox max;
-
-  @UiField CheckBox force;
-
-  @UiField Anchor groupNameLink;
-  @UiField SpanElement groupNameSpan;
-  @UiField SpanElement deletedGroupName;
-
-  @UiField Anchor deleteRule;
-
-  @UiField DivElement normal;
-  @UiField DivElement deleted;
-
-  @UiField SpanElement rangeEditor;
-
-  private Map<AccountGroup.UUID, GroupInfo> groupInfo;
-  private boolean isDeleted;
-  private HandlerRegistration clickHandler;
-
-  public PermissionRuleEditor(
-      boolean readOnly,
-      Map<AccountGroup.UUID, GroupInfo> groupInfo,
-      AccessSection section,
-      Permission permission,
-      PermissionRange.WithDefaults validRange) {
-    this.groupInfo = groupInfo;
-    action = new ValueListBox<>(actionRenderer);
-
-    if (validRange != null && 10 < validRange.getRangeSize()) {
-      min = new RangeBox.Box();
-      max = new RangeBox.Box();
-
-    } else if (validRange != null) {
-      RangeBox.List minList = new RangeBox.List();
-      RangeBox.List maxList = new RangeBox.List();
-      List<Integer> valueList = validRange.getValuesAsList();
-
-      minList.list.setValue(validRange.getMin());
-      maxList.list.setValue(validRange.getMax());
-
-      minList.list.setAcceptableValues(valueList);
-      maxList.list.setAcceptableValues(valueList);
-
-      min = minList;
-      max = maxList;
-
-      action.setAcceptableValues(
-          Arrays.asList(
-              PermissionRule.Action.ALLOW,
-              PermissionRule.Action.DENY,
-              PermissionRule.Action.BLOCK));
-
-    } else {
-      min = new RangeBox.Box();
-      max = new RangeBox.Box();
-
-      if (GlobalCapability.PRIORITY.equals(permission.getName())) {
-        action.setValue(PermissionRule.Action.INTERACTIVE);
-        action.setAcceptableValues(
-            Arrays.asList(PermissionRule.Action.INTERACTIVE, PermissionRule.Action.BATCH));
-
-      } else {
-        action.setValue(PermissionRule.Action.ALLOW);
-        action.setAcceptableValues(
-            Arrays.asList(
-                PermissionRule.Action.ALLOW,
-                PermissionRule.Action.DENY,
-                PermissionRule.Action.BLOCK));
-      }
-    }
-
-    initWidget(uiBinder.createAndBindUi(this));
-
-    String name = permission.getName();
-    boolean canForce = PUSH.equals(name);
-    if (canForce) {
-      String ref = section.getName();
-      canForce = !ref.startsWith("refs/for/") && !ref.startsWith("^refs/for/");
-      force.setText(PermissionRule.FORCE_PUSH);
-    } else {
-      canForce = EDIT_TOPIC_NAME.equals(name);
-      force.setText(PermissionRule.FORCE_EDIT);
-    }
-    force.setVisible(canForce);
-    force.setEnabled(!readOnly);
-    action.getElement().setPropertyBoolean("disabled", readOnly);
-
-    if (validRange != null) {
-      min.setEnabled(!readOnly);
-      max.setEnabled(!readOnly);
-    } else {
-      rangeEditor.getStyle().setDisplay(Display.NONE);
-    }
-
-    if (readOnly) {
-      deleteRule.removeFromParent();
-      deleteRule = null;
-    }
-
-    if (name.equals(GlobalCapability.BATCH_CHANGES_LIMIT)) {
-      min.setEnabled(false);
-    }
-  }
-
-  boolean isDeleted() {
-    return isDeleted;
-  }
-
-  @UiHandler("deleteRule")
-  void onDeleteRule(@SuppressWarnings("unused") ClickEvent event) {
-    isDeleted = true;
-    normal.getStyle().setDisplay(Display.NONE);
-    deleted.getStyle().setDisplay(Display.BLOCK);
-  }
-
-  @UiHandler("undoDelete")
-  void onUndoDelete(@SuppressWarnings("unused") ClickEvent event) {
-    isDeleted = false;
-    deleted.getStyle().setDisplay(Display.NONE);
-    normal.getStyle().setDisplay(Display.BLOCK);
-  }
-
-  @Override
-  public void setValue(PermissionRule value) {
-    if (clickHandler != null) {
-      clickHandler.removeHandler();
-      clickHandler = null;
-    }
-
-    GroupReference ref = value.getGroup();
-    GroupInfo info =
-        groupInfo != null && ref.getUUID() != null ? groupInfo.get(ref.getUUID()) : null;
-
-    boolean link;
-    if (ref.getUUID() != null && AccountGroup.isInternalGroup(ref.getUUID())) {
-      final String token = Dispatcher.toGroup(ref.getUUID());
-      groupNameLink.setText(ref.getName());
-      groupNameLink.setHref("#" + token);
-      groupNameLink.setTitle(info != null ? info.getDescription() : null);
-      groupNameLink.setTarget(null);
-      clickHandler =
-          groupNameLink.addClickHandler(
-              new ClickHandler() {
-                @Override
-                public void onClick(ClickEvent event) {
-                  event.preventDefault();
-                  event.stopPropagation();
-                  Gerrit.display(token);
-                }
-              });
-      link = true;
-    } else if (info != null && info.getUrl() != null) {
-      groupNameLink.setText(ref.getName());
-      groupNameLink.setHref(info.getUrl());
-      groupNameLink.setTitle(info.getDescription());
-      groupNameLink.setTarget("_blank");
-      link = true;
-    } else {
-      groupNameSpan.setInnerText(ref.getName());
-      groupNameSpan.setTitle(ref.getUUID() != null ? ref.getUUID().get() : "");
-      link = false;
-    }
-
-    deletedGroupName.setInnerText(ref.getName());
-    groupNameLink.setVisible(link);
-    UIObject.setVisible(groupNameSpan, !link);
-  }
-
-  @Override
-  public void setDelegate(EditorDelegate<PermissionRule> delegate) {}
-
-  @Override
-  public void flush() {}
-
-  @Override
-  public void onPropertyChange(String... paths) {}
-
-  private static class ActionRenderer implements Renderer<PermissionRule.Action> {
-    @Override
-    public String render(PermissionRule.Action object) {
-      return object != null ? object.toString() : "";
-    }
-
-    @Override
-    public void render(PermissionRule.Action object, Appendable appendable) throws IOException {
-      appendable.append(render(object));
-    }
-  }
-
-  private static final ActionRenderer actionRenderer = new ActionRenderer();
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionRuleEditor.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionRuleEditor.ui.xml
deleted file mode 100644
index 644fef4..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionRuleEditor.ui.xml
+++ /dev/null
@@ -1,107 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2011 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-  xmlns:ui='urn:ui:com.google.gwt.uibinder'
-  xmlns:g='urn:import:com.google.gwt.user.client.ui'
-  xmlns:e='urn:import:com.google.gwt.editor.ui.client'
-  xmlns:my='urn:import:com.google.gerrit.client.admin'
-  xmlns:q='urn:import:com.google.gerrit.client.ui'
-  ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
-  ui:generateKeys='com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator'
-  ui:generateLocales='default,en'
-  >
-<ui:with field='res' type='com.google.gerrit.client.admin.AdminResources'/>
-<ui:style gss='false'>
-  @eval selectionColor com.google.gerrit.client.Gerrit.getTheme().selectionColor;
-
-  .panel {
-    position: relative;
-    height: 1.5em;
-  }
-
-  .panel:hover {
-    background-color: selectionColor;
-  }
-
-  .normal {
-    padding-left: 10px;
-    white-space: nowrap;
-    height: 100%;
-  }
-
-  .deleted {
-    height: 100%;
-  }
-
-  .actionList, .minmax {
-    font-size: 80%;
-  }
-
-  .forcePush {
-    position: absolute;
-    top: 0;
-    right: 36px;
-    width: 7em;
-    font-size: 80%;
-  }
-
-  .deleteIcon {
-    position: absolute;
-    top: 2px;
-    right: 11px;
-  }
-
-  .groupName {
-    display: inline;
-  }
-</ui:style>
-
-<g:HTMLPanel styleName='{style.panel}'>
-<div ui:field='normal' class='{style.normal}'>
-  <g:ValueListBox ui:field='action' styleName='{style.actionList}'/>
-  <span ui:field='rangeEditor'>
-    <g:Widget ui:field='min' styleName='{style.minmax}'/>
-    <g:Widget ui:field='max' styleName='{style.minmax}'/>
-  </span>
-
-  <g:Anchor ui:field='groupNameLink' styleName='{style.groupName}'/>
-  <span ui:field='groupNameSpan' styleName='{style.groupName}'/>
-  <g:CheckBox ui:field='force' addStyleNames='{style.forcePush}'/>
-  <g:Anchor
-      ui:field='deleteRule'
-      href='javascript:void'
-      styleName='{style.deleteIcon} {res.css.deleteIcon}'
-      title='Delete this rule'>
-    <ui:attribute name='title'/>
-  </g:Anchor>
-</div>
-
-<div
-    ui:field='deleted'
-    class='{res.css.deleted} {style.deleted}'
-    style='display: none'>
-  <ui:msg>Group <span ui:field='deletedGroupName'/> was deleted</ui:msg>
-  <g:Anchor
-      ui:field='undoDelete'
-      href='javascript:void'
-      styleName='{style.deleteIcon} {res.css.undoIcon}'
-      title='Undo deletion'>
-    <ui:attribute name='title'/>
-  </g:Anchor>
-</div>
-</g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PluginListScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PluginListScreen.java
deleted file mode 100644
index 381c644..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PluginListScreen.java
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.api.ExtensionScreen;
-import com.google.gerrit.client.plugins.PluginInfo;
-import com.google.gerrit.client.plugins.PluginMap;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gerrit.client.ui.FancyFlexTable;
-import com.google.gerrit.client.ui.InlineHyperlink;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.ImageResourceRenderer;
-import com.google.gwt.user.client.ui.Panel;
-
-public class PluginListScreen extends PluginScreen {
-
-  private Panel pluginPanel;
-  private PluginTable pluginTable;
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    initPluginList();
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    PluginMap.all(
-        new ScreenLoadCallback<PluginMap>(this) {
-          @Override
-          protected void preDisplay(PluginMap result) {
-            pluginTable.display(result);
-          }
-        });
-  }
-
-  private void initPluginList() {
-    pluginTable = new PluginTable();
-    pluginTable.addStyleName(Gerrit.RESOURCES.css().pluginsTable());
-
-    pluginPanel = new FlowPanel();
-    pluginPanel.setWidth("500px");
-    pluginPanel.add(pluginTable);
-    add(pluginPanel);
-  }
-
-  private static class PluginTable extends FancyFlexTable<PluginInfo> {
-    PluginTable() {
-      table.setText(0, 1, AdminConstants.I.columnPluginName());
-      table.setText(0, 2, AdminConstants.I.columnPluginSettings());
-      table.setText(0, 3, AdminConstants.I.columnPluginVersion());
-      table.setText(0, 4, AdminConstants.I.columnPluginStatus());
-
-      final FlexCellFormatter fmt = table.getFlexCellFormatter();
-      fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().dataHeader());
-      fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader());
-      fmt.addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader());
-      fmt.addStyleName(0, 4, Gerrit.RESOURCES.css().dataHeader());
-    }
-
-    void display(PluginMap plugins) {
-      while (1 < table.getRowCount()) {
-        table.removeRow(table.getRowCount() - 1);
-      }
-
-      for (PluginInfo p : Natives.asList(plugins.values())) {
-        final int row = table.getRowCount();
-        table.insertRow(row);
-        applyDataRowStyle(row);
-        populate(row, p);
-      }
-    }
-
-    void populate(int row, PluginInfo plugin) {
-      if (plugin.disabled() || plugin.indexUrl() == null) {
-        table.setText(row, 1, plugin.name());
-      } else {
-        table.setWidget(
-            row, 1, new Anchor(plugin.name(), Gerrit.selfRedirect(plugin.indexUrl()), "_blank"));
-
-        if (new ExtensionScreen(plugin.name() + "/settings").isFound()) {
-          InlineHyperlink adminScreenLink = new InlineHyperlink();
-          adminScreenLink.setHTML(new ImageResourceRenderer().render(Gerrit.RESOURCES.gear()));
-          adminScreenLink.setTargetHistoryToken("/x/" + plugin.name() + "/settings");
-          adminScreenLink.setTitle(AdminConstants.I.pluginSettingsToolTip());
-          table.setWidget(row, 2, adminScreenLink);
-        }
-      }
-
-      table.setText(row, 3, plugin.version());
-      table.setText(
-          row,
-          4,
-          plugin.disabled() ? AdminConstants.I.pluginDisabled() : AdminConstants.I.pluginEnabled());
-
-      final FlexCellFormatter fmt = table.getFlexCellFormatter();
-      fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().dataCell());
-      fmt.addStyleName(row, 2, Gerrit.RESOURCES.css().dataCell());
-      fmt.addStyleName(row, 3, Gerrit.RESOURCES.css().dataCell());
-      fmt.addStyleName(row, 4, Gerrit.RESOURCES.css().dataCell());
-
-      setRowItem(row, plugin);
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PluginScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PluginScreen.java
deleted file mode 100644
index 0909fe1..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PluginScreen.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import com.google.gerrit.client.ui.Screen;
-
-public abstract class PluginScreen extends Screen {
-
-  public PluginScreen() {
-    setRequiresSignIn(true);
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    setPageTitle(AdminConstants.I.plugins());
-    display();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessEditor.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessEditor.java
deleted file mode 100644
index a52ea60..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessEditor.java
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright (C) 2011 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import com.google.gerrit.client.Dispatcher;
-import com.google.gerrit.client.ui.Hyperlink;
-import com.google.gerrit.client.ui.ParentProjectBox;
-import com.google.gerrit.common.data.AccessSection;
-import com.google.gerrit.common.data.ProjectAccess;
-import com.google.gerrit.common.data.WebLinkInfoCommon;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.DivElement;
-import com.google.gwt.dom.client.Style.Display;
-import com.google.gwt.editor.client.Editor;
-import com.google.gwt.editor.client.EditorDelegate;
-import com.google.gwt.editor.client.ValueAwareEditor;
-import com.google.gwt.editor.client.adapters.EditorSource;
-import com.google.gwt.editor.client.adapters.ListEditor;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.Image;
-import java.util.ArrayList;
-import java.util.List;
-
-public class ProjectAccessEditor extends Composite
-    implements Editor<ProjectAccess>, ValueAwareEditor<ProjectAccess> {
-  interface Binder extends UiBinder<HTMLPanel, ProjectAccessEditor> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  @UiField DivElement inheritsFrom;
-
-  @UiField Hyperlink parentProject;
-
-  @UiField @Editor.Ignore ParentProjectBox parentProjectBox;
-
-  @UiField DivElement history;
-
-  @UiField FlowPanel webLinkPanel;
-
-  @UiField FlowPanel localContainer;
-  ListEditor<AccessSection, AccessSectionEditor> local;
-
-  @UiField Anchor addSection;
-
-  private ProjectAccess value;
-
-  private boolean editing;
-
-  public ProjectAccessEditor() {
-    initWidget(uiBinder.createAndBindUi(this));
-    local = ListEditor.of(new Source(localContainer));
-  }
-
-  @UiHandler("addSection")
-  void onAddSection(@SuppressWarnings("unused") ClickEvent event) {
-    int index = local.getList().size();
-    local.getList().add(new AccessSection("refs/heads/*"));
-
-    AccessSectionEditor editor = local.getEditors().get(index);
-    editor.enableEditing();
-    editor.editRefPattern();
-  }
-
-  @Override
-  public void setValue(ProjectAccess value) {
-    // If the owner can edit the Global Capabilities but they don't exist in this
-    // project, create an empty one at the beginning of the list making it
-    // possible to add permissions to it.
-    if (editing
-        && value.isOwnerOf(AccessSection.GLOBAL_CAPABILITIES)
-        && value.getLocal(AccessSection.GLOBAL_CAPABILITIES) == null) {
-      value.getLocal().add(0, new AccessSection(AccessSection.GLOBAL_CAPABILITIES));
-    }
-
-    this.value = value;
-
-    Project.NameKey parent = value.getInheritsFrom();
-    if (parent != null) {
-      inheritsFrom.getStyle().setDisplay(Display.BLOCK);
-      parentProject.setText(parent.get());
-      parentProject.setTargetHistoryToken( //
-          Dispatcher.toProjectAdmin(parent, ProjectScreen.ACCESS));
-
-      parentProjectBox.setVisible(editing);
-      parentProjectBox.setProject(value.getProjectName());
-      parentProjectBox.setParentProject(value.getInheritsFrom());
-      parentProject.setVisible(!parentProjectBox.isVisible());
-    } else {
-      inheritsFrom.getStyle().setDisplay(Display.NONE);
-    }
-    setUpWebLinks();
-
-    addSection.setVisible(editing && (!value.getOwnerOf().isEmpty() || value.canUpload()));
-  }
-
-  @Override
-  public void flush() {
-    List<AccessSection> src = local.getList();
-    List<AccessSection> keep = new ArrayList<>(src.size());
-
-    for (int i = 0; i < src.size(); i++) {
-      AccessSectionEditor e = (AccessSectionEditor) localContainer.getWidget(i);
-      if (!e.isDeleted() && !src.get(i).getPermissions().isEmpty()) {
-        keep.add(src.get(i));
-      }
-    }
-    value.setLocal(keep);
-    value.setInheritsFrom(parentProjectBox.getParentProjectName());
-  }
-
-  @Override
-  public void onPropertyChange(String... paths) {}
-
-  @Override
-  public void setDelegate(EditorDelegate<ProjectAccess> delegate) {}
-
-  void setEditing(boolean editing) {
-    this.editing = editing;
-    addSection.setVisible(editing);
-  }
-
-  private void setUpWebLinks() {
-    List<WebLinkInfoCommon> links = value.getFileHistoryLinks();
-    if (!value.isConfigVisible() || links == null || links.isEmpty()) {
-      history.getStyle().setDisplay(Display.NONE);
-      return;
-    }
-    for (WebLinkInfoCommon link : links) {
-      webLinkPanel.add(toAnchor(link));
-    }
-  }
-
-  private static Anchor toAnchor(WebLinkInfoCommon info) {
-    Anchor a = new Anchor();
-    a.setHref(info.url);
-    if (info.target != null && !info.target.isEmpty()) {
-      a.setTarget(info.target);
-    }
-    if (info.imageUrl != null && !info.imageUrl.isEmpty()) {
-      Image img = new Image();
-      img.setAltText(info.name);
-      img.setUrl(info.imageUrl);
-      img.setTitle(info.name);
-      a.getElement().appendChild(img.getElement());
-    } else {
-      a.setText("(" + info.name + ")");
-    }
-    return a;
-  }
-
-  private class Source extends EditorSource<AccessSectionEditor> {
-    private final FlowPanel container;
-
-    Source(FlowPanel container) {
-      this.container = container;
-    }
-
-    @Override
-    public AccessSectionEditor create(int index) {
-      AccessSectionEditor subEditor = new AccessSectionEditor(value);
-      subEditor.setEditing(editing);
-      container.insert(subEditor, index);
-      return subEditor;
-    }
-
-    @Override
-    public void dispose(AccessSectionEditor subEditor) {
-      subEditor.removeFromParent();
-    }
-
-    @Override
-    public void setIndex(AccessSectionEditor subEditor, int index) {
-      container.insert(subEditor, index);
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessEditor.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessEditor.ui.xml
deleted file mode 100644
index 7fbf70d..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessEditor.ui.xml
+++ /dev/null
@@ -1,82 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2011 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-  xmlns:ui='urn:ui:com.google.gwt.uibinder'
-  xmlns:g='urn:import:com.google.gwt.user.client.ui'
-  xmlns:q='urn:import:com.google.gerrit.client.ui'
-  ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
-  ui:generateKeys='com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator'
-  ui:generateLocales='default,en'
-  >
-<ui:style gss='false'>
-  .inheritsFrom {
-    margin-bottom: 0.5em;
-  }
-  .parentTitle {
-    font-weight: bold;
-  }
-  .parentLink {
-    display: inline;
-  }
-
-  .history {
-    margin-bottom: 0.5em;
-  }
-  .historyTitle {
-    font-weight: bold;
-  }
-  .webLinkPanel a {
-    display: inline;
-  }
-  .webLinkPanel>a {
-    margin-left:2px;
-  }
-
-  .addContainer {
-    margin-top: 5px;
-  }
-  .addContainer:hover {
-    background-color: selectionColor;
-  }
-</ui:style>
-
-<g:HTMLPanel>
-  <div ui:field='inheritsFrom' class='{style.inheritsFrom}'>
-    <span class='{style.parentTitle}'><ui:msg>Rights Inherit From:</ui:msg></span>
-    <q:Hyperlink ui:field='parentProject' styleName='{style.parentLink}'/>
-    <q:ParentProjectBox
-      ui:field='parentProjectBox'
-      visible='false'/>
-  </div>
-  <div ui:field='history' class='{style.history}'>
-    <span class='{style.historyTitle}'><ui:msg>History:</ui:msg></span>
-    <td>
-      <g:FlowPanel ui:field="webLinkPanel" styleName='{style.webLinkPanel}'/>
-    </td>
-  </div>
-
-  <g:FlowPanel ui:field='localContainer'/>
-  <div class='{style.addContainer}'>
-    <g:Anchor
-        ui:field='addSection'
-        href='javascript:void'
-        text='Add Reference'>
-      <ui:attribute name='text'/>
-    </g:Anchor>
-  </div>
-</g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessScreen.java
deleted file mode 100644
index eb44bda..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessScreen.java
+++ /dev/null
@@ -1,312 +0,0 @@
-// Copyright (C) 2011 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import static com.google.gerrit.common.ProjectAccessUtil.mergeSections;
-import static com.google.gerrit.common.ProjectAccessUtil.removeEmptyPermissionsAndSections;
-
-import com.google.gerrit.client.ErrorDialog;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.config.CapabilityInfo;
-import com.google.gerrit.client.config.ConfigServerApi;
-import com.google.gerrit.client.rpc.CallbackGroup;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.common.data.AccessSection;
-import com.google.gerrit.common.data.ProjectAccess;
-import com.google.gerrit.common.errors.UpdateParentFailedException;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.DivElement;
-import com.google.gwt.editor.client.SimpleBeanEditorDriver;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwtexpui.globalkey.client.NpTextArea;
-import com.google.gwtjsonrpc.client.RemoteJsonException;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-public class ProjectAccessScreen extends ProjectScreen {
-  interface Binder extends UiBinder<HTMLPanel, ProjectAccessScreen> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  interface Driver
-      extends SimpleBeanEditorDriver< //
-          ProjectAccess, //
-          ProjectAccessEditor> {}
-
-  @UiField DivElement editTools;
-
-  @UiField Button edit;
-
-  @UiField Button cancel1;
-
-  @UiField Button cancel2;
-
-  @UiField VerticalPanel error;
-
-  @UiField ProjectAccessEditor accessEditor;
-
-  @UiField DivElement commitTools;
-
-  @UiField NpTextArea commitMessage;
-
-  @UiField Button commit;
-
-  @UiField Button review;
-
-  private Driver driver;
-
-  private ProjectAccess access;
-
-  private NativeMap<CapabilityInfo> capabilityMap;
-
-  public ProjectAccessScreen(Project.NameKey toShow) {
-    super(toShow);
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    add(uiBinder.createAndBindUi(this));
-
-    driver = GWT.create(Driver.class);
-    accessEditor.setEditing(false);
-    driver.initialize(accessEditor);
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    CallbackGroup cbs = new CallbackGroup();
-    ConfigServerApi.capabilities(
-        cbs.add(
-            new AsyncCallback<NativeMap<CapabilityInfo>>() {
-              @Override
-              public void onSuccess(NativeMap<CapabilityInfo> result) {
-                capabilityMap = result;
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {
-                // Handled by ScreenLoadCallback.onFailure().
-              }
-            }));
-    Util.PROJECT_SVC.projectAccess(
-        getProjectKey(),
-        cbs.addFinal(
-            new ScreenLoadCallback<ProjectAccess>(this) {
-              @Override
-              public void preDisplay(ProjectAccess access) {
-                displayReadOnly(access);
-              }
-            }));
-    savedPanel = ACCESS;
-  }
-
-  private void displayReadOnly(ProjectAccess access) {
-    this.access = access;
-    Map<String, String> allCapabilities = new HashMap<>();
-    for (CapabilityInfo c : Natives.asList(capabilityMap.values())) {
-      allCapabilities.put(c.id(), c.name());
-    }
-    this.access.setCapabilities(allCapabilities);
-    accessEditor.setEditing(false);
-    UIObject.setVisible(editTools, !access.getOwnerOf().isEmpty() || access.canUpload());
-    edit.setEnabled(!access.getOwnerOf().isEmpty() || access.canUpload());
-    cancel1.setVisible(false);
-    UIObject.setVisible(commitTools, false);
-    driver.edit(access);
-  }
-
-  @UiHandler("edit")
-  void onEdit(@SuppressWarnings("unused") ClickEvent event) {
-    resetEditors();
-
-    edit.setEnabled(false);
-    cancel1.setVisible(true);
-    UIObject.setVisible(commitTools, true);
-    commit.setVisible(!access.getOwnerOf().isEmpty());
-    review.setVisible(access.canUpload());
-    accessEditor.setEditing(true);
-    driver.edit(access);
-  }
-
-  private void resetEditors() {
-    // Push an empty instance through the driver before pushing the real
-    // data. This will force GWT to delete and recreate the editors, which
-    // is required to build initialize them as editable vs. read-only.
-    ProjectAccess mock = new ProjectAccess();
-    mock.setProjectName(access.getProjectName());
-    mock.setRevision(access.getRevision());
-    mock.setLocal(Collections.<AccessSection>emptyList());
-    mock.setOwnerOf(Collections.<String>emptySet());
-    driver.edit(mock);
-  }
-
-  @UiHandler(value = {"cancel1", "cancel2"})
-  void onCancel(@SuppressWarnings("unused") ClickEvent event) {
-    Gerrit.display(PageLinks.toProjectAcceess(getProjectKey()));
-  }
-
-  @UiHandler("commit")
-  void onCommit(@SuppressWarnings("unused") ClickEvent event) {
-    final ProjectAccess access = driver.flush();
-
-    if (driver.hasErrors()) {
-      Window.alert(AdminConstants.I.errorsMustBeFixed());
-      return;
-    }
-
-    String message = commitMessage.getText().trim();
-    if ("".equals(message)) {
-      message = null;
-    }
-
-    enable(false);
-    Util.PROJECT_SVC.changeProjectAccess( //
-        getProjectKey(), //
-        access.getRevision(), //
-        message, //
-        access.getLocal(), //
-        access.getInheritsFrom(), //
-        new GerritCallback<ProjectAccess>() {
-          @Override
-          public void onSuccess(ProjectAccess newAccess) {
-            enable(true);
-            commitMessage.setText("");
-            error.clear();
-            final Set<String> diffs = getDiffs(access, newAccess);
-            if (diffs.isEmpty()) {
-              displayReadOnly(newAccess);
-            } else {
-              error.add(new Label(Gerrit.C.projectAccessError()));
-              for (String diff : diffs) {
-                error.add(new Label(diff));
-              }
-              if (access.canUpload()) {
-                error.add(new Label(Gerrit.C.projectAccessProposeForReviewHint()));
-              }
-            }
-          }
-
-          private Set<String> getDiffs(ProjectAccess wantedAccess, ProjectAccess newAccess) {
-            List<AccessSection> wantedSections =
-                mergeSections(removeEmptyPermissionsAndSections(wantedAccess.getLocal()));
-            List<AccessSection> newSections =
-                removeEmptyPermissionsAndSections(newAccess.getLocal());
-            HashSet<AccessSection> same = new HashSet<>(wantedSections);
-            HashSet<AccessSection> different =
-                new HashSet<>(wantedSections.size() + newSections.size());
-            different.addAll(wantedSections);
-            different.addAll(newSections);
-            same.retainAll(newSections);
-            different.removeAll(same);
-
-            Set<String> differentNames = new HashSet<>();
-            for (AccessSection s : different) {
-              differentNames.add(s.getName());
-            }
-            return differentNames;
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            error.clear();
-            enable(true);
-            if (caught instanceof RemoteJsonException
-                && caught.getMessage().startsWith(UpdateParentFailedException.MESSAGE)) {
-              new ErrorDialog(
-                      Gerrit.M.parentUpdateFailed(
-                          caught
-                              .getMessage()
-                              .substring(UpdateParentFailedException.MESSAGE.length() + 1)))
-                  .center();
-            } else {
-              super.onFailure(caught);
-            }
-          }
-        });
-  }
-
-  @UiHandler("review")
-  void onReview(@SuppressWarnings("unused") ClickEvent event) {
-    final ProjectAccess access = driver.flush();
-
-    if (driver.hasErrors()) {
-      Window.alert(AdminConstants.I.errorsMustBeFixed());
-      return;
-    }
-
-    String message = commitMessage.getText().trim();
-    if ("".equals(message)) {
-      message = null;
-    }
-
-    enable(false);
-    Util.PROJECT_SVC.reviewProjectAccess( //
-        getProjectKey(), //
-        access.getRevision(), //
-        message, //
-        access.getLocal(), //
-        access.getInheritsFrom(), //
-        new GerritCallback<Change.Id>() {
-          @Override
-          public void onSuccess(Change.Id changeId) {
-            enable(true);
-            commitMessage.setText("");
-            error.clear();
-            if (changeId != null) {
-              Gerrit.display(PageLinks.toChange(getProjectKey(), changeId));
-            } else {
-              displayReadOnly(access);
-            }
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            error.clear();
-            enable(true);
-            super.onFailure(caught);
-          }
-        });
-  }
-
-  private void enable(boolean enabled) {
-    commitMessage.setEnabled(enabled);
-    commit.setEnabled(enabled && !access.getOwnerOf().isEmpty());
-    review.setEnabled(enabled && access.canUpload());
-    cancel1.setEnabled(enabled);
-    cancel2.setEnabled(enabled);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessScreen.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessScreen.ui.xml
deleted file mode 100644
index 724c7a1..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessScreen.ui.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2011 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-  xmlns:ui='urn:ui:com.google.gwt.uibinder'
-  xmlns:g='urn:import:com.google.gwt.user.client.ui'
-  xmlns:my='urn:import:com.google.gerrit.client.admin'
-  xmlns:expui='urn:import:com.google.gwtexpui.globalkey.client'
-  ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
-  ui:generateKeys='com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator'
-  ui:generateLocales='default,en'
-  >
-<ui:style gss='false'>
-  @external .gwt-TextArea;
-
-  .commitMessage {
-    margin-top: 2em;
-  }
-  .commitMessage .gwt-TextArea {
-    margin: 5px 5px 5px 5px;
-  }
-  .errorMessage {
-    margin-top: 5px;
-    margin-bottom: 5px;
-    color: red;
-  }
-</ui:style>
-
-<g:HTMLPanel>
-  <div ui:field='editTools'>
-    <g:Button
-        ui:field='edit'
-        text='Edit'>
-      <ui:attribute name='text'/>
-    </g:Button>
-    <g:Button
-        ui:field='cancel1'
-        text='Cancel'>
-      <ui:attribute name='text'/>
-    </g:Button>
-  </div>
-  <my:ProjectAccessEditor ui:field='accessEditor'/>
-  <div ui:field='commitTools'>
-    <div class='{style.commitMessage}'>
-      <ui:msg>Commit Message (optional):</ui:msg><br/>
-      <expui:NpTextArea
-          ui:field='commitMessage'
-          visibleLines='4'
-          characterWidth='60'
-          spellCheck='true'
-          />
-    </div>
-    <g:VerticalPanel
-      styleName='{style.errorMessage}'
-      ui:field='error'>
-    </g:VerticalPanel>
-    <g:Button
-        ui:field='commit'
-        text='Save Changes'>
-      <ui:attribute name='text'/>
-    </g:Button>
-    <g:Button
-        ui:field='review'
-        text='Save for Review'>
-      <ui:attribute name='text'/>
-    </g:Button>
-    <g:Button
-        ui:field='cancel2'
-        text='Cancel'>
-      <ui:attribute name='text'/>
-    </g:Button>
-  </div>
-</g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesScreen.java
deleted file mode 100644
index c6a391b..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesScreen.java
+++ /dev/null
@@ -1,673 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import static com.google.gerrit.client.ui.Util.highlight;
-
-import com.google.gerrit.client.ConfirmationCallback;
-import com.google.gerrit.client.ConfirmationDialog;
-import com.google.gerrit.client.ErrorDialog;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.VoidResult;
-import com.google.gerrit.client.access.AccessMap;
-import com.google.gerrit.client.access.ProjectAccessInfo;
-import com.google.gerrit.client.actions.ActionButton;
-import com.google.gerrit.client.info.ActionInfo;
-import com.google.gerrit.client.info.WebLinkInfo;
-import com.google.gerrit.client.projects.BranchInfo;
-import com.google.gerrit.client.projects.ProjectApi;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.NativeString;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gerrit.client.ui.HintTextBox;
-import com.google.gerrit.client.ui.Hyperlink;
-import com.google.gerrit.client.ui.NavigationTable;
-import com.google.gerrit.client.ui.OnEditEnabler;
-import com.google.gerrit.client.ui.PagingHyperlink;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.event.dom.client.KeyUpEvent;
-import com.google.gwt.event.dom.client.KeyUpHandler;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.logical.shared.ValueChangeHandler;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.InlineHTML;
-import com.google.gwt.user.client.ui.InlineLabel;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.globalkey.client.NpTextBox;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-public class ProjectBranchesScreen extends PaginatedProjectScreen {
-  private Hyperlink prev;
-  private Hyperlink next;
-  private BranchesTable branchTable;
-  private Button delBranch;
-  private Button addBranch;
-  private HintTextBox nameTxtBox;
-  private HintTextBox irevTxtBox;
-  private FlowPanel addPanel;
-  private NpTextBox filterTxt;
-  private Query query;
-
-  public ProjectBranchesScreen(Project.NameKey toShow) {
-    super(toShow);
-  }
-
-  @Override
-  public String getScreenToken() {
-    return PageLinks.toProjectBranches(getProjectKey());
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    addPanel.setVisible(false);
-    AccessMap.get(
-        getProjectKey(),
-        new GerritCallback<ProjectAccessInfo>() {
-          @Override
-          public void onSuccess(ProjectAccessInfo result) {
-            addPanel.setVisible(result.canAddRefs());
-          }
-        });
-    query = new Query(match).start(start).run();
-    savedPanel = BRANCHES;
-  }
-
-  private void updateForm() {
-    branchTable.updateDeleteButton();
-    addBranch.setEnabled(true);
-    nameTxtBox.setEnabled(true);
-    irevTxtBox.setEnabled(true);
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    initPageHeader();
-
-    prev = PagingHyperlink.createPrev();
-    prev.setVisible(false);
-
-    next = PagingHyperlink.createNext();
-    next.setVisible(false);
-
-    addPanel = new FlowPanel();
-
-    final Grid addGrid = new Grid(2, 2);
-    addGrid.setStyleName(Gerrit.RESOURCES.css().addBranch());
-    final int texBoxLength = 50;
-
-    nameTxtBox = new HintTextBox();
-    nameTxtBox.setVisibleLength(texBoxLength);
-    nameTxtBox.setHintText(AdminConstants.I.defaultBranchName());
-    nameTxtBox.addKeyPressHandler(
-        new KeyPressHandler() {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
-              doAddNewBranch();
-            }
-          }
-        });
-    addGrid.setText(0, 0, AdminConstants.I.columnBranchName() + ":");
-    addGrid.setWidget(0, 1, nameTxtBox);
-
-    irevTxtBox = new HintTextBox();
-    irevTxtBox.setVisibleLength(texBoxLength);
-    irevTxtBox.setHintText(AdminConstants.I.defaultRevisionSpec());
-    irevTxtBox.addKeyPressHandler(
-        new KeyPressHandler() {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
-              doAddNewBranch();
-            }
-          }
-        });
-    addGrid.setText(1, 0, AdminConstants.I.initialRevision() + ":");
-    addGrid.setWidget(1, 1, irevTxtBox);
-
-    addBranch = new Button(AdminConstants.I.buttonAddBranch());
-    addBranch.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            doAddNewBranch();
-          }
-        });
-    addPanel.add(addGrid);
-    addPanel.add(addBranch);
-
-    branchTable = new BranchesTable();
-
-    delBranch = new Button(AdminConstants.I.buttonDeleteBranch());
-    delBranch.setStyleName(Gerrit.RESOURCES.css().branchTableDeleteButton());
-    delBranch.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            branchTable.deleteChecked();
-          }
-        });
-    HorizontalPanel buttons = new HorizontalPanel();
-    buttons.setStyleName(Gerrit.RESOURCES.css().branchTablePrevNextLinks());
-    buttons.add(delBranch);
-    buttons.add(prev);
-    buttons.add(next);
-    add(branchTable);
-    add(buttons);
-    add(addPanel);
-  }
-
-  private void initPageHeader() {
-    parseToken();
-    HorizontalPanel hp = new HorizontalPanel();
-    hp.setStyleName(Gerrit.RESOURCES.css().projectFilterPanel());
-    Label filterLabel = new Label(AdminConstants.I.projectFilter());
-    filterLabel.setStyleName(Gerrit.RESOURCES.css().projectFilterLabel());
-    hp.add(filterLabel);
-    filterTxt = new NpTextBox();
-    filterTxt.setValue(match);
-    filterTxt.addKeyUpHandler(
-        new KeyUpHandler() {
-          @Override
-          public void onKeyUp(KeyUpEvent event) {
-            Query q = new Query(filterTxt.getValue());
-            if (match.equals(q.qMatch)) {
-              q.start(start);
-            } else {
-              if (query == null) {
-                q.run();
-              }
-              query = q;
-            }
-          }
-        });
-    hp.add(filterTxt);
-    add(hp);
-  }
-
-  private void doAddNewBranch() {
-    final String branchName = nameTxtBox.getText().trim();
-    if ("".equals(branchName)) {
-      nameTxtBox.setFocus(true);
-      return;
-    }
-
-    final String rev = irevTxtBox.getText().trim();
-    if ("".equals(rev)) {
-      irevTxtBox.setText("HEAD");
-      Scheduler.get()
-          .scheduleDeferred(
-              new ScheduledCommand() {
-                @Override
-                public void execute() {
-                  irevTxtBox.selectAll();
-                  irevTxtBox.setFocus(true);
-                }
-              });
-      return;
-    }
-
-    addBranch.setEnabled(false);
-    ProjectApi.createBranch(
-        getProjectKey(),
-        branchName,
-        rev,
-        new GerritCallback<BranchInfo>() {
-          @Override
-          public void onSuccess(BranchInfo branch) {
-            showAddedBranch(branch);
-            nameTxtBox.setText("");
-            irevTxtBox.setText("");
-            query = new Query(match).start(start).run();
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            addBranch.setEnabled(true);
-            selectAllAndFocus(nameTxtBox);
-            new ErrorDialog(caught.getMessage()).center();
-          }
-        });
-  }
-
-  void showAddedBranch(BranchInfo branch) {
-    SafeHtmlBuilder b = new SafeHtmlBuilder();
-    b.openElement("b");
-    b.append(Gerrit.C.branchCreationConfirmationMessage());
-    b.closeElement("b");
-
-    b.openElement("p");
-    b.append(branch.ref());
-    b.closeElement("p");
-
-    ConfirmationDialog confirmationDialog =
-        new ConfirmationDialog(
-            Gerrit.C.branchCreationDialogTitle(),
-            b.toSafeHtml(),
-            new ConfirmationCallback() {
-              @Override
-              public void onOk() {
-                // do nothing
-              }
-            });
-    confirmationDialog.center();
-    confirmationDialog.setCancelVisible(false);
-  }
-
-  private static void selectAllAndFocus(TextBox textBox) {
-    textBox.selectAll();
-    textBox.setFocus(true);
-  }
-
-  private class BranchesTable extends NavigationTable<BranchInfo> {
-    private ValueChangeHandler<Boolean> updateDeleteHandler;
-    boolean canDelete;
-
-    BranchesTable() {
-      table.setWidth("");
-      table.setText(0, 2, AdminConstants.I.columnBranchName());
-      table.setText(0, 3, AdminConstants.I.columnBranchRevision());
-
-      final FlexCellFormatter fmt = table.getFlexCellFormatter();
-      fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().iconHeader());
-      fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader());
-      fmt.addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader());
-      fmt.addStyleName(0, 4, Gerrit.RESOURCES.css().dataHeader());
-
-      updateDeleteHandler =
-          new ValueChangeHandler<Boolean>() {
-            @Override
-            public void onValueChange(ValueChangeEvent<Boolean> event) {
-              updateDeleteButton();
-            }
-          };
-    }
-
-    Set<String> getCheckedRefs() {
-      Set<String> refs = new HashSet<>();
-      for (int row = 1; row < table.getRowCount(); row++) {
-        final BranchInfo k = getRowItem(row);
-        if (k != null
-            && table.getWidget(row, 1) instanceof CheckBox
-            && ((CheckBox) table.getWidget(row, 1)).getValue()) {
-          refs.add(k.ref());
-        }
-      }
-      return refs;
-    }
-
-    void setChecked(Set<String> refs) {
-      for (int row = 1; row < table.getRowCount(); row++) {
-        final BranchInfo k = getRowItem(row);
-        if (k != null && refs.contains(k.ref()) && table.getWidget(row, 1) instanceof CheckBox) {
-          ((CheckBox) table.getWidget(row, 1)).setValue(true);
-        }
-      }
-    }
-
-    void deleteChecked() {
-      final Set<String> refs = getCheckedRefs();
-
-      SafeHtmlBuilder b = new SafeHtmlBuilder();
-      b.openElement("b");
-      b.append(Gerrit.C.branchDeletionConfirmationMessage());
-      b.closeElement("b");
-
-      b.openElement("p");
-      boolean first = true;
-      for (String ref : refs) {
-        if (!first) {
-          b.append(",").br();
-        }
-        b.append(ref);
-        first = false;
-      }
-      b.closeElement("p");
-
-      if (refs.isEmpty()) {
-        updateDeleteButton();
-        return;
-      }
-
-      delBranch.setEnabled(false);
-      ConfirmationDialog confirmationDialog =
-          new ConfirmationDialog(
-              Gerrit.C.branchDeletionDialogTitle(),
-              b.toSafeHtml(),
-              new ConfirmationCallback() {
-                @Override
-                public void onOk() {
-                  deleteBranches(refs);
-                }
-
-                @Override
-                public void onCancel() {
-                  branchTable.updateDeleteButton();
-                }
-              });
-      confirmationDialog.center();
-    }
-
-    private void deleteBranches(Set<String> branches) {
-      ProjectApi.deleteBranches(
-          getProjectKey(),
-          branches,
-          new GerritCallback<VoidResult>() {
-            @Override
-            public void onSuccess(VoidResult result) {
-              query = new Query(match).start(start).run();
-            }
-
-            @Override
-            public void onFailure(Throwable caught) {
-              query = new Query(match).start(start).run();
-              super.onFailure(caught);
-            }
-          });
-    }
-
-    void display(List<BranchInfo> branches) {
-      displaySubset(branches, 0, branches.size());
-    }
-
-    void displaySubset(List<BranchInfo> branches, int fromIndex, int toIndex) {
-      canDelete = false;
-
-      while (1 < table.getRowCount()) {
-        table.removeRow(table.getRowCount() - 1);
-      }
-
-      for (BranchInfo k : branches.subList(fromIndex, toIndex)) {
-        final int row = table.getRowCount();
-        table.insertRow(row);
-        applyDataRowStyle(row);
-        populate(row, k);
-      }
-    }
-
-    void populate(int row, BranchInfo k) {
-      if (k.canDelete()) {
-        CheckBox sel = new CheckBox();
-        sel.addValueChangeHandler(updateDeleteHandler);
-        table.setWidget(row, 1, sel);
-        canDelete = true;
-      } else {
-        table.setText(row, 1, "");
-      }
-
-      table.setWidget(row, 2, new InlineHTML(highlight(k.getShortName(), match)));
-
-      if (k.revision() != null) {
-        if ("HEAD".equals(k.getShortName())) {
-          setHeadRevision(row, 3, k.revision());
-        } else {
-          table.setText(row, 3, k.revision());
-        }
-      } else {
-        table.setText(row, 3, "");
-      }
-
-      FlowPanel actionsPanel = new FlowPanel();
-      if (k.webLinks() != null) {
-        for (WebLinkInfo webLink : Natives.asList(k.webLinks())) {
-          actionsPanel.add(webLink.toAnchor());
-        }
-      }
-      if (k.actions() != null) {
-        k.actions().copyKeysIntoChildren("id");
-        for (ActionInfo a : Natives.asList(k.actions().values())) {
-          actionsPanel.add(new ActionButton(getProjectKey(), k, a));
-        }
-      }
-      table.setWidget(row, 4, actionsPanel);
-
-      final FlexCellFormatter fmt = table.getFlexCellFormatter();
-      String iconCellStyle = Gerrit.RESOURCES.css().iconCell();
-      String dataCellStyle = Gerrit.RESOURCES.css().dataCell();
-      if (RefNames.REFS_CONFIG.equals(k.getShortName()) || "HEAD".equals(k.getShortName())) {
-        iconCellStyle = Gerrit.RESOURCES.css().specialBranchIconCell();
-        dataCellStyle = Gerrit.RESOURCES.css().specialBranchDataCell();
-        fmt.setStyleName(row, 0, iconCellStyle);
-      }
-      fmt.addStyleName(row, 1, iconCellStyle);
-      fmt.addStyleName(row, 2, dataCellStyle);
-      fmt.addStyleName(row, 3, dataCellStyle);
-      fmt.addStyleName(row, 4, dataCellStyle);
-
-      setRowItem(row, k);
-    }
-
-    private void setHeadRevision(int row, int column, String rev) {
-      AccessMap.get(
-          getProjectKey(),
-          new GerritCallback<ProjectAccessInfo>() {
-            @Override
-            public void onSuccess(ProjectAccessInfo result) {
-              if (result.isOwner()) {
-                table.setWidget(row, column, getHeadRevisionWidget(rev));
-              } else {
-                table.setText(row, 3, rev);
-              }
-            }
-          });
-    }
-
-    private Widget getHeadRevisionWidget(String headRevision) {
-      FlowPanel p = new FlowPanel();
-      final InlineLabel l = new InlineLabel(headRevision);
-      final Image edit = new Image(Gerrit.RESOURCES.edit());
-      edit.addStyleName(Gerrit.RESOURCES.css().editHeadButton());
-
-      final NpTextBox input = new NpTextBox();
-      input.setVisibleLength(35);
-      input.setValue(headRevision);
-      input.setVisible(false);
-      final Button save = new Button();
-      save.setText(AdminConstants.I.saveHeadButton());
-      save.setVisible(false);
-      save.setEnabled(false);
-      final Button cancel = new Button();
-      cancel.setText(AdminConstants.I.cancelHeadButton());
-      cancel.setVisible(false);
-
-      OnEditEnabler e = new OnEditEnabler(save);
-      e.listenTo(input);
-
-      edit.addClickHandler(
-          new ClickHandler() {
-            @Override
-            public void onClick(ClickEvent event) {
-              l.setVisible(false);
-              edit.setVisible(false);
-              input.setVisible(true);
-              save.setVisible(true);
-              cancel.setVisible(true);
-            }
-          });
-      save.addClickHandler(
-          new ClickHandler() {
-            @Override
-            public void onClick(ClickEvent event) {
-              save.setEnabled(false);
-              ProjectApi.setHead(
-                  getProjectKey(),
-                  input.getValue().trim(),
-                  new GerritCallback<NativeString>() {
-                    @Override
-                    public void onSuccess(NativeString result) {
-                      Gerrit.display(PageLinks.toProjectBranches(getProjectKey()));
-                    }
-
-                    @Override
-                    public void onFailure(Throwable caught) {
-                      super.onFailure(caught);
-                      save.setEnabled(true);
-                    }
-                  });
-            }
-          });
-      cancel.addClickHandler(
-          new ClickHandler() {
-            @Override
-            public void onClick(ClickEvent event) {
-              l.setVisible(true);
-              edit.setVisible(true);
-              input.setVisible(false);
-              input.setValue(headRevision);
-              save.setVisible(false);
-              save.setEnabled(false);
-              cancel.setVisible(false);
-            }
-          });
-
-      p.add(l);
-      p.add(edit);
-      p.add(input);
-      p.add(save);
-      p.add(cancel);
-      return p;
-    }
-
-    boolean hasBranchCanDelete() {
-      return canDelete;
-    }
-
-    void updateDeleteButton() {
-      boolean on = false;
-      for (int row = 1; row < table.getRowCount(); row++) {
-        Widget w = table.getWidget(row, 1);
-        if (w != null && w instanceof CheckBox) {
-          CheckBox sel = (CheckBox) w;
-          if (sel.getValue()) {
-            on = true;
-            break;
-          }
-        }
-      }
-      delBranch.setEnabled(on);
-    }
-
-    @Override
-    protected void onOpenRow(int row) {
-      if (row > 0) {
-        movePointerTo(row);
-      }
-    }
-
-    @Override
-    protected Object getRowItemKey(BranchInfo item) {
-      return item.ref();
-    }
-  }
-
-  @Override
-  public void onShowView() {
-    super.onShowView();
-    if (match != null) {
-      filterTxt.setCursorPos(match.length());
-    }
-    filterTxt.setFocus(true);
-  }
-
-  private class Query {
-    private String qMatch;
-    private int qStart;
-
-    Query(String match) {
-      this.qMatch = match;
-    }
-
-    Query start(int start) {
-      this.qStart = start;
-      return this;
-    }
-
-    Query run() {
-      // Retrieve one more branch than page size to determine if there are more
-      // branches to display
-      ProjectApi.getBranches(
-          getProjectKey(),
-          pageSize + 1,
-          qStart,
-          qMatch,
-          new ScreenLoadCallback<JsArray<BranchInfo>>(ProjectBranchesScreen.this) {
-            @Override
-            public void preDisplay(JsArray<BranchInfo> result) {
-              if (!isAttached()) {
-                // View has been disposed.
-              } else if (query == Query.this) {
-                query = null;
-                showList(result);
-              } else {
-                query.run();
-              }
-            }
-          });
-      return this;
-    }
-
-    void showList(JsArray<BranchInfo> result) {
-      setToken(getTokenForScreen(qMatch, qStart));
-      ProjectBranchesScreen.this.match = qMatch;
-      ProjectBranchesScreen.this.start = qStart;
-
-      if (result.length() <= pageSize) {
-        branchTable.display(Natives.asList(result));
-        next.setVisible(false);
-      } else {
-        branchTable.displaySubset(Natives.asList(result), 0, result.length() - 1);
-        setupNavigationLink(next, qMatch, qStart + pageSize);
-      }
-      if (qStart > 0) {
-        setupNavigationLink(prev, qMatch, qStart - pageSize);
-      } else {
-        prev.setVisible(false);
-      }
-
-      delBranch.setVisible(branchTable.hasBranchCanDelete());
-      Set<String> checkedRefs = branchTable.getCheckedRefs();
-      branchTable.setChecked(checkedRefs);
-      updateForm();
-
-      if (!isCurrentView()) {
-        display();
-      }
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectDashboardsScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectDashboardsScreen.java
deleted file mode 100644
index 7b5d04d..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectDashboardsScreen.java
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import com.google.gerrit.client.dashboards.DashboardList;
-import com.google.gerrit.client.dashboards.DashboardsTable;
-import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.user.client.ui.FlowPanel;
-
-public class ProjectDashboardsScreen extends ProjectScreen {
-  private DashboardsTable dashes;
-  Project.NameKey project;
-
-  public ProjectDashboardsScreen(Project.NameKey project) {
-    super(project);
-    this.project = project;
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    DashboardList.all(
-        getProjectKey(),
-        new ScreenLoadCallback<JsArray<DashboardList>>(this) {
-          @Override
-          protected void preDisplay(JsArray<DashboardList> result) {
-            dashes.display(result);
-          }
-        });
-    savedPanel = DASHBOARDS;
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    dashes = new DashboardsTable(project);
-    FlowPanel fp = new FlowPanel();
-    fp.add(dashes);
-    add(fp);
-    dashes.setSavePointerId("dashboards/project/" + getProjectKey().get());
-    display();
-  }
-
-  @Override
-  public void registerKeys() {
-    super.registerKeys();
-    dashes.setRegisterKeys(true);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java
deleted file mode 100644
index d10a031..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java
+++ /dev/null
@@ -1,826 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.GerritUiExtensionPoint;
-import com.google.gerrit.client.StringListPanel;
-import com.google.gerrit.client.access.AccessMap;
-import com.google.gerrit.client.access.ProjectAccessInfo;
-import com.google.gerrit.client.actions.ActionButton;
-import com.google.gerrit.client.api.ExtensionPanel;
-import com.google.gerrit.client.change.Resources;
-import com.google.gerrit.client.download.DownloadPanel;
-import com.google.gerrit.client.info.ActionInfo;
-import com.google.gerrit.client.info.DownloadInfo.DownloadCommandInfo;
-import com.google.gerrit.client.info.DownloadInfo.DownloadSchemeInfo;
-import com.google.gerrit.client.projects.ConfigInfo;
-import com.google.gerrit.client.projects.ConfigInfo.ConfigParameterInfo;
-import com.google.gerrit.client.projects.ConfigInfo.ConfigParameterValue;
-import com.google.gerrit.client.projects.ConfigInfo.InheritedBooleanInfo;
-import com.google.gerrit.client.projects.ConfigInfo.SubmitTypeInfo;
-import com.google.gerrit.client.projects.ProjectApi;
-import com.google.gerrit.client.rpc.CallbackGroup;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gerrit.client.ui.NpIntTextBox;
-import com.google.gerrit.client.ui.OnEditEnabler;
-import com.google.gerrit.client.ui.SmallHeading;
-import com.google.gerrit.extensions.client.InheritableBoolean;
-import com.google.gerrit.extensions.client.ProjectState;
-import com.google.gerrit.extensions.client.SubmitType;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.event.dom.client.ChangeEvent;
-import com.google.gwt.event.dom.client.ChangeHandler;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.FlexTable;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HasEnabled;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.ListBox;
-import com.google.gwt.user.client.ui.Panel;
-import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.globalkey.client.NpTextArea;
-import com.google.gwtexpui.globalkey.client.NpTextBox;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-public class ProjectInfoScreen extends ProjectScreen {
-  private boolean isOwner;
-  private boolean configVisible;
-
-  private LabeledWidgetsGrid grid;
-  private Panel pluginOptionsPanel;
-  private LabeledWidgetsGrid actionsGrid;
-
-  // Section: Project Options
-  private ListBox requireChangeID;
-  private ListBox submitType;
-  private ListBox state;
-  private ListBox contentMerge;
-  private ListBox newChangeForAllNotInTarget;
-  private ListBox enableSignedPush;
-  private ListBox requireSignedPush;
-  private ListBox rejectImplicitMerges;
-  private ListBox privateByDefault;
-  private ListBox workInProgressByDefault;
-  private ListBox enableReviewerByEmail;
-  private ListBox matchAuthorToCommitterDate;
-  private NpTextBox maxObjectSizeLimit;
-  private Label effectiveMaxObjectSizeLimit;
-  private Map<String, Map<String, HasEnabled>> pluginConfigWidgets;
-
-  // Section: Contributor Agreements
-  private ListBox contributorAgreements;
-  private ListBox signedOffBy;
-
-  private NpTextArea descTxt;
-  private Button saveProject;
-
-  private OnEditEnabler saveEnabler;
-
-  public ProjectInfoScreen(Project.NameKey toShow) {
-    super(toShow);
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-
-    Resources.I.style().ensureInjected();
-    saveProject = new Button(AdminConstants.I.buttonSaveChanges());
-    saveProject.setStyleName("");
-    saveProject.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            doSave();
-          }
-        });
-
-    ExtensionPanel extensionPanelTop =
-        new ExtensionPanel(GerritUiExtensionPoint.PROJECT_INFO_SCREEN_TOP);
-    extensionPanelTop.put(GerritUiExtensionPoint.Key.PROJECT_NAME, getProjectKey().get());
-    add(extensionPanelTop);
-
-    add(new ProjectDownloadPanel(getProjectKey().get(), true));
-
-    initDescription();
-    grid = new LabeledWidgetsGrid();
-    pluginOptionsPanel = new FlowPanel();
-    actionsGrid = new LabeledWidgetsGrid();
-    initProjectOptions();
-    initAgreements();
-    add(grid);
-    add(pluginOptionsPanel);
-    add(saveProject);
-    add(actionsGrid);
-
-    ExtensionPanel extensionPanelBottom =
-        new ExtensionPanel(GerritUiExtensionPoint.PROJECT_INFO_SCREEN_BOTTOM);
-    extensionPanelBottom.put(GerritUiExtensionPoint.Key.PROJECT_NAME, getProjectKey().get());
-    add(extensionPanelBottom);
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-
-    Project.NameKey project = getProjectKey();
-    CallbackGroup cbg = new CallbackGroup();
-    AccessMap.get(
-        project,
-        cbg.add(
-            new GerritCallback<ProjectAccessInfo>() {
-              @Override
-              public void onSuccess(ProjectAccessInfo result) {
-                isOwner = result.isOwner();
-                configVisible = result.configVisible();
-                enableForm();
-                saveProject.setVisible(isOwner);
-              }
-            }));
-    ProjectApi.getConfig(
-        project,
-        cbg.addFinal(
-            new ScreenLoadCallback<ConfigInfo>(this) {
-              @Override
-              public void preDisplay(ConfigInfo result) {
-                display(result);
-              }
-            }));
-
-    savedPanel = INFO;
-  }
-
-  private void enableForm() {
-    enableForm(isOwner);
-  }
-
-  private void enableForm(boolean isOwner) {
-    state.setEnabled(isOwner);
-    submitType.setEnabled(isOwner);
-    setEnabledForUseContentMerge();
-    newChangeForAllNotInTarget.setEnabled(isOwner);
-    if (enableSignedPush != null) {
-      enableSignedPush.setEnabled(isOwner);
-    }
-    if (requireSignedPush != null) {
-      requireSignedPush.setEnabled(isOwner);
-    }
-    descTxt.setEnabled(isOwner);
-    contributorAgreements.setEnabled(isOwner);
-    signedOffBy.setEnabled(isOwner);
-    requireChangeID.setEnabled(isOwner);
-    rejectImplicitMerges.setEnabled(isOwner);
-    privateByDefault.setEnabled(isOwner);
-    workInProgressByDefault.setEnabled(isOwner);
-    maxObjectSizeLimit.setEnabled(isOwner);
-    enableReviewerByEmail.setEnabled(isOwner);
-    matchAuthorToCommitterDate.setEnabled(isOwner);
-
-    if (pluginConfigWidgets != null) {
-      for (Map<String, HasEnabled> widgetMap : pluginConfigWidgets.values()) {
-        for (HasEnabled widget : widgetMap.values()) {
-          widget.setEnabled(isOwner);
-        }
-      }
-    }
-  }
-
-  private void initDescription() {
-    final VerticalPanel vp = new VerticalPanel();
-    vp.add(new SmallHeading(AdminConstants.I.headingDescription()));
-
-    descTxt = new NpTextArea();
-    descTxt.setVisibleLines(6);
-    descTxt.setCharacterWidth(60);
-    vp.add(descTxt);
-
-    add(vp);
-    saveEnabler = new OnEditEnabler(saveProject);
-    saveEnabler.listenTo(descTxt);
-  }
-
-  private void initProjectOptions() {
-    grid.addHeader(new SmallHeading(AdminConstants.I.headingProjectOptions()));
-
-    state = new ListBox();
-    for (ProjectState stateValue : ProjectState.values()) {
-      state.addItem(Util.toLongString(stateValue), stateValue.name());
-    }
-    saveEnabler.listenTo(state);
-    grid.add(AdminConstants.I.headingProjectState(), state);
-
-    submitType = new ListBox();
-    for (SubmitType type : SubmitType.values()) {
-      submitType.addItem(Util.toLongString(type), type.name());
-    }
-    submitType.addChangeHandler(
-        new ChangeHandler() {
-          @Override
-          public void onChange(ChangeEvent event) {
-            setEnabledForUseContentMerge();
-          }
-        });
-    saveEnabler.listenTo(submitType);
-    grid.add(AdminConstants.I.headingProjectSubmitType(), submitType);
-
-    contentMerge = newInheritedBooleanBox();
-    saveEnabler.listenTo(contentMerge);
-    grid.add(AdminConstants.I.useContentMerge(), contentMerge);
-
-    newChangeForAllNotInTarget = newInheritedBooleanBox();
-    saveEnabler.listenTo(newChangeForAllNotInTarget);
-    grid.add(AdminConstants.I.createNewChangeForAllNotInTarget(), newChangeForAllNotInTarget);
-
-    requireChangeID = newInheritedBooleanBox();
-    saveEnabler.listenTo(requireChangeID);
-    grid.addHtml(AdminConstants.I.requireChangeID(), requireChangeID);
-
-    if (Gerrit.info().receive().enableSignedPush()) {
-      enableSignedPush = newInheritedBooleanBox();
-      saveEnabler.listenTo(enableSignedPush);
-      grid.add(AdminConstants.I.enableSignedPush(), enableSignedPush);
-      requireSignedPush = newInheritedBooleanBox();
-      saveEnabler.listenTo(requireSignedPush);
-      grid.add(AdminConstants.I.requireSignedPush(), requireSignedPush);
-    }
-
-    rejectImplicitMerges = newInheritedBooleanBox();
-    saveEnabler.listenTo(rejectImplicitMerges);
-    grid.addHtml(AdminConstants.I.rejectImplicitMerges(), rejectImplicitMerges);
-
-    privateByDefault = newInheritedBooleanBox();
-    saveEnabler.listenTo(privateByDefault);
-    grid.addHtml(AdminConstants.I.privateByDefault(), privateByDefault);
-
-    workInProgressByDefault = newInheritedBooleanBox();
-    saveEnabler.listenTo(workInProgressByDefault);
-    grid.addHtml(AdminConstants.I.workInProgressByDefault(), workInProgressByDefault);
-
-    enableReviewerByEmail = newInheritedBooleanBox();
-    saveEnabler.listenTo(enableReviewerByEmail);
-    grid.addHtml(AdminConstants.I.enableReviewerByEmail(), enableReviewerByEmail);
-
-    matchAuthorToCommitterDate = newInheritedBooleanBox();
-    saveEnabler.listenTo(matchAuthorToCommitterDate);
-    grid.addHtml(AdminConstants.I.matchAuthorToCommitterDate(), matchAuthorToCommitterDate);
-
-    maxObjectSizeLimit = new NpTextBox();
-    saveEnabler.listenTo(maxObjectSizeLimit);
-    effectiveMaxObjectSizeLimit = new Label();
-    effectiveMaxObjectSizeLimit.setStyleName(
-        Gerrit.RESOURCES.css().maxObjectSizeLimitEffectiveLabel());
-    HorizontalPanel p = new HorizontalPanel();
-    p.add(maxObjectSizeLimit);
-    p.add(effectiveMaxObjectSizeLimit);
-    grid.addHtml(AdminConstants.I.headingMaxObjectSizeLimit(), p);
-  }
-
-  private static ListBox newInheritedBooleanBox() {
-    ListBox box = new ListBox();
-    for (InheritableBoolean b : InheritableBoolean.values()) {
-      box.addItem(b.name(), b.name());
-    }
-    return box;
-  }
-
-  /**
-   * Enables the {@link #contentMerge} checkbox if the selected submit type allows the usage of
-   * content merge. If the submit type (currently only 'Fast Forward Only') does not allow content
-   * merge the useContentMerge checkbox gets disabled.
-   */
-  private void setEnabledForUseContentMerge() {
-    if (SubmitType.FAST_FORWARD_ONLY.equals(
-        SubmitType.valueOf(submitType.getValue(submitType.getSelectedIndex())))) {
-      contentMerge.setEnabled(false);
-      InheritedBooleanInfo b = InheritedBooleanInfo.create();
-      b.setConfiguredValue(InheritableBoolean.FALSE);
-      setBool(contentMerge, b);
-    } else {
-      contentMerge.setEnabled(submitType.isEnabled());
-    }
-  }
-
-  private void initAgreements() {
-    grid.addHeader(new SmallHeading(AdminConstants.I.headingAgreements()));
-
-    contributorAgreements = newInheritedBooleanBox();
-    if (Gerrit.info().auth().useContributorAgreements()) {
-      saveEnabler.listenTo(contributorAgreements);
-      grid.add(AdminConstants.I.useContributorAgreements(), contributorAgreements);
-    }
-
-    signedOffBy = newInheritedBooleanBox();
-    saveEnabler.listenTo(signedOffBy);
-    grid.addHtml(AdminConstants.I.useSignedOffBy(), signedOffBy);
-  }
-
-  private void setSubmitType(SubmitTypeInfo newSubmitType) {
-    int index = -1;
-    if (newSubmitType != null) {
-      for (int i = 0; i < submitType.getItemCount(); i++) {
-        if (submitType.getValue(i).equals(SubmitType.INHERIT.name())) {
-          submitType.setItemText(i, getInheritString(newSubmitType));
-        }
-        if (newSubmitType.configuredValue().name().equals(submitType.getValue(i))) {
-          index = i;
-        }
-      }
-      submitType.setSelectedIndex(index);
-      setEnabledForUseContentMerge();
-    }
-  }
-
-  private static String getInheritString(SubmitTypeInfo submitType) {
-    return Util.toLongString(SubmitType.INHERIT)
-        + " ("
-        + Util.toLongString(submitType.inheritedValue())
-        + ")";
-  }
-
-  private void setState(ProjectState newState) {
-    if (state != null) {
-      for (int i = 0; i < state.getItemCount(); i++) {
-        if (newState.name().equals(state.getValue(i))) {
-          state.setSelectedIndex(i);
-          break;
-        }
-      }
-    }
-  }
-
-  private void setBool(ListBox box, InheritedBooleanInfo inheritedBoolean) {
-    if (box == null) {
-      return;
-    }
-    int inheritedIndex = -1;
-    for (int i = 0; i < box.getItemCount(); i++) {
-      if (box.getValue(i).startsWith(InheritableBoolean.INHERIT.name())) {
-        inheritedIndex = i;
-      }
-      if (box.getValue(i).startsWith(inheritedBoolean.configuredValue().name())) {
-        box.setSelectedIndex(i);
-      }
-    }
-    if (inheritedIndex >= 0) {
-      if (Gerrit.info().gerrit().isAllProjects(getProjectKey())) {
-        if (box.getSelectedIndex() == inheritedIndex) {
-          for (int i = 0; i < box.getItemCount(); i++) {
-            if (box.getValue(i).equals(InheritableBoolean.FALSE.name())) {
-              box.setSelectedIndex(i);
-              break;
-            }
-          }
-        }
-        box.removeItem(inheritedIndex);
-      } else {
-        box.setItemText(
-            inheritedIndex,
-            InheritableBoolean.INHERIT.name() + " (" + inheritedBoolean.inheritedValue() + ")");
-      }
-    }
-  }
-
-  private static InheritableBoolean getBool(ListBox box) {
-    int i = box.getSelectedIndex();
-    if (i >= 0) {
-      final String selectedValue = box.getValue(i);
-      if (selectedValue.startsWith(InheritableBoolean.INHERIT.name())) {
-        return InheritableBoolean.INHERIT;
-      }
-      return InheritableBoolean.valueOf(selectedValue);
-    }
-    return InheritableBoolean.INHERIT;
-  }
-
-  void display(ConfigInfo result) {
-    descTxt.setText(result.description());
-    setBool(contributorAgreements, result.useContributorAgreements());
-    setBool(signedOffBy, result.useSignedOffBy());
-    setBool(contentMerge, result.useContentMerge());
-    setBool(newChangeForAllNotInTarget, result.createNewChangeForAllNotInTarget());
-    setBool(requireChangeID, result.requireChangeId());
-    if (Gerrit.info().receive().enableSignedPush()) {
-      setBool(enableSignedPush, result.enableSignedPush());
-      setBool(requireSignedPush, result.requireSignedPush());
-    }
-    setBool(rejectImplicitMerges, result.rejectImplicitMerges());
-    setBool(privateByDefault, result.privateByDefault());
-    setBool(workInProgressByDefault, result.workInProgressByDefault());
-    setBool(enableReviewerByEmail, result.enableReviewerByEmail());
-    setBool(matchAuthorToCommitterDate, result.matchAuthorToCommitterDate());
-    setSubmitType(result.defaultSubmitType());
-    setState(result.state());
-    maxObjectSizeLimit.setText(result.maxObjectSizeLimit().configuredValue());
-    if (result.maxObjectSizeLimit().value() != null) {
-      effectiveMaxObjectSizeLimit.setText(
-          AdminMessages.I.effectiveMaxObjectSizeLimit(result.maxObjectSizeLimit().value()));
-      if (result.maxObjectSizeLimit().summary() != null) {
-        effectiveMaxObjectSizeLimit.setTitle(result.maxObjectSizeLimit().summary());
-      }
-    } else {
-      effectiveMaxObjectSizeLimit.setText(AdminMessages.I.noMaxObjectSizeLimit());
-    }
-
-    saveProject.setEnabled(false);
-    initPluginOptions(result);
-    initProjectActions(result);
-  }
-
-  private void initPluginOptions(ConfigInfo info) {
-    pluginOptionsPanel.clear();
-    pluginConfigWidgets = new HashMap<>();
-
-    for (String pluginName : info.pluginConfig().keySet()) {
-      Map<String, HasEnabled> widgetMap = new HashMap<>();
-      pluginConfigWidgets.put(pluginName, widgetMap);
-      LabeledWidgetsGrid g = new LabeledWidgetsGrid();
-      g.addHeader(new SmallHeading(AdminMessages.I.pluginProjectOptionsTitle(pluginName)));
-      pluginOptionsPanel.add(g);
-      NativeMap<ConfigParameterInfo> pluginConfig = info.pluginConfig(pluginName);
-      pluginConfig.copyKeysIntoChildren("name");
-      for (ConfigParameterInfo param : Natives.asList(pluginConfig.values())) {
-        HasEnabled w;
-        switch (param.type()) {
-          case "STRING":
-          case "INT":
-          case "LONG":
-            w = renderTextBox(g, param);
-            break;
-          case "BOOLEAN":
-            w = renderCheckBox(g, param);
-            break;
-          case "LIST":
-            w = renderListBox(g, param);
-            break;
-          case "ARRAY":
-            w = renderStringListPanel(g, param);
-            break;
-          default:
-            throw new UnsupportedOperationException("unsupported widget type");
-        }
-        if (param.editable()) {
-          widgetMap.put(param.name(), w);
-        } else {
-          w.setEnabled(false);
-        }
-      }
-    }
-
-    enableForm();
-  }
-
-  private TextBox renderTextBox(LabeledWidgetsGrid g, ConfigParameterInfo param) {
-    NpTextBox textBox = param.type().equals("STRING") ? new NpTextBox() : new NpIntTextBox();
-    if (param.inheritable()) {
-      textBox.setValue(param.configuredValue());
-      Label inheritedLabel =
-          new Label(AdminMessages.I.pluginProjectInheritedValue(param.inheritedValue()));
-      inheritedLabel.setStyleName(Gerrit.RESOURCES.css().pluginProjectConfigInheritedValue());
-      HorizontalPanel p = new HorizontalPanel();
-      p.add(textBox);
-      p.add(inheritedLabel);
-      addWidget(g, p, param);
-    } else {
-      textBox.setValue(param.value());
-      addWidget(g, textBox, param);
-    }
-    if (textBox.getValue().length() > textBox.getVisibleLength()) {
-      textBox.setVisibleLength(textBox.getValue().length());
-    }
-    saveEnabler.listenTo(textBox);
-    return textBox;
-  }
-
-  private CheckBox renderCheckBox(LabeledWidgetsGrid g, ConfigParameterInfo param) {
-    CheckBox checkBox = new CheckBox(getDisplayName(param));
-    checkBox.setValue(Boolean.parseBoolean(param.value()));
-    HorizontalPanel p = new HorizontalPanel();
-    p.add(checkBox);
-    if (param.description() != null) {
-      Image infoImg = new Image(Gerrit.RESOURCES.info());
-      infoImg.setTitle(param.description());
-      p.add(infoImg);
-    }
-    if (param.warning() != null) {
-      Image warningImg = new Image(Gerrit.RESOURCES.warning());
-      warningImg.setTitle(param.warning());
-      p.add(warningImg);
-    }
-    g.add((String) null, p);
-    saveEnabler.listenTo(checkBox);
-    return checkBox;
-  }
-
-  private ListBox renderListBox(LabeledWidgetsGrid g, ConfigParameterInfo param) {
-    if (param.permittedValues() == null) {
-      return null;
-    }
-    ListBox listBox = new ListBox();
-    if (param.inheritable()) {
-      listBox.addItem(AdminMessages.I.pluginProjectInheritedListValue(param.inheritedValue()));
-      if (param.configuredValue() == null) {
-        listBox.setSelectedIndex(0);
-      }
-      for (int i = 0; i < param.permittedValues().length(); i++) {
-        String pv = param.permittedValues().get(i);
-        listBox.addItem(pv);
-        if (pv.equals(param.configuredValue())) {
-          listBox.setSelectedIndex(i + 1);
-        }
-      }
-    } else {
-      for (int i = 0; i < param.permittedValues().length(); i++) {
-        String pv = param.permittedValues().get(i);
-        listBox.addItem(pv);
-        if (pv.equals(param.value())) {
-          listBox.setSelectedIndex(i);
-        }
-      }
-    }
-
-    if (param.editable()) {
-      saveEnabler.listenTo(listBox);
-      addWidget(g, listBox, param);
-    } else {
-      listBox.setEnabled(false);
-
-      if (param.inheritable() && listBox.getSelectedIndex() != 0) {
-        // the inherited value is not selected,
-        // since the listBox is disabled the inherited value cannot be
-        // seen and we have to display it explicitly
-        Label inheritedLabel =
-            new Label(AdminMessages.I.pluginProjectInheritedValue(param.inheritedValue()));
-        inheritedLabel.setStyleName(Gerrit.RESOURCES.css().pluginProjectConfigInheritedValue());
-        HorizontalPanel p = new HorizontalPanel();
-        p.add(listBox);
-        p.add(inheritedLabel);
-        addWidget(g, p, param);
-      } else {
-        addWidget(g, listBox, param);
-      }
-    }
-
-    return listBox;
-  }
-
-  private StringListPanel renderStringListPanel(LabeledWidgetsGrid g, ConfigParameterInfo param) {
-    StringListPanel p =
-        new StringListPanel(null, Arrays.asList(getDisplayName(param)), saveProject, false);
-    List<List<String>> values = new ArrayList<>();
-    for (String v : Natives.asList(param.values())) {
-      values.add(Arrays.asList(v));
-    }
-    p.display(values);
-    if (!param.editable()) {
-      p.setEnabled(false);
-    }
-    addWidget(g, p, param);
-    return p;
-  }
-
-  private void addWidget(LabeledWidgetsGrid g, Widget w, ConfigParameterInfo param) {
-    if (param.description() != null || param.warning() != null) {
-      HorizontalPanel p = new HorizontalPanel();
-      p.add(new Label(getDisplayName(param)));
-      if (param.description() != null) {
-        Image infoImg = new Image(Gerrit.RESOURCES.info());
-        infoImg.setTitle(param.description());
-        p.add(infoImg);
-      }
-      if (param.warning() != null) {
-        Image warningImg = new Image(Gerrit.RESOURCES.warning());
-        warningImg.setTitle(param.warning());
-        p.add(warningImg);
-      }
-      p.add(new Label(":"));
-      g.add(p, w);
-    } else {
-      g.add(getDisplayName(param), w);
-    }
-  }
-
-  private String getDisplayName(ConfigParameterInfo param) {
-    return param.displayName() != null ? param.displayName() : param.name();
-  }
-
-  private void initProjectActions(ConfigInfo info) {
-    actionsGrid.clear(true);
-    actionsGrid.removeAllRows();
-    boolean showCreateChange = Gerrit.isSignedIn();
-
-    NativeMap<ActionInfo> actions = info.actions();
-    if (actions == null) {
-      actions = NativeMap.create().cast();
-    }
-    if (actions.isEmpty() && !showCreateChange) {
-      return;
-    }
-    actions.copyKeysIntoChildren("id");
-    actionsGrid.addHeader(new SmallHeading(AdminConstants.I.headingProjectCommands()));
-    FlowPanel actionsPanel = new FlowPanel();
-    actionsPanel.setStyleName(Gerrit.RESOURCES.css().projectActions());
-    actionsPanel.setVisible(true);
-    actionsGrid.add(AdminConstants.I.headingCommands(), actionsPanel);
-
-    for (String id : actions.keySet()) {
-      actionsPanel.add(new ActionButton(getProjectKey(), actions.get(id)));
-    }
-
-    // TODO: The user should have create permission on the branch referred to by
-    // HEAD. This would have to happen on the server side.
-    if (showCreateChange) {
-      actionsPanel.add(createChangeAction());
-    }
-
-    if (isOwner && configVisible) {
-      actionsPanel.add(createEditConfigAction());
-    }
-  }
-
-  private Button createChangeAction() {
-    final Button createChange = new Button(AdminConstants.I.buttonCreateChange());
-    createChange.setStyleName("");
-    createChange.setTitle(AdminConstants.I.buttonCreateChangeDescription());
-    createChange.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            CreateChangeAction.call(createChange, getProjectKey().get());
-          }
-        });
-    return createChange;
-  }
-
-  private Button createEditConfigAction() {
-    final Button editConfig = new Button(AdminConstants.I.buttonEditConfig());
-    editConfig.setStyleName("");
-    editConfig.setTitle(AdminConstants.I.buttonEditConfigDescription());
-    editConfig.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            EditConfigAction.call(editConfig, getProjectKey());
-          }
-        });
-    return editConfig;
-  }
-
-  private void doSave() {
-    enableForm(false);
-    saveProject.setEnabled(false);
-    InheritableBoolean esp = enableSignedPush != null ? getBool(enableSignedPush) : null;
-    InheritableBoolean rsp = requireSignedPush != null ? getBool(requireSignedPush) : null;
-    ProjectApi.setConfig(
-        getProjectKey(),
-        descTxt.getText().trim(),
-        getBool(contributorAgreements),
-        getBool(contentMerge),
-        getBool(signedOffBy),
-        getBool(newChangeForAllNotInTarget),
-        getBool(requireChangeID),
-        esp,
-        rsp,
-        getBool(rejectImplicitMerges),
-        getBool(privateByDefault),
-        getBool(workInProgressByDefault),
-        getBool(enableReviewerByEmail),
-        getBool(matchAuthorToCommitterDate),
-        maxObjectSizeLimit.getText().trim(),
-        SubmitType.valueOf(submitType.getValue(submitType.getSelectedIndex())),
-        ProjectState.valueOf(state.getValue(state.getSelectedIndex())),
-        getPluginConfigValues(),
-        new GerritCallback<ConfigInfo>() {
-          @Override
-          public void onSuccess(ConfigInfo result) {
-            enableForm();
-            display(result);
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            enableForm();
-            super.onFailure(caught);
-          }
-        });
-  }
-
-  private Map<String, Map<String, ConfigParameterValue>> getPluginConfigValues() {
-    Map<String, Map<String, ConfigParameterValue>> pluginConfigValues =
-        new HashMap<>(pluginConfigWidgets.size());
-    for (Entry<String, Map<String, HasEnabled>> e : pluginConfigWidgets.entrySet()) {
-      Map<String, ConfigParameterValue> values = new HashMap<>(e.getValue().size());
-      pluginConfigValues.put(e.getKey(), values);
-      for (Entry<String, HasEnabled> e2 : e.getValue().entrySet()) {
-        HasEnabled widget = e2.getValue();
-        if (widget instanceof TextBox) {
-          values.put(
-              e2.getKey(),
-              ConfigParameterValue.create().value(((TextBox) widget).getValue().trim()));
-        } else if (widget instanceof CheckBox) {
-          values.put(
-              e2.getKey(),
-              ConfigParameterValue.create()
-                  .value(Boolean.toString(((CheckBox) widget).getValue())));
-        } else if (widget instanceof ListBox) {
-          ListBox listBox = (ListBox) widget;
-          // the inherited value is at index 0,
-          // if it is selected no value should be set on this project
-          String value =
-              listBox.getSelectedIndex() > 0 ? listBox.getValue(listBox.getSelectedIndex()) : null;
-          values.put(e2.getKey(), ConfigParameterValue.create().value(value));
-        } else if (widget instanceof StringListPanel) {
-          values.put(
-              e2.getKey(),
-              ConfigParameterValue.create()
-                  .values(((StringListPanel) widget).getValues(0).toArray(new String[] {})));
-        } else {
-          throw new UnsupportedOperationException("unsupported widget type");
-        }
-      }
-    }
-    return pluginConfigValues;
-  }
-
-  public static class ProjectDownloadPanel extends DownloadPanel {
-    public ProjectDownloadPanel(String project, boolean isAllowsAnonymous) {
-      super(project, isAllowsAnonymous);
-    }
-
-    @Override
-    protected List<DownloadCommandInfo> getCommands(DownloadSchemeInfo schemeInfo) {
-      return schemeInfo.cloneCommands(project);
-    }
-  }
-
-  private static class LabeledWidgetsGrid extends FlexTable {
-    private String labelSuffix;
-
-    LabeledWidgetsGrid() {
-      super();
-      labelSuffix = ":";
-    }
-
-    private void addHeader(Widget widget) {
-      int row = getRowCount();
-      insertRow(row);
-      setWidget(row, 0, widget);
-      getCellFormatter().getElement(row, 0).setAttribute("colSpan", "2");
-    }
-
-    private void add(String label, boolean labelIsHtml, Widget widget) {
-      int row = getRowCount();
-      insertRow(row);
-      if (label != null) {
-        if (labelIsHtml) {
-          setHTML(row, 0, label + labelSuffix);
-        } else {
-          setText(row, 0, label + labelSuffix);
-        }
-      }
-      setWidget(row, 1, widget);
-    }
-
-    public void add(String label, Widget widget) {
-      add(label, false, widget);
-    }
-
-    public void addHtml(String label, Widget widget) {
-      add(label, true, widget);
-    }
-
-    public void add(Widget label, Widget widget) {
-      int row = getRowCount();
-      insertRow(row);
-      setWidget(row, 0, label);
-      setWidget(row, 1, widget);
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java
deleted file mode 100644
index 2a03136..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java
+++ /dev/null
@@ -1,259 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import static com.google.gerrit.common.PageLinks.ADMIN_PROJECTS;
-
-import com.google.gerrit.client.Dispatcher;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.info.WebLinkInfo;
-import com.google.gerrit.client.projects.ProjectInfo;
-import com.google.gerrit.client.projects.ProjectMap;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.HighlightingInlineHyperlink;
-import com.google.gerrit.client.ui.Hyperlink;
-import com.google.gerrit.client.ui.PagingHyperlink;
-import com.google.gerrit.client.ui.ProjectSearchLink;
-import com.google.gerrit.client.ui.ProjectsTable;
-import com.google.gerrit.common.PageLinks;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyUpEvent;
-import com.google.gwt.event.dom.client.KeyUpHandler;
-import com.google.gwt.user.client.History;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwtexpui.globalkey.client.NpTextBox;
-import java.util.List;
-
-public class ProjectListScreen extends PaginatedProjectScreen {
-  private Hyperlink prev;
-  private Hyperlink next;
-  private ProjectsTable projects;
-  private NpTextBox filterTxt;
-
-  private Query query;
-
-  public ProjectListScreen() {
-    super(null);
-  }
-
-  public ProjectListScreen(String params) {
-    this();
-    parseToken(params);
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    query = new Query(match).start(start).run();
-  }
-
-  @Override
-  public String getScreenToken() {
-    return ADMIN_PROJECTS;
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    setPageTitle(AdminConstants.I.projectListTitle());
-    initPageHeader();
-
-    prev = PagingHyperlink.createPrev();
-    prev.setVisible(false);
-
-    next = PagingHyperlink.createNext();
-    next.setVisible(false);
-
-    projects =
-        new ProjectsTable() {
-          @Override
-          protected void initColumnHeaders() {
-            super.initColumnHeaders();
-            table.setText(0, ProjectsTable.C_REPO_BROWSER, AdminConstants.I.projectRepoBrowser());
-            table
-                .getFlexCellFormatter()
-                .addStyleName(0, ProjectsTable.C_REPO_BROWSER, Gerrit.RESOURCES.css().dataHeader());
-          }
-
-          @Override
-          protected void onOpenRow(int row) {
-            History.newItem(link(getRowItem(row)));
-          }
-
-          private String link(ProjectInfo item) {
-            return Dispatcher.toProject(item.name_key());
-          }
-
-          @Override
-          protected void insert(int row, ProjectInfo k) {
-            super.insert(row, k);
-            table
-                .getFlexCellFormatter()
-                .addStyleName(row, ProjectsTable.C_REPO_BROWSER, Gerrit.RESOURCES.css().dataCell());
-          }
-
-          @Override
-          protected void populate(int row, ProjectInfo k) {
-            populateState(row, k);
-            FlowPanel fp = new FlowPanel();
-            fp.add(new ProjectSearchLink(k.name_key()));
-            fp.add(new HighlightingInlineHyperlink(k.name(), link(k), match));
-            table.setWidget(row, ProjectsTable.C_NAME, fp);
-            table.setText(row, ProjectsTable.C_DESCRIPTION, k.description());
-            addWebLinks(row, k);
-
-            setRowItem(row, k);
-          }
-
-          private void addWebLinks(int row, ProjectInfo k) {
-            List<WebLinkInfo> webLinks = Natives.asList(k.webLinks());
-            if (webLinks != null && !webLinks.isEmpty()) {
-              FlowPanel p = new FlowPanel();
-              table.setWidget(row, ProjectsTable.C_REPO_BROWSER, p);
-              for (WebLinkInfo weblink : webLinks) {
-                p.add(weblink.toAnchor());
-              }
-            }
-          }
-        };
-    projects.setSavePointerId(PageLinks.ADMIN_PROJECTS);
-
-    add(projects);
-    final HorizontalPanel buttons = new HorizontalPanel();
-    buttons.setStyleName(Gerrit.RESOURCES.css().changeTablePrevNextLinks());
-    buttons.add(prev);
-    buttons.add(next);
-    add(buttons);
-  }
-
-  private void initPageHeader() {
-    final HorizontalPanel hp = new HorizontalPanel();
-    hp.setStyleName(Gerrit.RESOURCES.css().projectFilterPanel());
-    final Label filterLabel = new Label(AdminConstants.I.projectFilter());
-    filterLabel.setStyleName(Gerrit.RESOURCES.css().projectFilterLabel());
-    hp.add(filterLabel);
-    filterTxt = new NpTextBox();
-    filterTxt.setValue(match);
-    filterTxt.addKeyUpHandler(
-        new KeyUpHandler() {
-          @Override
-          public void onKeyUp(KeyUpEvent event) {
-            Query q =
-                new Query(filterTxt.getValue())
-                    .open(event.getNativeKeyCode() == KeyCodes.KEY_ENTER);
-            if (match.equals(q.qMatch)) {
-              q.start(start);
-            }
-            if (q.open || !match.equals(q.qMatch)) {
-              if (query == null) {
-                q.run();
-              }
-              query = q;
-            }
-          }
-        });
-    hp.add(filterTxt);
-    add(hp);
-  }
-
-  @Override
-  public void onShowView() {
-    super.onShowView();
-    if (match != null) {
-      filterTxt.setCursorPos(match.length());
-    }
-    filterTxt.setFocus(true);
-  }
-
-  @Override
-  public void registerKeys() {
-    super.registerKeys();
-    projects.setRegisterKeys(true);
-  }
-
-  private class Query {
-    private final String qMatch;
-    private int qStart;
-    private boolean open;
-
-    Query(String match) {
-      this.qMatch = match;
-    }
-
-    Query start(int start) {
-      this.qStart = start;
-      return this;
-    }
-
-    Query open(boolean open) {
-      this.open = open;
-      return this;
-    }
-
-    Query run() {
-      int limit = open ? 1 : pageSize + 1;
-      ProjectMap.match(
-          qMatch,
-          limit,
-          qStart,
-          new GerritCallback<ProjectMap>() {
-            @Override
-            public void onSuccess(ProjectMap result) {
-              if (!isAttached()) {
-                // View has been disposed.
-              } else if (query == Query.this) {
-                query = null;
-                showMap(result);
-              } else {
-                query.run();
-              }
-            }
-          });
-      return this;
-    }
-
-    private void showMap(ProjectMap result) {
-      if (open && !result.isEmpty()) {
-        Gerrit.display(PageLinks.toProject(result.values().get(0).name_key()));
-        return;
-      }
-
-      setToken(getTokenForScreen(qMatch, qStart));
-      ProjectListScreen.this.match = qMatch;
-      ProjectListScreen.this.start = qStart;
-
-      if (result.size() <= pageSize) {
-        projects.display(result);
-        next.setVisible(false);
-      } else {
-        projects.displaySubset(result, 0, result.size() - 1);
-        setupNavigationLink(next, qMatch, qStart + pageSize);
-      }
-
-      if (qStart > 0) {
-        setupNavigationLink(prev, qMatch, qStart - pageSize);
-      } else {
-        prev.setVisible(false);
-      }
-
-      if (!isCurrentView()) {
-        display();
-      }
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectScreen.java
deleted file mode 100644
index dc964b8..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectScreen.java
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import com.google.gerrit.client.ui.Screen;
-import com.google.gerrit.reviewdb.client.Project;
-
-public abstract class ProjectScreen extends Screen {
-  public static final String INFO = "info";
-  public static final String BRANCHES = "branches";
-  public static final String ACCESS = "access";
-  public static final String DASHBOARDS = "dashboards";
-  public static final String TAGS = "tags";
-
-  protected static String savedPanel;
-  protected static Project.NameKey savedKey;
-
-  public static String getSavedPanel() {
-    return savedPanel;
-  }
-
-  public static Project.NameKey getSavedKey() {
-    return savedKey;
-  }
-
-  private final Project.NameKey name;
-
-  public ProjectScreen(Project.NameKey toShow) {
-    name = toShow;
-  }
-
-  public Project.NameKey getProjectKey() {
-    return name;
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    if (name != null) {
-      setPageTitle(AdminMessages.I.project(name.get()));
-    }
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    savedKey = name;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectTagsScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectTagsScreen.java
deleted file mode 100644
index 22c331d..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectTagsScreen.java
+++ /dev/null
@@ -1,571 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import static com.google.gerrit.client.ui.Util.highlight;
-
-import com.google.gerrit.client.ConfirmationCallback;
-import com.google.gerrit.client.ConfirmationDialog;
-import com.google.gerrit.client.ErrorDialog;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.VoidResult;
-import com.google.gerrit.client.access.AccessMap;
-import com.google.gerrit.client.access.ProjectAccessInfo;
-import com.google.gerrit.client.info.WebLinkInfo;
-import com.google.gerrit.client.projects.ProjectApi;
-import com.google.gerrit.client.projects.TagInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gerrit.client.ui.HintTextBox;
-import com.google.gerrit.client.ui.Hyperlink;
-import com.google.gerrit.client.ui.NavigationTable;
-import com.google.gerrit.client.ui.PagingHyperlink;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.event.dom.client.KeyUpEvent;
-import com.google.gwt.event.dom.client.KeyUpHandler;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.logical.shared.ValueChangeHandler;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.InlineHTML;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.globalkey.client.NpTextBox;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-public class ProjectTagsScreen extends PaginatedProjectScreen {
-  private Hyperlink prev;
-  private Hyperlink next;
-  private TagsTable tagTable;
-  private Button delTag;
-  private Button addTag;
-  private HintTextBox nameTxtBox;
-  private HintTextBox irevTxtBox;
-  private HintTextBox annotationTxtBox;
-  private FlowPanel addPanel;
-  private NpTextBox filterTxt;
-  private Query query;
-
-  public ProjectTagsScreen(Project.NameKey toShow) {
-    super(toShow);
-  }
-
-  @Override
-  public String getScreenToken() {
-    return PageLinks.toProjectTags(getProjectKey());
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    addPanel.setVisible(false);
-    AccessMap.get(
-        getProjectKey(),
-        new GerritCallback<ProjectAccessInfo>() {
-          @Override
-          public void onSuccess(ProjectAccessInfo result) {
-            addPanel.setVisible(result.canAddTagRefs());
-          }
-        });
-    query = new Query(match).start(start).run();
-    savedPanel = TAGS;
-  }
-
-  private void updateForm() {
-    tagTable.updateDeleteButton();
-    addTag.setEnabled(true);
-    nameTxtBox.setEnabled(true);
-    irevTxtBox.setEnabled(true);
-    annotationTxtBox.setEnabled(true);
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    initPageHeader();
-
-    prev = PagingHyperlink.createPrev();
-    prev.setVisible(false);
-
-    next = PagingHyperlink.createNext();
-    next.setVisible(false);
-
-    addPanel = new FlowPanel();
-
-    Grid addGrid = new Grid(3, 2);
-    addGrid.setStyleName(Gerrit.RESOURCES.css().addBranch());
-    int texBoxLength = 50;
-
-    KeyPressHandler onKeyPress =
-        new KeyPressHandler() {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
-              doAddNewTag();
-            }
-          }
-        };
-
-    nameTxtBox = new HintTextBox();
-    nameTxtBox.setVisibleLength(texBoxLength);
-    nameTxtBox.setHintText(AdminConstants.I.defaultTagName());
-    nameTxtBox.addKeyPressHandler(onKeyPress);
-    addGrid.setText(0, 0, AdminConstants.I.columnTagName() + ":");
-    addGrid.setWidget(0, 1, nameTxtBox);
-
-    irevTxtBox = new HintTextBox();
-    irevTxtBox.setVisibleLength(texBoxLength);
-    irevTxtBox.setHintText(AdminConstants.I.defaultRevisionSpec());
-    irevTxtBox.addKeyPressHandler(onKeyPress);
-    addGrid.setText(1, 0, AdminConstants.I.revision() + ":");
-    addGrid.setWidget(1, 1, irevTxtBox);
-
-    annotationTxtBox = new HintTextBox();
-    annotationTxtBox.setVisibleLength(texBoxLength);
-    annotationTxtBox.setHintText(AdminConstants.I.annotation());
-    annotationTxtBox.addKeyPressHandler(onKeyPress);
-    addGrid.setText(2, 0, AdminConstants.I.columnTagAnnotation() + ":");
-    addGrid.setWidget(2, 1, annotationTxtBox);
-
-    addTag = new Button(AdminConstants.I.buttonAddTag());
-    addTag.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            doAddNewTag();
-          }
-        });
-    addPanel.add(addGrid);
-    addPanel.add(addTag);
-
-    tagTable = new TagsTable();
-
-    delTag = new Button(AdminConstants.I.buttonDeleteTag());
-    delTag.setStyleName(Gerrit.RESOURCES.css().branchTableDeleteButton());
-    delTag.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            tagTable.deleteChecked();
-          }
-        });
-
-    HorizontalPanel buttons = new HorizontalPanel();
-    buttons.setStyleName(Gerrit.RESOURCES.css().branchTablePrevNextLinks());
-    buttons.add(delTag);
-    buttons.add(prev);
-    buttons.add(next);
-    add(tagTable);
-    add(buttons);
-    add(addPanel);
-  }
-
-  private void initPageHeader() {
-    parseToken();
-    HorizontalPanel hp = new HorizontalPanel();
-    hp.setStyleName(Gerrit.RESOURCES.css().projectFilterPanel());
-    Label filterLabel = new Label(AdminConstants.I.projectFilter());
-    filterLabel.setStyleName(Gerrit.RESOURCES.css().projectFilterLabel());
-    hp.add(filterLabel);
-    filterTxt = new NpTextBox();
-    filterTxt.setValue(match);
-    filterTxt.addKeyUpHandler(
-        new KeyUpHandler() {
-          @Override
-          public void onKeyUp(KeyUpEvent event) {
-            Query q = new Query(filterTxt.getValue());
-            if (match.equals(q.qMatch)) {
-              q.start(start);
-            } else {
-              if (query == null) {
-                q.run();
-              }
-              query = q;
-            }
-          }
-        });
-    hp.add(filterTxt);
-    add(hp);
-  }
-
-  private void doAddNewTag() {
-    String tagName = nameTxtBox.getText().trim();
-    if (tagName.isEmpty()) {
-      nameTxtBox.setFocus(true);
-      return;
-    }
-
-    String rev = irevTxtBox.getText().trim();
-    if (rev.isEmpty()) {
-      irevTxtBox.setText("HEAD");
-      Scheduler.get()
-          .scheduleDeferred(
-              new ScheduledCommand() {
-                @Override
-                public void execute() {
-                  irevTxtBox.selectAll();
-                  irevTxtBox.setFocus(true);
-                }
-              });
-      return;
-    }
-
-    String annotation = annotationTxtBox.getText().trim();
-    if (annotation.isEmpty()) {
-      annotation = null;
-    }
-
-    addTag.setEnabled(false);
-    ProjectApi.createTag(
-        getProjectKey(),
-        tagName,
-        rev,
-        annotation,
-        new GerritCallback<TagInfo>() {
-          @Override
-          public void onSuccess(TagInfo tag) {
-            showAddedTag(tag);
-            nameTxtBox.setText("");
-            irevTxtBox.setText("");
-            annotationTxtBox.setText("");
-            query = new Query(match).start(start).run();
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            addTag.setEnabled(true);
-            selectAllAndFocus(nameTxtBox);
-            new ErrorDialog(caught.getMessage()).center();
-          }
-        });
-  }
-
-  void showAddedTag(TagInfo tag) {
-    SafeHtmlBuilder b = new SafeHtmlBuilder();
-    b.openElement("b");
-    b.append(Gerrit.C.tagCreationConfirmationMessage());
-    b.closeElement("b");
-
-    b.openElement("p");
-    b.append(tag.ref());
-    b.closeElement("p");
-
-    ConfirmationDialog confirmationDialog =
-        new ConfirmationDialog(
-            Gerrit.C.tagCreationDialogTitle(),
-            b.toSafeHtml(),
-            new ConfirmationCallback() {
-              @Override
-              public void onOk() {
-                // do nothing
-              }
-            });
-    confirmationDialog.center();
-    confirmationDialog.setCancelVisible(false);
-  }
-
-  private static void selectAllAndFocus(TextBox textBox) {
-    textBox.selectAll();
-    textBox.setFocus(true);
-  }
-
-  private class TagsTable extends NavigationTable<TagInfo> {
-    private ValueChangeHandler<Boolean> updateDeleteHandler;
-    boolean canDelete;
-
-    TagsTable() {
-      table.setWidth("");
-      table.setText(0, 2, AdminConstants.I.columnTagName());
-      table.setText(0, 3, AdminConstants.I.columnTagRevision());
-
-      FlexCellFormatter fmt = table.getFlexCellFormatter();
-      fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().iconHeader());
-      fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader());
-      fmt.addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader());
-      fmt.addStyleName(0, 4, Gerrit.RESOURCES.css().dataHeader());
-
-      updateDeleteHandler =
-          new ValueChangeHandler<Boolean>() {
-            @Override
-            public void onValueChange(ValueChangeEvent<Boolean> event) {
-              updateDeleteButton();
-            }
-          };
-    }
-
-    Set<String> getCheckedRefs() {
-      Set<String> refs = new HashSet<>();
-      for (int row = 1; row < table.getRowCount(); row++) {
-        TagInfo k = getRowItem(row);
-        if (k != null
-            && table.getWidget(row, 1) instanceof CheckBox
-            && ((CheckBox) table.getWidget(row, 1)).getValue()) {
-          refs.add(k.ref());
-        }
-      }
-      return refs;
-    }
-
-    void setChecked(Set<String> refs) {
-      for (int row = 1; row < table.getRowCount(); row++) {
-        TagInfo k = getRowItem(row);
-        if (k != null && refs.contains(k.ref()) && table.getWidget(row, 1) instanceof CheckBox) {
-          ((CheckBox) table.getWidget(row, 1)).setValue(true);
-        }
-      }
-    }
-
-    void deleteChecked() {
-      final Set<String> refs = getCheckedRefs();
-
-      SafeHtmlBuilder b = new SafeHtmlBuilder();
-      b.openElement("b");
-      b.append(Gerrit.C.tagDeletionConfirmationMessage());
-      b.closeElement("b");
-
-      b.openElement("p");
-      boolean first = true;
-      for (String ref : refs) {
-        if (!first) {
-          b.append(",").br();
-        }
-        b.append(ref);
-        first = false;
-      }
-      b.closeElement("p");
-
-      if (refs.isEmpty()) {
-        updateDeleteButton();
-        return;
-      }
-
-      delTag.setEnabled(false);
-      ConfirmationDialog confirmationDialog =
-          new ConfirmationDialog(
-              Gerrit.C.tagDeletionDialogTitle(),
-              b.toSafeHtml(),
-              new ConfirmationCallback() {
-                @Override
-                public void onOk() {
-                  deleteTags(refs);
-                }
-
-                @Override
-                public void onCancel() {
-                  tagTable.updateDeleteButton();
-                }
-              });
-      confirmationDialog.center();
-    }
-
-    private void deleteTags(Set<String> tags) {
-      ProjectApi.deleteTags(
-          getProjectKey(),
-          tags,
-          new GerritCallback<VoidResult>() {
-            @Override
-            public void onSuccess(VoidResult result) {
-              query = new Query(match).start(start).run();
-            }
-
-            @Override
-            public void onFailure(Throwable caught) {
-              query = new Query(match).start(start).run();
-              super.onFailure(caught);
-            }
-          });
-    }
-
-    void display(List<TagInfo> tags) {
-      displaySubset(tags, 0, tags.size());
-    }
-
-    void displaySubset(List<TagInfo> tags, int fromIndex, int toIndex) {
-      canDelete = false;
-
-      while (1 < table.getRowCount()) {
-        table.removeRow(table.getRowCount() - 1);
-      }
-
-      for (TagInfo k : tags.subList(fromIndex, toIndex)) {
-        int row = table.getRowCount();
-        table.insertRow(row);
-        applyDataRowStyle(row);
-        populate(row, k);
-      }
-    }
-
-    void populate(int row, TagInfo k) {
-      if (k.canDelete()) {
-        CheckBox sel = new CheckBox();
-        sel.addValueChangeHandler(updateDeleteHandler);
-        table.setWidget(row, 1, sel);
-        canDelete = true;
-      } else {
-        table.setText(row, 1, "");
-      }
-
-      table.setWidget(row, 2, new InlineHTML(highlight(k.getShortName(), match)));
-
-      if (k.revision() != null) {
-        table.setText(row, 3, k.revision());
-      } else {
-        table.setText(row, 3, "");
-      }
-
-      FlowPanel actionsPanel = new FlowPanel();
-      if (k.webLinks() != null) {
-        for (WebLinkInfo webLink : Natives.asList(k.webLinks())) {
-          actionsPanel.add(webLink.toAnchor());
-        }
-      }
-      table.setWidget(row, 4, actionsPanel);
-
-      FlexCellFormatter fmt = table.getFlexCellFormatter();
-      String iconCellStyle = Gerrit.RESOURCES.css().iconCell();
-      String dataCellStyle = Gerrit.RESOURCES.css().dataCell();
-      fmt.addStyleName(row, 1, iconCellStyle);
-      fmt.addStyleName(row, 2, dataCellStyle);
-      fmt.addStyleName(row, 3, dataCellStyle);
-      fmt.addStyleName(row, 4, dataCellStyle);
-
-      setRowItem(row, k);
-    }
-
-    boolean hasTagCanDelete() {
-      return canDelete;
-    }
-
-    void updateDeleteButton() {
-      boolean on = false;
-      for (int row = 1; row < table.getRowCount(); row++) {
-        Widget w = table.getWidget(row, 1);
-        if (w != null && w instanceof CheckBox) {
-          CheckBox sel = (CheckBox) w;
-          if (sel.getValue()) {
-            on = true;
-            break;
-          }
-        }
-      }
-      delTag.setEnabled(on);
-    }
-
-    @Override
-    protected void onOpenRow(int row) {
-      if (row > 0) {
-        movePointerTo(row);
-      }
-    }
-
-    @Override
-    protected Object getRowItemKey(TagInfo item) {
-      return item.ref();
-    }
-  }
-
-  @Override
-  public void onShowView() {
-    super.onShowView();
-    if (match != null) {
-      filterTxt.setCursorPos(match.length());
-    }
-    filterTxt.setFocus(true);
-  }
-
-  private class Query {
-    private String qMatch;
-    private int qStart;
-
-    Query(String match) {
-      this.qMatch = match;
-    }
-
-    Query start(int start) {
-      this.qStart = start;
-      return this;
-    }
-
-    Query run() {
-      // Retrieve one more tag than page size to determine if there are more
-      // tags to display
-      ProjectApi.getTags(
-          getProjectKey(),
-          pageSize + 1,
-          qStart,
-          qMatch,
-          new ScreenLoadCallback<JsArray<TagInfo>>(ProjectTagsScreen.this) {
-            @Override
-            public void preDisplay(JsArray<TagInfo> result) {
-              if (!isAttached()) {
-                // View has been disposed.
-              } else if (query == Query.this) {
-                query = null;
-                showList(result);
-              } else {
-                query.run();
-              }
-            }
-          });
-      return this;
-    }
-
-    void showList(JsArray<TagInfo> result) {
-      setToken(getTokenForScreen(qMatch, qStart));
-      ProjectTagsScreen.this.match = qMatch;
-      ProjectTagsScreen.this.start = qStart;
-
-      if (result.length() <= pageSize) {
-        tagTable.display(Natives.asList(result));
-        next.setVisible(false);
-      } else {
-        tagTable.displaySubset(Natives.asList(result), 0, result.length() - 1);
-        setupNavigationLink(next, qMatch, qStart + pageSize);
-      }
-      if (qStart > 0) {
-        setupNavigationLink(prev, qMatch, qStart - pageSize);
-      } else {
-        prev.setVisible(false);
-      }
-
-      delTag.setVisible(tagTable.hasTagCanDelete());
-      Set<String> checkedRefs = tagTable.getCheckedRefs();
-      tagTable.setChecked(checkedRefs);
-      updateForm();
-
-      if (!isCurrentView()) {
-        display();
-      }
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/RangeBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/RangeBox.java
deleted file mode 100644
index 063a60c..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/RangeBox.java
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (C) 2011 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import com.google.gwt.editor.client.IsEditor;
-import com.google.gwt.editor.client.adapters.TakesValueEditor;
-import com.google.gwt.text.shared.Renderer;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.IntegerBox;
-import com.google.gwt.user.client.ui.ValueBoxBase.TextAlignment;
-import com.google.gwt.user.client.ui.ValueListBox;
-import java.io.IOException;
-
-abstract class RangeBox extends Composite implements IsEditor<TakesValueEditor<Integer>> {
-  static final RangeRenderer rangeRenderer = new RangeRenderer();
-
-  private static class RangeRenderer implements Renderer<Integer> {
-    @Override
-    public String render(Integer object) {
-      if (0 <= object) {
-        return "+" + object;
-      }
-      return String.valueOf(object);
-    }
-
-    @Override
-    public void render(Integer object, Appendable appendable) throws IOException {
-      appendable.append(render(object));
-    }
-  }
-
-  static class List extends RangeBox {
-    final ValueListBox<Integer> list;
-
-    List() {
-      list = new ValueListBox<>(rangeRenderer);
-      initWidget(list);
-    }
-
-    @Override
-    void setEnabled(boolean on) {
-      list.getElement().setPropertyBoolean("disabled", !on);
-    }
-
-    @Override
-    public TakesValueEditor<Integer> asEditor() {
-      return list.asEditor();
-    }
-  }
-
-  static class Box extends RangeBox {
-    private final IntegerBox box;
-
-    Box() {
-      box = new IntegerBox();
-      box.setVisibleLength(10);
-      box.setAlignment(TextAlignment.RIGHT);
-      initWidget(box);
-    }
-
-    @Override
-    void setEnabled(boolean on) {
-      box.getElement().setPropertyBoolean("disabled", !on);
-    }
-
-    @Override
-    public TakesValueEditor<Integer> asEditor() {
-      return box.asEditor();
-    }
-  }
-
-  abstract void setEnabled(boolean on);
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/RefPatternBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/RefPatternBox.java
deleted file mode 100644
index f1180cc..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/RefPatternBox.java
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (C) 2011 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import com.google.gwt.dom.client.Document;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.text.shared.Parser;
-import com.google.gwt.text.shared.Renderer;
-import com.google.gwt.user.client.ui.ValueBox;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-import java.io.IOException;
-import java.text.ParseException;
-
-public class RefPatternBox extends ValueBox<String> {
-  private static final Renderer<String> RENDERER =
-      new Renderer<String>() {
-        @Override
-        public String render(String ref) {
-          return ref;
-        }
-
-        @Override
-        public void render(String ref, Appendable dst) throws IOException {
-          dst.append(render(ref));
-        }
-      };
-
-  private static final Parser<String> PARSER =
-      new Parser<String>() {
-        @Override
-        public String parse(CharSequence text) throws ParseException {
-          String ref = text.toString();
-
-          if (ref.isEmpty()) {
-            throw new ParseException(AdminConstants.I.refErrorEmpty(), 0);
-          }
-
-          if (ref.charAt(0) == '/') {
-            throw new ParseException(AdminConstants.I.refErrorBeginSlash(), 0);
-          }
-
-          if (ref.charAt(0) == '^') {
-            if (!ref.startsWith("^refs/")) {
-              ref = "^refs/heads/" + ref.substring(1);
-            }
-          } else if (!ref.startsWith("refs/")) {
-            ref = "refs/heads/" + ref;
-          }
-
-          for (int i = 0; i < ref.length(); i++) {
-            final char c = ref.charAt(i);
-
-            if (c == '/' && 0 < i && ref.charAt(i - 1) == '/') {
-              throw new ParseException(AdminConstants.I.refErrorDoubleSlash(), i);
-            }
-
-            if (c == ' ') {
-              throw new ParseException(AdminConstants.I.refErrorNoSpace(), i);
-            }
-
-            if (c < ' ') {
-              throw new ParseException(AdminConstants.I.refErrorPrintable(), i);
-            }
-          }
-          return ref;
-        }
-      };
-
-  public RefPatternBox() {
-    super(Document.get().createTextInputElement(), RENDERER, PARSER);
-    addKeyPressHandler(GlobalKey.STOP_PROPAGATION);
-    addKeyPressHandler(
-        new KeyPressHandler() {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            if (event.getCharCode() == ' ') {
-              event.preventDefault();
-            }
-          }
-        });
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/Util.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/Util.java
deleted file mode 100644
index bbc8a1d..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/Util.java
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import com.google.gerrit.common.data.ProjectAdminService;
-import com.google.gerrit.extensions.client.ProjectState;
-import com.google.gerrit.extensions.client.SubmitType;
-import com.google.gwt.core.client.GWT;
-import com.google.gwtjsonrpc.client.JsonUtil;
-
-public class Util {
-  public static final ProjectAdminService PROJECT_SVC;
-
-  static {
-    PROJECT_SVC = GWT.create(ProjectAdminService.class);
-    JsonUtil.bind(PROJECT_SVC, "rpc/ProjectAdminService");
-
-    AdminResources.I.css().ensureInjected();
-  }
-
-  public static String toLongString(SubmitType type) {
-    if (type == null) {
-      return "";
-    }
-    switch (type) {
-      case INHERIT:
-        return AdminConstants.I.projectSubmitType_INHERIT();
-      case FAST_FORWARD_ONLY:
-        return AdminConstants.I.projectSubmitType_FAST_FORWARD_ONLY();
-      case MERGE_IF_NECESSARY:
-        return AdminConstants.I.projectSubmitType_MERGE_IF_NECESSARY();
-      case REBASE_IF_NECESSARY:
-        return AdminConstants.I.projectSubmitType_REBASE_IF_NECESSARY();
-      case REBASE_ALWAYS:
-        return AdminConstants.I.projectSubmitType_REBASE_ALWAYS();
-      case MERGE_ALWAYS:
-        return AdminConstants.I.projectSubmitType_MERGE_ALWAYS();
-      case CHERRY_PICK:
-        return AdminConstants.I.projectSubmitType_CHERRY_PICK();
-      default:
-        return type.name();
-    }
-  }
-
-  public static String toLongString(ProjectState type) {
-    if (type == null) {
-      return "";
-    }
-    switch (type) {
-      case ACTIVE:
-        return AdminConstants.I.projectState_ACTIVE();
-      case READ_ONLY:
-        return AdminConstants.I.projectState_READ_ONLY();
-      case HIDDEN:
-        return AdminConstants.I.projectState_HIDDEN();
-      default:
-        return type.name();
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ValueEditor.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ValueEditor.java
deleted file mode 100644
index ad614e5..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ValueEditor.java
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright (C) 2011 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.admin;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.DivElement;
-import com.google.gwt.dom.client.NativeEvent;
-import com.google.gwt.dom.client.Style.Display;
-import com.google.gwt.editor.client.EditorError;
-import com.google.gwt.editor.client.HasEditorErrors;
-import com.google.gwt.editor.client.IsEditor;
-import com.google.gwt.editor.client.LeafValueEditor;
-import com.google.gwt.editor.ui.client.adapters.ValueBoxEditor;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.DoubleClickEvent;
-import com.google.gwt.event.dom.client.DoubleClickHandler;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiChild;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.Focusable;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.SimplePanel;
-import com.google.gwt.user.client.ui.ValueBoxBase;
-import com.google.gwt.user.client.ui.Widget;
-import java.text.ParseException;
-import java.util.List;
-
-public class ValueEditor<T> extends Composite
-    implements HasEditorErrors<T>, IsEditor<ValueBoxEditor<T>>, LeafValueEditor<T>, Focusable {
-  interface Binder extends UiBinder<Widget, ValueEditor<?>> {}
-
-  static final Binder uiBinder = GWT.create(Binder.class);
-
-  @UiField SimplePanel textPanel;
-  private Label textLabel;
-  private StartEditHandlers startHandlers;
-
-  @UiField Image editIcon;
-
-  @UiField SimplePanel editPanel;
-
-  @UiField DivElement errorLabel;
-
-  private ValueBoxBase<T> editChild;
-  private ValueBoxEditor<T> editProxy;
-  private boolean ignoreEditorValue;
-  private T value;
-
-  public ValueEditor() {
-    startHandlers = new StartEditHandlers();
-    initWidget(uiBinder.createAndBindUi(this));
-    editPanel.setVisible(false);
-    editIcon.addClickHandler(startHandlers);
-  }
-
-  public void edit() {
-    textPanel.removeFromParent();
-    textPanel = null;
-    textLabel = null;
-
-    editIcon.removeFromParent();
-    editIcon = null;
-    startHandlers = null;
-
-    editPanel.setVisible(true);
-  }
-
-  @Override
-  public ValueBoxEditor<T> asEditor() {
-    if (editProxy == null) {
-      editProxy = new EditorProxy();
-    }
-    return editProxy;
-  }
-
-  @Override
-  public T getValue() {
-    return ignoreEditorValue ? value : asEditor().getValue();
-  }
-
-  @Override
-  public void setValue(T value) {
-    this.value = value;
-    asEditor().setValue(value);
-  }
-
-  void setIgnoreEditorValue(boolean off) {
-    ignoreEditorValue = off;
-  }
-
-  public void setEditTitle(String title) {
-    editIcon.setTitle(title);
-  }
-
-  @UiChild(limit = 1, tagname = "display")
-  public void setDisplay(Label widget) {
-    textLabel = widget;
-    textPanel.add(textLabel);
-
-    textLabel.addClickHandler(startHandlers);
-    textLabel.addDoubleClickHandler(startHandlers);
-  }
-
-  @UiChild(limit = 1, tagname = "editor")
-  public void setEditor(ValueBoxBase<T> widget) {
-    editChild = widget;
-    editPanel.add(editChild);
-    editProxy = null;
-  }
-
-  public void setEnabled(boolean enabled) {
-    editIcon.setVisible(enabled);
-    startHandlers.enabled = enabled;
-  }
-
-  @Override
-  public void showErrors(List<EditorError> errors) {
-    StringBuilder buf = new StringBuilder();
-    for (EditorError error : errors) {
-      if (error.getEditor().equals(editProxy)) {
-        buf.append("\n");
-        if (error.getUserData() instanceof ParseException) {
-          buf.append(((ParseException) error.getUserData()).getMessage());
-        } else {
-          buf.append(error.getMessage());
-        }
-      }
-    }
-
-    if (0 < buf.length()) {
-      errorLabel.setInnerText(buf.substring(1));
-      errorLabel.getStyle().setDisplay(Display.BLOCK);
-    } else {
-      errorLabel.setInnerText("");
-      errorLabel.getStyle().setDisplay(Display.NONE);
-    }
-  }
-
-  @Override
-  public void setAccessKey(char key) {
-    editChild.setAccessKey(key);
-  }
-
-  @Override
-  public void setFocus(boolean focused) {
-    editChild.setFocus(focused);
-    if (focused) {
-      editChild.setCursorPos(editChild.getText().length());
-    }
-  }
-
-  @Override
-  public int getTabIndex() {
-    return editChild.getTabIndex();
-  }
-
-  @Override
-  public void setTabIndex(int index) {
-    editChild.setTabIndex(index);
-  }
-
-  private class StartEditHandlers implements ClickHandler, DoubleClickHandler {
-    boolean enabled;
-
-    @Override
-    public void onClick(ClickEvent event) {
-      if (enabled && event.getNativeButton() == NativeEvent.BUTTON_LEFT) {
-        edit();
-      }
-    }
-
-    @Override
-    public void onDoubleClick(DoubleClickEvent event) {
-      if (enabled && event.getNativeButton() == NativeEvent.BUTTON_LEFT) {
-        edit();
-      }
-    }
-  }
-
-  private class EditorProxy extends ValueBoxEditor<T> {
-    EditorProxy() {
-      super(editChild);
-    }
-
-    @Override
-    public void setValue(T value) {
-      super.setValue(value);
-      if (textLabel == null) {
-        setDisplay(new Label());
-      }
-      textLabel.setText(editChild.getText());
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ValueEditor.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ValueEditor.ui.xml
deleted file mode 100644
index 137ad2b..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ValueEditor.ui.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2011 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-  xmlns:ui='urn:ui:com.google.gwt.uibinder'
-  xmlns:g='urn:import:com.google.gwt.user.client.ui'
-  >
-<ui:with field='ico' type='com.google.gerrit.client.GerritResources'/>
-<ui:style gss='false'>
-  .panel {
-    position: relative;
-    white-space: nowrap;
-  }
-
-  .textPanel {
-    width: 100%;
-    padding-right: 21px;
-  }
-
-  .editIcon {
-    position: absolute;
-    top: 0;
-    right: 5px;
-  }
-
-  .editPanel {
-    width: 100%;
-  }
-
-  .errorLabel {
-    display: none;
-    color: red;
-    white-space: pre;
-  }
-</ui:style>
-<g:HTMLPanel stylePrimaryName='{style.panel}'>
-  <g:Image
-      ui:field='editIcon'
-      resource='{ico.edit}'
-      stylePrimaryName='{style.editIcon}'
-      title='Edit'>
-    <ui:attribute name='title'/>
-  </g:Image>
-  <g:SimplePanel ui:field='textPanel' stylePrimaryName='{style.textPanel}'/>
-
-  <g:SimplePanel ui:field='editPanel' stylePrimaryName='{style.editPanel}'/>
-  <div
-      ui:field='errorLabel'
-      class='{style.errorLabel}'/>
-</g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/admin.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/admin.css
deleted file mode 100644
index eca4823..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/admin.css
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the 'License');
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an 'AS IS' BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@eval selectionColor com.google.gerrit.client.Gerrit.getTheme().selectionColor;
-@eval textColor com.google.gerrit.client.Gerrit.getTheme().textColor;
-@def deletedBackground #a9a9a9;
-
-@sprite .deleteIcon {
-  gwt-image: 'deleteNormal';
-  border: none;
-}
-
-@sprite .deleteIcon:hover {
-  gwt-image: 'deleteHover';
-  border: none;
-}
-
-@sprite .undoIcon {
-  gwt-image: 'undoNormal';
-  border: none;
-}
-
-.deleted {
-  background-color: deletedBackground;
-  color: #ffffff;
-  white-space: nowrap;
-  padding-left: 50px;
-}
-
-.deleted:hover {
-  background-color: selectionColor;
-  color: textColor;
- }
-
-.deletedBorder {
-  background: 1px solid deletedBackground;
-}
-
-.deleteSectionHover {
-  background-color: selectionColor !important;
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/arrow_undo.png b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/arrow_undo.png
deleted file mode 100644
index 6972c5e..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/arrow_undo.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/deleteHover.png b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/deleteHover.png
deleted file mode 100644
index 9fde3fa..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/deleteHover.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/deleteNormal.png b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/deleteNormal.png
deleted file mode 100644
index 47a1195..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/deleteNormal.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ActionContext.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ActionContext.java
deleted file mode 100644
index cf8de54..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ActionContext.java
+++ /dev/null
@@ -1,293 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.api;
-
-import com.google.gerrit.client.actions.ActionButton;
-import com.google.gerrit.client.info.ActionInfo;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.ChangeInfo.EditInfo;
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.client.projects.BranchInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.NativeString;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class ActionContext extends JavaScriptObject {
-  static final native void init() /*-{
-    var Gerrit = $wnd.Gerrit;
-    var doc = $wnd.document;
-    var stopPropagation = function (e) {
-      if (e && e.stopPropagation) e.stopPropagation();
-      else $wnd.event.cancelBubble = true;
-    };
-
-    Gerrit.ActionContext = function(u){this._u=u};
-    Gerrit.ActionContext.prototype = {
-      go: Gerrit.go,
-      refresh: Gerrit.refresh,
-      refreshMenuBar: Gerrit.refreshMenuBar,
-      isSignedIn: Gerrit.isSignedIn,
-      showError: Gerrit.showError,
-
-      br: function(){return doc.createElement('br')},
-      hr: function(){return doc.createElement('hr')},
-      button: function(label, o) {
-        var e = doc.createElement('button');
-        e.appendChild(this.div(doc.createTextNode(label)));
-        if (o && o.onclick) e.onclick = o.onclick;
-        return e;
-      },
-      checkbox: function() {
-        var e = doc.createElement('input');
-        e.type = 'checkbox';
-        return e;
-      },
-      div: function() {
-        var e = doc.createElement('div');
-        for (var i = 0; i < arguments.length; i++)
-          e.appendChild(arguments[i]);
-        return e;
-      },
-      label: function(c,label) {
-        var e = doc.createElement('label');
-        e.appendChild(c);
-        e.appendChild(doc.createTextNode(label));
-        return e;
-      },
-      prependLabel: function(label,c) {
-        var e = doc.createElement('label');
-        e.appendChild(doc.createTextNode(label));
-        e.appendChild(c);
-        return e;
-      },
-      span: function() {
-        var e = doc.createElement('span');
-        for (var i = 0; i < arguments.length; i++)
-          e.appendChild(arguments[i]);
-        return e;
-      },
-      msg: function(label) {
-        var e = doc.createElement('span');
-        e.appendChild(doc.createTextNode(label));
-        return e;
-      },
-      textarea: function(o) {
-        var e = doc.createElement('textarea');
-        e.onkeypress = stopPropagation;
-        if (o && o.rows) e.rows = o.rows;
-        if (o && o.cols) e.cols = o.cols;
-        return e;
-      },
-      textfield: function() {
-        var e = doc.createElement('input');
-        e.type = 'text';
-        e.onkeypress = stopPropagation;
-        return e;
-      },
-      select: function(a,s) {
-        var e = doc.createElement('select');
-        for (var i = 0; i < a.length; i++) {
-          var o = doc.createElement('option');
-          if (i==s) {
-            o.setAttributeNode(doc.createAttribute("selected"));
-          }
-          o.appendChild(doc.createTextNode(a[i]));
-          e.appendChild(o);
-        }
-        return e;
-      },
-      selected: function(e) {
-        return e.options[e.selectedIndex].text;
-      },
-
-      popup: function(e){
-        this._p=@com.google.gerrit.client.api.PopupHelper::popup(
-          Lcom/google/gerrit/client/api/ActionContext;Lcom/google/gwt/dom/client/Element;)(this,e)},
-      hide: function() {
-        this._p.@com.google.gerrit.client.api.PopupHelper::hide()();
-        delete this['_p'];
-      },
-
-      call: function(i,b) {
-        var m = this.action.method.toLowerCase();
-        if (m == 'get' || m == 'delete' || i==null) this[m](b);
-        else this[m](i,b);
-      },
-      get: function(b){@com.google.gerrit.client.api.ActionContext::get(
-        Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;)(this._u,b)},
-      post: function(i,b){@com.google.gerrit.client.api.ActionContext::post(
-        Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;Lcom/google/gwt/core/client/JavaScriptObject;)(
-        this._u,i,b)},
-      put: function(i,b){@com.google.gerrit.client.api.ActionContext::put(
-        Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;Lcom/google/gwt/core/client/JavaScriptObject;)(
-        this._u,i,b)},
-      'delete': function(b){@com.google.gerrit.client.api.ActionContext::delete(
-        Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;)(this._u,b)},
-      del: function(b){@com.google.gerrit.client.api.ActionContext::delete(
-        Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;)(this._u,b)},
-    };
-  }-*/;
-
-  static final native ActionContext create(RestApi f) /*-{
-    return new $wnd.Gerrit.ActionContext(f);
-  }-*/;
-
-  final native void set(ActionInfo a) /*-{ this.action=a; }-*/;
-
-  final native void set(ChangeInfo c) /*-{ this.change=c; }-*/;
-
-  final native void set(EditInfo e) /*-{ this.edit=e; }-*/;
-
-  final native void set(Project.NameKey p) /*-{ this.project=p; }-*/;
-
-  final native void set(BranchInfo b) /*-{ this.branch=b }-*/;
-
-  final native void set(RevisionInfo r) /*-{ this.revision=r; }-*/;
-
-  final native void button(ActionButton b) /*-{ this._b=b; }-*/;
-
-  final native ActionButton button() /*-{ return this._b; }-*/;
-
-  public final native boolean has_popup() /*-{ return this.hasOwnProperty('_p') }-*/;
-
-  public final native void hide() /*-{ this.hide(); }-*/;
-
-  protected ActionContext() {}
-
-  static final void get(RestApi api, JavaScriptObject cb) {
-    api.get(wrap(cb));
-  }
-
-  /**
-   * The same as {@link #get(RestApi, JavaScriptObject)} but without converting a {@link
-   * NativeString} result to String.
-   */
-  static final void getRaw(RestApi api, JavaScriptObject cb) {
-    api.get(wrapRaw(cb));
-  }
-
-  static final void post(RestApi api, JavaScriptObject in, JavaScriptObject cb) {
-    if (NativeString.is(in)) {
-      post(api, ((NativeString) in).asString(), cb);
-    } else {
-      api.post(in, wrap(cb));
-    }
-  }
-
-  /**
-   * The same as {@link #post(RestApi, JavaScriptObject, JavaScriptObject)} but without converting a
-   * {@link NativeString} result to String.
-   */
-  static final void postRaw(RestApi api, JavaScriptObject in, JavaScriptObject cb) {
-    if (NativeString.is(in)) {
-      postRaw(api, ((NativeString) in).asString(), cb);
-    } else {
-      api.post(in, wrapRaw(cb));
-    }
-  }
-
-  static final void post(RestApi api, String in, JavaScriptObject cb) {
-    api.post(in, wrap(cb));
-  }
-
-  /**
-   * The same as {@link #post(RestApi, String, JavaScriptObject)} but without converting a {@link
-   * NativeString} result to String.
-   */
-  static final void postRaw(RestApi api, String in, JavaScriptObject cb) {
-    api.post(in, wrapRaw(cb));
-  }
-
-  static final void put(RestApi api, JavaScriptObject cb) {
-    api.put(wrap(cb));
-  }
-
-  /**
-   * The same as {@link #put(RestApi, JavaScriptObject)} but without converting a {@link
-   * NativeString} result to String.
-   */
-  static final void putRaw(RestApi api, JavaScriptObject cb) {
-    api.put(wrapRaw(cb));
-  }
-
-  static final void put(RestApi api, JavaScriptObject in, JavaScriptObject cb) {
-    if (NativeString.is(in)) {
-      put(api, ((NativeString) in).asString(), cb);
-    } else {
-      api.put(in, wrap(cb));
-    }
-  }
-
-  /**
-   * The same as {@link #put(RestApi, JavaScriptObject, JavaScriptObject)} but without converting a
-   * {@link NativeString} result to String.
-   */
-  static final void putRaw(RestApi api, JavaScriptObject in, JavaScriptObject cb) {
-    if (NativeString.is(in)) {
-      putRaw(api, ((NativeString) in).asString(), cb);
-    } else {
-      api.put(in, wrapRaw(cb));
-    }
-  }
-
-  static final void put(RestApi api, String in, JavaScriptObject cb) {
-    api.put(in, wrap(cb));
-  }
-
-  /**
-   * The same as {@link #put(RestApi, String, JavaScriptObject)} but without converting a {@link
-   * NativeString} result to String.
-   */
-  static final void putRaw(RestApi api, String in, JavaScriptObject cb) {
-    api.put(in, wrapRaw(cb));
-  }
-
-  static final void delete(RestApi api, JavaScriptObject cb) {
-    api.delete(wrap(cb));
-  }
-
-  /**
-   * The same as {@link #delete(RestApi, JavaScriptObject)} but without converting a {@link
-   * NativeString} result to String.
-   */
-  static final void deleteRaw(RestApi api, JavaScriptObject cb) {
-    api.delete(wrapRaw(cb));
-  }
-
-  private static GerritCallback<JavaScriptObject> wrap(JavaScriptObject cb) {
-    return new GerritCallback<JavaScriptObject>() {
-      @Override
-      public void onSuccess(JavaScriptObject result) {
-        if (NativeString.is(result)) {
-          NativeString s = result.cast();
-          ApiGlue.invoke(cb, s.asString());
-        } else {
-          ApiGlue.invoke(cb, result);
-        }
-      }
-    };
-  }
-
-  private static GerritCallback<JavaScriptObject> wrapRaw(JavaScriptObject cb) {
-    return new GerritCallback<JavaScriptObject>() {
-      @Override
-      public void onSuccess(JavaScriptObject result) {
-        ApiGlue.invoke(cb, result);
-      }
-    };
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ApiGlue.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ApiGlue.java
deleted file mode 100644
index 294fa9b..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ApiGlue.java
+++ /dev/null
@@ -1,322 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.api;
-
-import com.google.gerrit.client.ErrorDialog;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.info.GeneralPreferences;
-import com.google.gerrit.client.info.ServerInfo;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.user.client.History;
-import com.google.gwt.user.client.Window;
-
-public class ApiGlue {
-  private static String pluginName;
-
-  public static void init() {
-    init0();
-    ActionContext.init();
-    HtmlTemplate.init();
-    Plugin.init();
-  }
-
-  private static native void init0() /*-{
-    var serverUrl = @com.google.gwt.core.client.GWT::getHostPageBaseURL()();
-    var ScreenDefinition = @com.google.gerrit.client.api.ExtensionScreen.Definition::TYPE;
-    var SettingsScreenDefinition = @com.google.gerrit.client.api.ExtensionSettingsScreen.Definition::TYPE;
-    var PanelDefinition = @com.google.gerrit.client.api.ExtensionPanel.Definition::TYPE;
-    $wnd.Gerrit = {
-      JsonString: @com.google.gerrit.client.rpc.NativeString::TYPE,
-      events: {},
-      plugins: {},
-      screens: {},
-      settingsScreens: {},
-      panels: {},
-      change_actions: {},
-      edit_actions: {},
-      revision_actions: {},
-      project_actions: {},
-      branch_actions: {},
-
-      getPluginName: @com.google.gerrit.client.api.ApiGlue::getPluginName(),
-      injectCss: @com.google.gwt.dom.client.StyleInjector::inject(Ljava/lang/String;),
-      install: function (f) {
-        var p = this._getPluginByUrl(@com.google.gerrit.client.api.PluginName::getCallerUrl()());
-        @com.google.gerrit.client.api.ApiGlue::install(
-            Lcom/google/gwt/core/client/JavaScriptObject;
-            Lcom/google/gerrit/client/api/Plugin;)
-          (f,p);
-      },
-      installGwt: function(u){return this._getPluginByUrl(u)},
-      _getPluginByUrl: function(u) {
-        return u.indexOf(serverUrl) == 0
-          ? this.plugins[u.substring(serverUrl.length)]
-          : this.plugins[u]
-      },
-
-      go: @com.google.gerrit.client.api.ApiGlue::go(Ljava/lang/String;),
-      refresh: @com.google.gerrit.client.api.ApiGlue::refresh(),
-      refreshMenuBar: @com.google.gerrit.client.api.ApiGlue::refreshMenuBar(),
-      isSignedIn: @com.google.gerrit.client.api.ApiGlue::isSignedIn(),
-      showError: @com.google.gerrit.client.api.ApiGlue::showError(Ljava/lang/String;),
-      getServerInfo: @com.google.gerrit.client.api.ApiGlue::getServerInfo(),
-      getCurrentUser: @com.google.gerrit.client.api.ApiGlue::getCurrentUser(),
-      getUserPreferences: @com.google.gerrit.client.api.ApiGlue::getUserPreferences(),
-      refreshUserPreferences: @com.google.gerrit.client.api.ApiGlue::refreshUserPreferences(),
-
-      on: function (e,f){(this.events[e] || (this.events[e]=[])).push(f)},
-      onAction: function (t,n,c){this._onAction(this.getPluginName(),t,n,c)},
-      _onAction: function (p,t,n,c) {
-        var i = p+'~'+n;
-        if ('change' == t) this.change_actions[i]=c;
-        else if ('edit' == t) this.edit_actions[i]=c;
-        else if ('revision' == t) this.revision_actions[i]=c;
-        else if ('project' == t) this.project_actions[i]=c;
-        else if ('branch' == t) this.branch_actions[i]=c;
-        else if ('screen' == t) _screen(p,t,c);
-      },
-      screen: function(r,c){this._screen(this.getPluginName(),r,c)},
-      _screen: function(p,r,c){
-        var s = new ScreenDefinition(r,c);
-        (this.screens[p] || (this.screens[p]=[])).push(s);
-      },
-      settingsScreen: function(p,m,c){this._settingsScreen(this.getPluginName(),p,m,c)},
-      _settingsScreen: function(n,p,m,c){
-        var s = new SettingsScreenDefinition(p,m,c);
-        (this.settingsScreens[n] || (this.settingsScreens[n]=[])).push(s);
-      },
-      panel: function(i,c,n){this._panel(this.getPluginName(),i,c,n)},
-      _panel: function(n,i,c,x){
-        var p = new PanelDefinition(n,c,x);
-        (this.panels[i] || (this.panels[i]=[])).push(p);
-      },
-
-      url: function (d) {
-        if (d && d.length > 0)
-          return serverUrl + (d.charAt(0)=='/' ? d.substring(1) : d);
-        return serverUrl;
-      },
-
-      _api: function(u) {
-        return @com.google.gerrit.client.rpc.RestApi::new(Ljava/lang/String;)(u);
-      },
-      get: function(u,b) {
-        @com.google.gerrit.client.api.ActionContext::get(
-            Lcom/google/gerrit/client/rpc/RestApi;
-            Lcom/google/gwt/core/client/JavaScriptObject;)
-          (this._api(u), b);
-      },
-      get_raw: function(u,b) {
-        @com.google.gerrit.client.api.ActionContext::getRaw(
-            Lcom/google/gerrit/client/rpc/RestApi;
-            Lcom/google/gwt/core/client/JavaScriptObject;)
-          (this._api(u), b);
-      },
-      post: function(u,i,b) {
-        if (typeof i == 'string') {
-          @com.google.gerrit.client.api.ActionContext::post(
-              Lcom/google/gerrit/client/rpc/RestApi;
-              Ljava/lang/String;
-              Lcom/google/gwt/core/client/JavaScriptObject;)
-            (this._api(u), i, b);
-        } else {
-          @com.google.gerrit.client.api.ActionContext::post(
-              Lcom/google/gerrit/client/rpc/RestApi;
-              Lcom/google/gwt/core/client/JavaScriptObject;
-              Lcom/google/gwt/core/client/JavaScriptObject;)
-            (this._api(u), i, b);
-        }
-      },
-      post_raw: function(u,i,b) {
-        if (typeof i == 'string') {
-          @com.google.gerrit.client.api.ActionContext::postRaw(
-              Lcom/google/gerrit/client/rpc/RestApi;
-              Ljava/lang/String;
-              Lcom/google/gwt/core/client/JavaScriptObject;)
-            (this._api(u), i, b);
-        } else {
-          @com.google.gerrit.client.api.ActionContext::postRaw(
-              Lcom/google/gerrit/client/rpc/RestApi;
-              Lcom/google/gwt/core/client/JavaScriptObject;
-              Lcom/google/gwt/core/client/JavaScriptObject;)
-            (this._api(u), i, b);
-        }
-      },
-      put: function(u,i,b) {
-        if (b) {
-          if (typeof i == 'string') {
-            @com.google.gerrit.client.api.ActionContext::put(
-                Lcom/google/gerrit/client/rpc/RestApi;
-                Ljava/lang/String;
-                Lcom/google/gwt/core/client/JavaScriptObject;)
-              (this._api(u), i, b);
-          } else {
-            @com.google.gerrit.client.api.ActionContext::put(
-                Lcom/google/gerrit/client/rpc/RestApi;
-                Lcom/google/gwt/core/client/JavaScriptObject;
-                Lcom/google/gwt/core/client/JavaScriptObject;)
-              (this._api(u), i, b);
-          }
-        } else {
-          @com.google.gerrit.client.api.ActionContext::put(
-              Lcom/google/gerrit/client/rpc/RestApi;
-              Lcom/google/gwt/core/client/JavaScriptObject;)
-            (this._api(u), i);
-        }
-      },
-      put_raw: function(u,i,b) {
-        if (b) {
-          if (typeof i == 'string') {
-            @com.google.gerrit.client.api.ActionContext::putRaw(
-                Lcom/google/gerrit/client/rpc/RestApi;
-                Ljava/lang/String;
-                Lcom/google/gwt/core/client/JavaScriptObject;)
-              (this._api(u), i, b);
-          } else {
-            @com.google.gerrit.client.api.ActionContext::putRaw(
-                Lcom/google/gerrit/client/rpc/RestApi;
-                Lcom/google/gwt/core/client/JavaScriptObject;
-                Lcom/google/gwt/core/client/JavaScriptObject;)
-              (this._api(u), i, b);
-          }
-        } else {
-          @com.google.gerrit.client.api.ActionContext::putRaw(
-              Lcom/google/gerrit/client/rpc/RestApi;
-              Lcom/google/gwt/core/client/JavaScriptObject;)
-            (this._api(u), i);
-        }
-      },
-      'delete': function(u,b) {
-        @com.google.gerrit.client.api.ActionContext::delete(
-            Lcom/google/gerrit/client/rpc/RestApi;
-            Lcom/google/gwt/core/client/JavaScriptObject;)
-          (this._api(u), b);
-      },
-      del: function(u,b) {
-        @com.google.gerrit.client.api.ActionContext::delete(
-            Lcom/google/gerrit/client/rpc/RestApi;
-            Lcom/google/gwt/core/client/JavaScriptObject;)
-          (this._api(u), b);
-      },
-      del_raw: function(u,b) {
-        @com.google.gerrit.client.api.ActionContext::deleteRaw(
-            Lcom/google/gerrit/client/rpc/RestApi;
-            Lcom/google/gwt/core/client/JavaScriptObject;)
-          (this._api(u), b);
-      },
-    };
-  }-*/;
-
-  private static void install(JavaScriptObject cb, Plugin p) throws Exception {
-    try {
-      pluginName = p.name();
-      invoke(cb, p);
-      p._initialized();
-    } catch (Exception e) {
-      p.failure(e);
-      throw e;
-    } finally {
-      pluginName = null;
-      PluginLoader.loaded();
-    }
-  }
-
-  private static String getPluginName() {
-    if (pluginName != null) {
-      return pluginName;
-    }
-    return PluginName.fromUrl(PluginName.getCallerUrl());
-  }
-
-  private static void go(String urlOrToken) {
-    if (urlOrToken.startsWith("http:")
-        || urlOrToken.startsWith("https:")
-        || urlOrToken.startsWith("//")) {
-      Window.Location.assign(urlOrToken);
-    } else {
-      Gerrit.display(urlOrToken);
-    }
-  }
-
-  private static void refresh() {
-    Gerrit.display(History.getToken());
-  }
-
-  private static ServerInfo getServerInfo() {
-    return Gerrit.info();
-  }
-
-  private static AccountInfo getCurrentUser() {
-    return Gerrit.getUserAccount();
-  }
-
-  private static GeneralPreferences getUserPreferences() {
-    return Gerrit.getUserPreferences();
-  }
-
-  private static void refreshUserPreferences() {
-    Gerrit.refreshUserPreferences();
-  }
-
-  private static void refreshMenuBar() {
-    Gerrit.refreshMenuBar();
-  }
-
-  private static boolean isSignedIn() {
-    return Gerrit.isSignedIn();
-  }
-
-  private static void showError(String message) {
-    new ErrorDialog(message).center();
-  }
-
-  static final native void invoke(JavaScriptObject f) /*-{ f(); }-*/;
-
-  static final native void invoke(JavaScriptObject f, JavaScriptObject a) /*-{ f(a); }-*/;
-
-  static final native void invoke(
-      JavaScriptObject f, JavaScriptObject a, JavaScriptObject b) /*-{ f(a,b) }-*/;
-
-  static final native void invoke(JavaScriptObject f, String a) /*-{ f(a); }-*/;
-
-  public static final void fireEvent(String event, String a) {
-    JsArray<JavaScriptObject> h = getEventHandlers(event);
-    for (int i = 0; i < h.length(); i++) {
-      invoke(h.get(i), a);
-    }
-  }
-
-  public static final void fireEvent(String event, Element e) {
-    JsArray<JavaScriptObject> h = getEventHandlers(event);
-    for (int i = 0; i < h.length(); i++) {
-      invoke(h.get(i), e);
-    }
-  }
-
-  static final void fireEvent(String event, JavaScriptObject a, JavaScriptObject b) {
-    JsArray<JavaScriptObject> h = getEventHandlers(event);
-    for (int i = 0; i < h.length(); i++) {
-      invoke(h.get(i), a, b);
-    }
-  }
-
-  static final native JsArray<JavaScriptObject> getEventHandlers(String e)
-      /*-{ return $wnd.Gerrit.events[e] || [] }-*/ ;
-
-  private ApiGlue() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ChangeGlue.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ChangeGlue.java
deleted file mode 100644
index c7f0051..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ChangeGlue.java
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.api;
-
-import com.google.gerrit.client.actions.ActionButton;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.info.ActionInfo;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-
-public class ChangeGlue {
-  public static void fireShowChange(ChangeInfo change, RevisionInfo rev) {
-    ApiGlue.fireEvent("showchange", change, rev);
-  }
-
-  public static boolean onSubmitChange(ChangeInfo change, RevisionInfo rev) {
-    JsArray<JavaScriptObject> h = ApiGlue.getEventHandlers("submitchange");
-    for (int i = 0; i < h.length(); i++) {
-      if (!invoke(h.get(i), change, rev)) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  public static void onAction(ChangeInfo change, ActionInfo action, ActionButton button) {
-    RestApi api = ChangeApi.change(change.project(), change.legacyId().get()).view(action.id());
-    JavaScriptObject f = get(action.id());
-    if (f != null) {
-      ActionContext c = ActionContext.create(api);
-      c.set(action);
-      c.set(change);
-      c.button(button);
-      ApiGlue.invoke(f, c);
-    } else {
-      DefaultActions.invoke(change, action, api);
-    }
-  }
-
-  private static native JavaScriptObject get(String id) /*-{
-    return $wnd.Gerrit.change_actions[id];
-  }-*/;
-
-  private static native boolean invoke(JavaScriptObject h, ChangeInfo a, RevisionInfo r)
-      /*-{ return h(a,r) }-*/ ;
-
-  private ChangeGlue() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/DefaultActions.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/DefaultActions.java
deleted file mode 100644
index 0c4aacd..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/DefaultActions.java
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.api;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.info.ActionInfo;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.NativeString;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.Window.Location;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-class DefaultActions {
-  static void invoke(ChangeInfo change, ActionInfo action, RestApi api) {
-    invoke(action, api, callback(PageLinks.toChange(change.projectNameKey(), change.legacyId())));
-  }
-
-  static void invoke(Project.NameKey project, ActionInfo action, RestApi api) {
-    invoke(action, api, callback(PageLinks.toProject(project)));
-  }
-
-  private static AsyncCallback<JavaScriptObject> callback(String target) {
-    return new GerritCallback<JavaScriptObject>() {
-      @Override
-      public void onSuccess(JavaScriptObject in) {
-        UiResult result = asUiResult(in);
-        if (result == null) {
-          Gerrit.display(target);
-          return;
-        }
-
-        if (result.alert() != null) {
-          Window.alert(result.alert());
-        }
-
-        if (result.redirectUrl() != null && result.openWindow()) {
-          Window.open(result.redirectUrl(), "_blank", null);
-        } else if (result.redirectUrl() != null) {
-          Location.assign(result.redirectUrl());
-        } else {
-          Gerrit.display(target);
-        }
-      }
-
-      private UiResult asUiResult(JavaScriptObject in) {
-        if (NativeString.is(in)) {
-          String str = ((NativeString) in).asString();
-          return str.isEmpty() ? UiResult.none() : UiResult.alert(str);
-        }
-        return in.cast();
-      }
-    };
-  }
-
-  private static void invoke(ActionInfo action, RestApi api, AsyncCallback<JavaScriptObject> cb) {
-    if ("GET".equalsIgnoreCase(action.method())) {
-      api.get(cb);
-    } else if ("PUT".equalsIgnoreCase(action.method())) {
-      api.put(JavaScriptObject.createObject(), cb);
-    } else if ("DELETE".equalsIgnoreCase(action.method())) {
-      api.delete(cb);
-    } else {
-      api.post(JavaScriptObject.createObject(), cb);
-    }
-  }
-
-  private DefaultActions() {}
-
-  private static class UiResult extends JavaScriptObject {
-    static native UiResult alert(String m) /*-{ return {'alert':m} }-*/;
-
-    static native UiResult none() /*-{ return {} }-*/;
-
-    final native String alert() /*-{ return this.alert }-*/;
-
-    final native String redirectUrl() /*-{ return this.url }-*/;
-
-    final native boolean openWindow() /*-{ return this.open_window || false }-*/;
-
-    protected UiResult() {}
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/EditGlue.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/EditGlue.java
deleted file mode 100644
index 85cfde6..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/EditGlue.java
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.api;
-
-import com.google.gerrit.client.actions.ActionButton;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.info.ActionInfo;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.ChangeInfo.EditInfo;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class EditGlue {
-  public static void onAction(
-      ChangeInfo change, EditInfo edit, ActionInfo action, ActionButton button) {
-    RestApi api = ChangeApi.edit(change.project(), change.legacyId().get()).view(action.id());
-
-    JavaScriptObject f = get(action.id());
-    if (f != null) {
-      ActionContext c = ActionContext.create(api);
-      c.set(action);
-      c.set(change);
-      c.set(edit);
-      c.button(button);
-      ApiGlue.invoke(f, c);
-    } else {
-      DefaultActions.invoke(change, action, api);
-    }
-  }
-
-  private static native JavaScriptObject get(String id) /*-{
-    return $wnd.Gerrit.edit_actions[id];
-  }-*/;
-
-  private EditGlue() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ExtensionPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ExtensionPanel.java
deleted file mode 100644
index 6d3dd60..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ExtensionPanel.java
+++ /dev/null
@@ -1,205 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.api;
-
-import com.google.gerrit.client.GerritUiExtensionPoint;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.SimplePanel;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-public class ExtensionPanel extends FlowPanel {
-  private static final Logger logger = Logger.getLogger(ExtensionPanel.class.getName());
-  private final GerritUiExtensionPoint extensionPoint;
-  private final List<Context> contexts;
-
-  public ExtensionPanel(GerritUiExtensionPoint extensionPoint) {
-    this(extensionPoint, new ArrayList<String>());
-  }
-
-  public ExtensionPanel(GerritUiExtensionPoint extensionPoint, List<String> panelNames) {
-    this.extensionPoint = extensionPoint;
-    this.contexts = create(panelNames);
-  }
-
-  private List<Context> create(List<String> panelNames) {
-    List<Context> contexts = new ArrayList<>();
-    for (Definition def : getOrderedDefs(panelNames)) {
-      SimplePanel p = new SimplePanel();
-      add(p);
-      contexts.add(Context.create(def, p));
-    }
-    return contexts;
-  }
-
-  private List<Definition> getOrderedDefs(List<String> panelNames) {
-    if (panelNames == null) {
-      panelNames = Collections.emptyList();
-    }
-    Map<String, List<Definition>> defsOrderedByName = new LinkedHashMap<>();
-    for (String name : panelNames) {
-      defsOrderedByName.put(name, new ArrayList<Definition>());
-    }
-    for (Definition def : Natives.asList(Definition.get(extensionPoint.name()))) {
-      addDef(def, defsOrderedByName);
-    }
-    List<Definition> orderedDefs = new ArrayList<>();
-    for (List<Definition> defList : defsOrderedByName.values()) {
-      orderedDefs.addAll(defList);
-    }
-    return orderedDefs;
-  }
-
-  private static void addDef(Definition def, Map<String, List<Definition>> defsOrderedByName) {
-    String panelName = def.getPanelName();
-    if (panelName.equals(def.getPluginName() + ".undefined")) {
-      /* Handle a partially undefined panel name from the
-      javascript layer by generating a random panel name.
-      This maintains support for panels that do not provide a name. */
-      panelName =
-          def.getPluginName() + "." + Long.toHexString(Double.doubleToLongBits(Math.random()));
-    }
-    if (defsOrderedByName.containsKey(panelName)) {
-      defsOrderedByName.get(panelName).add(def);
-    } else if (defsOrderedByName.containsKey(def.getPluginName())) {
-      defsOrderedByName.get(def.getPluginName()).add(def);
-    } else {
-      defsOrderedByName.put(panelName, Collections.singletonList(def));
-    }
-  }
-
-  public void put(GerritUiExtensionPoint.Key key, String value) {
-    for (Context ctx : contexts) {
-      ctx.put(key.name(), value);
-    }
-  }
-
-  public void putInt(GerritUiExtensionPoint.Key key, int value) {
-    for (Context ctx : contexts) {
-      ctx.putInt(key.name(), value);
-    }
-  }
-
-  public void putBoolean(GerritUiExtensionPoint.Key key, boolean value) {
-    for (Context ctx : contexts) {
-      ctx.putBoolean(key.name(), value);
-    }
-  }
-
-  public void putObject(GerritUiExtensionPoint.Key key, JavaScriptObject value) {
-    for (Context ctx : contexts) {
-      ctx.putObject(key.name(), value);
-    }
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    for (Context ctx : contexts) {
-      try {
-        ctx.onLoad();
-      } catch (RuntimeException e) {
-        logger.log(
-            Level.SEVERE,
-            "Failed to load extension panel for extension point "
-                + extensionPoint.name()
-                + " from plugin "
-                + ctx.getPluginName()
-                + ": "
-                + e.getMessage());
-      }
-    }
-  }
-
-  @Override
-  protected void onUnload() {
-    super.onUnload();
-    for (Context ctx : contexts) {
-      for (JavaScriptObject u : Natives.asList(ctx.unload())) {
-        ApiGlue.invoke(u);
-      }
-    }
-  }
-
-  static class Definition extends JavaScriptObject {
-    static final JavaScriptObject TYPE = init();
-
-    private static native JavaScriptObject init() /*-{
-      function PanelDefinition(n, c, x) {
-        this.pluginName = n;
-        this.onLoad = c;
-        this.name = x;
-      };
-      return PanelDefinition;
-    }-*/;
-
-    static native JsArray<Definition> get(String i) /*-{ return $wnd.Gerrit.panels[i] || [] }-*/;
-
-    protected Definition() {}
-
-    public final native String getPanelName() /*-{ return this.pluginName + "." + this.name; }-*/;
-
-    public final native String getPluginName() /*-{ return this.pluginName; }-*/;
-  }
-
-  static class Context extends JavaScriptObject {
-    static final Context create(Definition def, SimplePanel panel) {
-      return create(TYPE, def, panel.getElement());
-    }
-
-    final native void onLoad() /*-{ this._d.onLoad(this) }-*/;
-
-    final native JsArray<JavaScriptObject> unload() /*-{ return this._u }-*/;
-
-    final native String getPluginName() /*-{ return this._d.pluginName; }-*/;
-
-    final native void put(String k, String v) /*-{ this.p[k] = v; }-*/;
-
-    final native void putInt(String k, int v) /*-{ this.p[k] = v; }-*/;
-
-    final native void putBoolean(String k, boolean v) /*-{ this.p[k] = v; }-*/;
-
-    final native void putObject(String k, JavaScriptObject v) /*-{ this.p[k] = v; }-*/;
-
-    private static native Context create(JavaScriptObject T, Definition d, Element e)
-        /*-{ return new T(d,e) }-*/ ;
-
-    private static final JavaScriptObject TYPE = init();
-
-    private static native JavaScriptObject init() /*-{
-      var T = function(d,e) {
-        this._d = d;
-        this._u = [];
-        this.body = e;
-        this.p = {};
-      };
-      T.prototype = {
-        onUnload: function(f){this._u.push(f)},
-      };
-      return T;
-    }-*/;
-
-    protected Context() {}
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ExtensionScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ExtensionScreen.java
deleted file mode 100644
index ff495b9..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ExtensionScreen.java
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.api;
-
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.Screen;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.dom.client.Element;
-
-/** Screen contributed by a plugin. */
-public class ExtensionScreen extends Screen {
-  private Context ctx;
-
-  public ExtensionScreen(String token) {
-    if (token.contains("?")) {
-      token = token.substring(0, token.indexOf('?'));
-    }
-    String name;
-    String rest;
-    int s = token.indexOf('/');
-    if (0 < s) {
-      name = token.substring(0, s);
-      rest = token.substring(s + 1);
-    } else {
-      name = token;
-      rest = "";
-    }
-    ctx = create(name, rest);
-  }
-
-  private Context create(String name, String rest) {
-    for (Definition def : Natives.asList(Definition.get(name))) {
-      JsArrayString m = def.match(rest);
-      if (m != null) {
-        return Context.create(def, this, m);
-      }
-    }
-    return null;
-  }
-
-  public boolean isFound() {
-    return ctx != null;
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    setHeaderVisible(false);
-    ctx.onLoad();
-  }
-
-  @Override
-  protected void onUnload() {
-    super.onUnload();
-    for (JavaScriptObject u : Natives.asList(ctx.unload())) {
-      ApiGlue.invoke(u);
-    }
-  }
-
-  static class Definition extends JavaScriptObject {
-    static final JavaScriptObject TYPE = init();
-
-    private static native JavaScriptObject init() /*-{
-      function ScreenDefinition(r, c) {
-        this.pattern = r;
-        this.onLoad = c;
-      };
-      return ScreenDefinition;
-    }-*/;
-
-    static native JsArray<Definition> get(String n) /*-{ return $wnd.Gerrit.screens[n] || [] }-*/;
-
-    final native JsArrayString match(String t) /*-{
-      var p = this.pattern;
-      if (p instanceof $wnd.RegExp) {
-        var m = p.exec(t);
-        return m && m[0] == t ? m : null;
-      }
-      return p == t ? [t] : null;
-    }-*/;
-
-    protected Definition() {}
-  }
-
-  static class Context extends JavaScriptObject {
-    static final Context create(Definition def, ExtensionScreen view, JsArrayString match) {
-      return create(TYPE, def, view, view.getBody().getElement(), match);
-    }
-
-    final native void onLoad() /*-{ this._d.onLoad(this) }-*/;
-
-    final native JsArray<JavaScriptObject> unload() /*-{ return this._u }-*/;
-
-    private static native Context create(
-        JavaScriptObject T, Definition d, ExtensionScreen s, Element e, JsArrayString m)
-        /*-{ return new T(d,s,e,m) }-*/ ;
-
-    private static final JavaScriptObject TYPE = init();
-
-    private static native JavaScriptObject init() /*-{
-      var T = function(d,s,e,m) {
-        this._d = d;
-        this._s = s;
-        this._u = [];
-        this.body = e;
-        this.token = m[0];
-        this.token_match = m;
-      };
-      T.prototype = {
-        setTitle: function(t){this._s.@com.google.gerrit.client.ui.Screen::setPageTitle(Ljava/lang/String;)(t)},
-        setWindowTitle: function(t){this._s.@com.google.gerrit.client.ui.Screen::setWindowTitle(Ljava/lang/String;)(t)},
-        show: function(){$entry(this._s.@com.google.gwtexpui.user.client.View::display()())},
-        onUnload: function(f){this._u.push(f)},
-      };
-      return T;
-    }-*/;
-
-    protected Context() {}
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ExtensionSettingsScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ExtensionSettingsScreen.java
deleted file mode 100644
index e7d1ed1..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ExtensionSettingsScreen.java
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.api;
-
-import com.google.gerrit.client.account.SettingsScreen;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.NativeString;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.dom.client.Element;
-import java.util.Set;
-
-/** SettingsScreen contributed by a plugin. */
-public class ExtensionSettingsScreen extends SettingsScreen {
-  private Context ctx;
-
-  public ExtensionSettingsScreen(String token) {
-    if (token.contains("?")) {
-      token = token.substring(0, token.indexOf('?'));
-    }
-    String name;
-    String rest;
-    int s = token.indexOf('/');
-    if (0 < s) {
-      name = token.substring(0, s);
-      rest = token.substring(s + 1);
-    } else {
-      name = token;
-      rest = "";
-    }
-    ctx = create(name, rest);
-  }
-
-  private Context create(String name, String rest) {
-    for (Definition def : Natives.asList(Definition.get(name))) {
-      if (def.matches(rest)) {
-        return Context.create(def, this);
-      }
-    }
-    return null;
-  }
-
-  public boolean isFound() {
-    return ctx != null;
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    setHeaderVisible(false);
-    ctx.onLoad();
-  }
-
-  @Override
-  protected void onUnload() {
-    super.onUnload();
-    for (JavaScriptObject u : Natives.asList(ctx.unload())) {
-      ApiGlue.invoke(u);
-    }
-  }
-
-  public static class Definition extends JavaScriptObject {
-    static final JavaScriptObject TYPE = init();
-
-    private static native JavaScriptObject init() /*-{
-      function SettingsScreenDefinition(p, m, c) {
-        this.path = p;
-        this.menu = m;
-        this.onLoad = c;
-      };
-      return SettingsScreenDefinition;
-    }-*/;
-
-    public static native JsArray<Definition> get(String n)
-        /*-{ return $wnd.Gerrit.settingsScreens[n] || [] }-*/ ;
-
-    public static final Set<String> plugins() {
-      return Natives.keys(settingsScreens());
-    }
-
-    private static native NativeMap<NativeString> settingsScreens()
-        /*-{ return $wnd.Gerrit.settingsScreens; }-*/ ;
-
-    public final native String getPath() /*-{ return this.path; }-*/;
-
-    public final native String getMenu() /*-{ return this.menu; }-*/;
-
-    final native boolean matches(String t) /*-{ return this.path == t; }-*/;
-
-    protected Definition() {}
-  }
-
-  static class Context extends JavaScriptObject {
-    static final Context create(Definition def, ExtensionSettingsScreen view) {
-      return create(TYPE, def, view, view.getBody().getElement());
-    }
-
-    final native void onLoad() /*-{ this._d.onLoad(this) }-*/;
-
-    final native JsArray<JavaScriptObject> unload() /*-{ return this._u }-*/;
-
-    private static native Context create(
-        JavaScriptObject T, Definition d, ExtensionSettingsScreen s, Element e)
-        /*-{ return new T(d,s,e) }-*/ ;
-
-    private static final JavaScriptObject TYPE = init();
-
-    private static native JavaScriptObject init() /*-{
-      var T = function(d,s,e) {
-        this._d = d;
-        this._s = s;
-        this._u = [];
-        this.body = e;
-      };
-      T.prototype = {
-        setTitle: function(t){this._s.@com.google.gerrit.client.ui.Screen::setPageTitle(Ljava/lang/String;)(t)},
-        setWindowTitle: function(t){this._s.@com.google.gerrit.client.ui.Screen::setWindowTitle(Ljava/lang/String;)(t)},
-        show: function(){$entry(this._s.@com.google.gwtexpui.user.client.View::display()())},
-        onUnload: function(f){this._u.push(f)},
-      };
-      return T;
-    }-*/;
-
-    protected Context() {}
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/HtmlTemplate.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/HtmlTemplate.java
deleted file mode 100644
index ba9c659..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/HtmlTemplate.java
+++ /dev/null
@@ -1,153 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.api;
-
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.dom.client.Document;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.Node;
-import com.google.gwt.dom.client.StyleInjector;
-import com.google.gwt.user.client.DOM;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-
-final class HtmlTemplate {
-  static native void init() /*-{
-    var ElementSet = function(r,e) {
-      this.root = r;
-      this.elements = e;
-    };
-    ElementSet.prototype = {
-      clear: function() {
-        this.root = null;
-        this.elements = null;
-      },
-    };
-
-    $wnd.Gerrit.css = @com.google.gerrit.client.api.HtmlTemplate::css(Ljava/lang/String;);
-    $wnd.Gerrit.html = function(h,r,w) {
-      var i = {};
-      if (r) {
-        h = h.replace(
-          /\sid=['"]\{([a-z_][a-z0-9_]*)\}['"]|\{([a-z0-9._-]+)\}/gi,
-          function(m,a,b) {
-            if (a)
-              return @com.google.gerrit.client.api.HtmlTemplate::id(
-                  Lcom/google/gerrit/client/api/HtmlTemplate$IdMap;
-                  Ljava/lang/String;)
-                (i,a);
-            return @com.google.gerrit.client.api.HtmlTemplate::html(
-                Lcom/google/gerrit/client/api/HtmlTemplate$ReplacementMap;
-                Ljava/lang/String;)
-              (r,b);
-          });
-      }
-      var e = @com.google.gerrit.client.api.HtmlTemplate::parseHtml(
-          Ljava/lang/String;Lcom/google/gerrit/client/api/HtmlTemplate$IdMap;
-          Lcom/google/gerrit/client/api/HtmlTemplate$ReplacementMap;
-          Z)
-        (h,i,r,!!w);
-      return w ? new ElementSet(e,i) : e;
-    };
-  }-*/;
-
-  private static String css(String css) {
-    String name = DOM.createUniqueId();
-    StyleInjector.inject("." + name + "{" + css + "}");
-    return name;
-  }
-
-  private static String id(IdMap idMap, String key) {
-    String id = DOM.createUniqueId();
-    idMap.put(id, key);
-    return " id='" + id + "'";
-  }
-
-  private static String html(ReplacementMap opts, String id) {
-    int d = id.indexOf('.');
-    if (0 < d) {
-      String name = id.substring(0, d);
-      String rest = id.substring(d + 1);
-      return html(opts.map(name), rest);
-    }
-    return new SafeHtmlBuilder().append(opts.str(id)).asString();
-  }
-
-  private static Node parseHtml(String html, IdMap ids, ReplacementMap opts, boolean wantElements) {
-    Element div = Document.get().createDivElement();
-    div.setInnerHTML(html);
-    if (!ids.isEmpty()) {
-      attachHandlers(div, ids, opts, wantElements);
-    }
-    if (div.getChildCount() == 1) {
-      return div.getFirstChild();
-    }
-    return div;
-  }
-
-  private static void attachHandlers(
-      Element e, IdMap ids, ReplacementMap opts, boolean wantElements) {
-    if (e.getId() != null) {
-      String key = ids.get(e.getId());
-      if (key != null) {
-        ids.remove(e.getId());
-        if (wantElements) {
-          ids.put(key, e);
-        }
-        e.setId(null);
-        opts.map(key).attachHandlers(e);
-      }
-    }
-    for (Element c = e.getFirstChildElement(); c != null; ) {
-      attachHandlers(c, ids, opts, wantElements);
-      c = c.getNextSiblingElement();
-    }
-  }
-
-  private static class ReplacementMap extends JavaScriptObject {
-    final native ReplacementMap map(String n) /*-{ return this[n] }-*/;
-
-    final native String str(String n) /*-{ return ''+this[n] }-*/;
-
-    final native void attachHandlers(Element e) /*-{
-      for (var k in this) {
-        var f = this[k];
-        if (k.substring(0, 2) == 'on' && typeof f == 'function')
-          e[k] = f;
-      }
-    }-*/;
-
-    protected ReplacementMap() {}
-  }
-
-  private static class IdMap extends JavaScriptObject {
-    final native String get(String i) /*-{ return this[i] }-*/;
-
-    final native void remove(String i) /*-{ delete this[i] }-*/;
-
-    final native void put(String i, String k) /*-{ this[i] = k }-*/;
-
-    final native void put(String k, Element e) /*-{ this[k] = e }-*/;
-
-    final native boolean isEmpty() /*-{
-      for (var i in this)
-        return false;
-      return true;
-    }-*/;
-
-    protected IdMap() {}
-  }
-
-  private HtmlTemplate() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/Plugin.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/Plugin.java
deleted file mode 100644
index 48a812c1..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/Plugin.java
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.api;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-final class Plugin extends JavaScriptObject {
-  private static final JavaScriptObject TYPE = createType();
-
-  static Plugin create(String url) {
-    int s = "plugins/".length();
-    int e = url.indexOf('/', s);
-    String name = url.substring(s, e);
-    return create(TYPE, url, name);
-  }
-
-  native String url() /*-{ return this._scriptUrl }-*/;
-
-  native String name() /*-{ return this.name }-*/;
-
-  native boolean loaded() /*-{ return this._success || this._failure != null }-*/;
-
-  native Exception failure() /*-{ return this._failure }-*/;
-
-  native void failure(Exception e) /*-{ this._failure = e }-*/;
-
-  native boolean success() /*-{ return this._success || false }-*/;
-
-  native void _initialized() /*-{ this._success = true }-*/;
-
-  private static native Plugin create(JavaScriptObject T, String u, String n)
-      /*-{ return new T(u,n) }-*/ ;
-
-  private static native JavaScriptObject createType() /*-{
-    function Plugin(u, n) {
-      this._scriptUrl = u;
-      this.name = n;
-    }
-    return Plugin;
-  }-*/;
-
-  static native void init() /*-{
-    var G = $wnd.Gerrit;
-    @com.google.gerrit.client.api.Plugin::TYPE.prototype = {
-      getPluginName: function(){return this.name},
-      getServerInfo: @com.google.gerrit.client.api.ApiGlue::getServerInfo(),
-      getCurrentUser: @com.google.gerrit.client.api.ApiGlue::getCurrentUser(),
-      getUserPreferences: @com.google.gerrit.client.api.ApiGlue::getUserPreferences(),
-      refreshUserPreferences: @com.google.gerrit.client.api.ApiGlue::refreshUserPreferences(),
-      go: @com.google.gerrit.client.api.ApiGlue::go(Ljava/lang/String;),
-      refresh: @com.google.gerrit.client.api.ApiGlue::refresh(),
-      refreshMenuBar: @com.google.gerrit.client.api.ApiGlue::refreshMenuBar(),
-      isSignedIn: @com.google.gerrit.client.api.ApiGlue::isSignedIn(),
-      showError: @com.google.gerrit.client.api.ApiGlue::showError(Ljava/lang/String;),
-      on: function(e,f){G.on(e,f)},
-      onAction: function(t,n,c){G._onAction(this.name,t,n,c)},
-      screen: function(p,c){G._screen(this.name,p,c)},
-      settingsScreen: function(p,m,c){G._settingsScreen(this.name,p,m,c)},
-      panel: function(i,c,n){G._panel(this.name,i,c,n)},
-
-      url: function (u){return G.url(this._url(u))},
-      get: function(u,b){@com.google.gerrit.client.api.ActionContext::get(
-        Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;)(this._api(u),b)},
-      post: function(u,i,b){@com.google.gerrit.client.api.ActionContext::post(
-        Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;Lcom/google/gwt/core/client/JavaScriptObject;)(
-        this._api(u),i,b)},
-      put: function(u,i,b){@com.google.gerrit.client.api.ActionContext::put(
-        Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;Lcom/google/gwt/core/client/JavaScriptObject;)(
-        this._api(u),i,b)},
-      'delete': function(u,b){@com.google.gerrit.client.api.ActionContext::delete(
-        Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;)(this._api(u),b)},
-      del: function(u,b){@com.google.gerrit.client.api.ActionContext::delete(
-        Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;)(this._api(u),b)},
-
-      _loadedGwt: function(){@com.google.gerrit.client.api.PluginLoader::loaded()()},
-      _api: function(u){return @com.google.gerrit.client.rpc.RestApi::new(Ljava/lang/String;)(this._url(u))},
-      _url: function (d) {
-        var u = 'plugins/' + this.name + '/';
-        if (d && d.length > 0)
-          return u + (d.charAt(0)=='/' ? d.substring(1) : d);
-        return u;
-      },
-    };
-  }-*/;
-
-  protected Plugin() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/PluginLoader.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/PluginLoader.java
deleted file mode 100644
index de25ef0..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/PluginLoader.java
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.api;
-
-import static java.util.stream.Collectors.toList;
-
-import com.google.gerrit.client.ErrorDialog;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.VoidResult;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gwt.core.client.Callback;
-import com.google.gwt.core.client.CodeDownloadException;
-import com.google.gwt.core.client.ScriptInjector;
-import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.DialogBox;
-import com.google.gwtexpui.progress.client.ProgressBar;
-import java.util.List;
-
-/** Loads JavaScript plugins with a progress meter visible. */
-public class PluginLoader extends DialogBox {
-  private static PluginLoader self;
-
-  public static void load(
-      List<String> plugins, int loadTimeout, AsyncCallback<VoidResult> callback) {
-    if (plugins == null || plugins.isEmpty()) {
-      callback.onSuccess(VoidResult.create());
-    } else {
-      plugins = plugins.stream().filter(p -> p.endsWith(".js")).collect(toList());
-      if (plugins.isEmpty()) {
-        callback.onSuccess(VoidResult.create());
-      } else {
-        self = new PluginLoader(loadTimeout, callback);
-        self.load(plugins);
-        self.startTimers();
-        self.center();
-      }
-    }
-  }
-
-  static void loaded() {
-    self.loadedOne();
-  }
-
-  private final int loadTimeout;
-  private final AsyncCallback<VoidResult> callback;
-  private ProgressBar progress;
-  private Timer show;
-  private Timer update;
-  private Timer timeout;
-  private boolean visible;
-
-  private PluginLoader(int loadTimeout, AsyncCallback<VoidResult> cb) {
-    super(/* auto hide */ false, /* modal */ true);
-    callback = cb;
-    this.loadTimeout = loadTimeout;
-    progress = new ProgressBar(Gerrit.C.loadingPlugins());
-
-    setStyleName(Gerrit.RESOURCES.css().errorDialog());
-    addStyleName(Gerrit.RESOURCES.css().loadingPluginsDialog());
-  }
-
-  private void load(List<String> pluginUrls) {
-    for (String url : pluginUrls) {
-      Plugin plugin = Plugin.create(url);
-      plugins().put(url, plugin);
-      ScriptInjector.fromUrl(url)
-          .setWindow(ScriptInjector.TOP_WINDOW)
-          .setCallback(new LoadCallback(plugin))
-          .inject();
-    }
-  }
-
-  private void startTimers() {
-    show =
-        new Timer() {
-          @Override
-          public void run() {
-            setText(Window.getTitle());
-            setWidget(progress);
-            setGlassEnabled(true);
-            getGlassElement().addClassName(Gerrit.RESOURCES.css().errorDialogGlass());
-            hide(true);
-            center();
-            visible = true;
-          }
-        };
-    show.schedule(500);
-
-    update =
-        new Timer() {
-          private int cycle;
-
-          @Override
-          public void run() {
-            progress.setValue(100 * ++cycle * 250 / loadTimeout);
-          }
-        };
-    update.scheduleRepeating(250);
-
-    timeout =
-        new Timer() {
-          @Override
-          public void run() {
-            finish();
-          }
-        };
-    timeout.schedule(loadTimeout);
-  }
-
-  private void loadedOne() {
-    boolean done = true;
-    for (Plugin plugin : Natives.asList(plugins().values())) {
-      done &= plugin.loaded();
-    }
-    if (done) {
-      finish();
-    }
-  }
-
-  private void finish() {
-    show.cancel();
-    update.cancel();
-    timeout.cancel();
-    self = null;
-
-    if (!hadFailures()) {
-      if (visible) {
-        progress.setValue(100);
-        new Timer() {
-          @Override
-          public void run() {
-            hide(true);
-          }
-        }.schedule(250);
-      } else {
-        hide(true);
-      }
-    }
-
-    callback.onSuccess(VoidResult.create());
-  }
-
-  private boolean hadFailures() {
-    boolean failed = false;
-    for (Plugin plugin : Natives.asList(plugins().values())) {
-      if (!plugin.success()) {
-        failed = true;
-
-        Exception e = plugin.failure();
-        String msg;
-        if (e != null && e instanceof CodeDownloadException) {
-          msg = Gerrit.M.cannotDownloadPlugin(plugin.url());
-        } else {
-          msg = Gerrit.M.pluginFailed(plugin.name());
-        }
-        hide(true);
-        new ErrorDialog(msg).center();
-      }
-    }
-    return failed;
-  }
-
-  private static native NativeMap<Plugin> plugins() /*-{ return $wnd.Gerrit.plugins }-*/;
-
-  private class LoadCallback implements Callback<Void, Exception> {
-    private final Plugin plugin;
-
-    LoadCallback(Plugin plugin) {
-      this.plugin = plugin;
-    }
-
-    @Override
-    public void onSuccess(Void result) {}
-
-    @Override
-    public void onFailure(Exception reason) {
-      plugin.failure(reason);
-      loadedOne();
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/PluginName.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/PluginName.java
deleted file mode 100644
index 7cf4fbb..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/PluginName.java
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.api;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JavaScriptException;
-import com.google.gwt.core.client.JsArrayString;
-
-/**
- * Determines the name a plugin has been installed under.
- *
- * <p>This implementation guesses the name a plugin runs under by looking at the JavaScript call
- * stack and identifying the URL of the script file calling {@code Gerrit.install()}. The simple
- * approach applied here is looking at the source URLs and extracting the name out of the string,
- * e.g.: {@code "http://localhost:8080/plugins/[name]/static/foo.js"}.
- */
-class PluginName {
-  private static final String UNKNOWN = "<unknown>";
-
-  private static String baseUrl() {
-    return GWT.getHostPageBaseURL() + "plugins/";
-  }
-
-  static String getCallerUrl() {
-    return GWT.<PluginName>create(PluginName.class).findCallerUrl();
-  }
-
-  static String fromUrl(String url) {
-    String baseUrl = baseUrl();
-    if (url != null && url.startsWith(baseUrl)) {
-      int s = url.indexOf('/', baseUrl.length());
-      if (s > 0) {
-        return url.substring(baseUrl.length(), s);
-      }
-    }
-    return UNKNOWN;
-  }
-
-  String findCallerUrl() {
-    JavaScriptException err = makeException();
-    if (hasStack(err)) {
-      return PluginNameMoz.getUrl(err);
-    }
-
-    String baseUrl = baseUrl();
-    StackTraceElement[] trace = getTrace(err);
-    for (int i = trace.length - 1; i >= 0; i--) {
-      String u = trace[i].getFileName();
-      if (u != null && u.startsWith(baseUrl)) {
-        return u;
-      }
-    }
-    return UNKNOWN;
-  }
-
-  private static StackTraceElement[] getTrace(JavaScriptException err) {
-    if (err.getStackTrace().length == 0) {
-      err.fillInStackTrace();
-    }
-    return err.getStackTrace();
-  }
-
-  protected static final native JavaScriptException makeException()
-      /*-{ try { null.a() } catch (e) { return e } }-*/ ;
-
-  private static native boolean hasStack(JavaScriptException e) /*-{ return !!e.stack }-*/;
-
-  /** Extracts URL from the stack frame. */
-  static class PluginNameMoz extends PluginName {
-    @Override
-    String findCallerUrl() {
-      return getUrl(makeException());
-    }
-
-    private static String getUrl(JavaScriptException e) {
-      String baseUrl = baseUrl();
-      JsArrayString stack = getStack(e);
-      for (int i = stack.length() - 1; i >= 0; i--) {
-        String frame = stack.get(i);
-        int at = frame.indexOf(baseUrl);
-        if (at >= 0) {
-          int end = frame.indexOf(':', at + baseUrl.length());
-          if (end < 0) {
-            end = frame.length();
-          }
-          return frame.substring(at, end);
-        }
-      }
-      return UNKNOWN;
-    }
-
-    private static native JsArrayString getStack(JavaScriptException e)
-        /*-{ return e.stack ? e.stack.split('\n') : [] }-*/ ;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/PopupHelper.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/PopupHelper.java
deleted file mode 100644
index 173b369..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/PopupHelper.java
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.api;
-
-import com.google.gerrit.client.actions.ActionButton;
-import com.google.gerrit.client.change.Resources;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-
-class PopupHelper {
-  static PopupHelper popup(ActionContext ctx, Element panel) {
-    PopupHelper helper = new PopupHelper(ctx.button(), panel);
-    helper.show();
-    ctx.button().link(ctx);
-    return helper;
-  }
-
-  private final ActionButton activatingButton;
-  private final FlowPanel panel;
-  private PopupPanel popup;
-
-  PopupHelper(ActionButton button, Element child) {
-    activatingButton = button;
-    panel = new FlowPanel();
-    panel.setStyleName(Resources.I.style().popupContent());
-    panel.getElement().appendChild(child);
-  }
-
-  void show() {
-    final PopupPanel p = new PopupPanel(true);
-    p.setStyleName(Resources.I.style().popup());
-    p.addAutoHidePartner(activatingButton.getElement());
-    p.addCloseHandler(
-        new CloseHandler<PopupPanel>() {
-          @Override
-          public void onClose(CloseEvent<PopupPanel> event) {
-            activatingButton.unlink();
-            if (popup == p) {
-              popup = null;
-            }
-          }
-        });
-    p.add(panel);
-    p.showRelativeTo(activatingButton);
-    GlobalKey.dialog(p);
-    popup = p;
-  }
-
-  void hide() {
-    if (popup != null) {
-      activatingButton.unlink();
-      popup.hide();
-      popup = null;
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ProjectGlue.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ProjectGlue.java
deleted file mode 100644
index 92070f8..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ProjectGlue.java
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.api;
-
-import com.google.gerrit.client.actions.ActionButton;
-import com.google.gerrit.client.info.ActionInfo;
-import com.google.gerrit.client.projects.BranchInfo;
-import com.google.gerrit.client.projects.ProjectApi;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class ProjectGlue {
-  public static void onAction(
-      Project.NameKey project, BranchInfo branch, ActionInfo action, ActionButton button) {
-    RestApi api = ProjectApi.project(project).view("branches").id(branch.ref()).view(action.id());
-    JavaScriptObject f = branchAction(action.id());
-    if (f != null) {
-      ActionContext c = ActionContext.create(api);
-      c.set(action);
-      c.set(project);
-      c.set(branch);
-      c.button(button);
-      ApiGlue.invoke(f, c);
-    } else {
-      DefaultActions.invoke(project, action, api);
-    }
-  }
-
-  public static void onAction(Project.NameKey project, ActionInfo action, ActionButton button) {
-    RestApi api = ProjectApi.project(project).view(action.id());
-    JavaScriptObject f = projectAction(action.id());
-    if (f != null) {
-      ActionContext c = ActionContext.create(api);
-      c.set(action);
-      c.set(project);
-      c.button(button);
-      ApiGlue.invoke(f, c);
-    } else {
-      DefaultActions.invoke(project, action, api);
-    }
-  }
-
-  private static native JavaScriptObject projectAction(String id) /*-{
-    return $wnd.Gerrit.project_actions[id];
-  }-*/;
-
-  private static native JavaScriptObject branchAction(String id) /*-{
-    return $wnd.Gerrit.branch_actions[id];
-  }-*/;
-
-  private ProjectGlue() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/RevisionGlue.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/RevisionGlue.java
deleted file mode 100644
index d1029b2..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/RevisionGlue.java
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.api;
-
-import com.google.gerrit.client.actions.ActionButton;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.info.ActionInfo;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class RevisionGlue {
-  public static void onAction(
-      ChangeInfo change, RevisionInfo revision, ActionInfo action, ActionButton button) {
-    RestApi api =
-        ChangeApi.revision(change.project(), change.legacyId().get(), revision.name())
-            .view(action.id());
-
-    JavaScriptObject f = get(action.id());
-    if (f != null) {
-      ActionContext c = ActionContext.create(api);
-      c.set(action);
-      c.set(change);
-      c.set(revision);
-      c.button(button);
-      ApiGlue.invoke(f, c);
-    } else {
-      DefaultActions.invoke(change, action, api);
-    }
-  }
-
-  private static native JavaScriptObject get(String id) /*-{
-    return $wnd.Gerrit.revision_actions[id];
-  }-*/;
-
-  private RevisionGlue() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/openid/OpenIdConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/openid/OpenIdConstants.java
deleted file mode 100644
index a0eaef7..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/openid/OpenIdConstants.java
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.auth.openid;
-
-import com.google.gwt.i18n.client.Constants;
-
-public interface OpenIdConstants extends Constants {
-  String nameLaunchpad();
-
-  String nameYahoo();
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/openid/OpenIdConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/openid/OpenIdConstants.properties
deleted file mode 100644
index d6e8de6..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/openid/OpenIdConstants.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-nameLaunchpad = Launchpad ID
-nameYahoo = Yahoo! ID
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/openid/OpenIdUtil.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/openid/OpenIdUtil.java
deleted file mode 100644
index d5b7684..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/openid/OpenIdUtil.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.auth.openid;
-
-import com.google.gwt.core.client.GWT;
-
-public class OpenIdUtil {
-  public static final OpenIdConstants C;
-
-  static {
-    C = GWT.create(OpenIdConstants.class);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/blame/BlameInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/blame/BlameInfo.java
deleted file mode 100644
index 77fddeb..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/blame/BlameInfo.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.blame;
-
-import com.google.gerrit.client.RangeInfo;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-
-public class BlameInfo extends JavaScriptObject {
-  public final native String author() /*-{ return this.author; }-*/;
-
-  public final native String id() /*-{ return this.id; }-*/;
-
-  public final native String commitMsg() /*-{ return this.commit_msg; }-*/;
-
-  public final native int time() /*-{ return this.time; }-*/;
-
-  public final native JsArray<RangeInfo> ranges() /*-{ return this.ranges; }-*/;
-
-  protected BlameInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AbandonAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AbandonAction.java
deleted file mode 100644
index fd58959..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AbandonAction.java
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.user.client.ui.Button;
-
-class AbandonAction extends ActionMessageBox {
-  private final Project.NameKey project;
-  private final Change.Id id;
-
-  AbandonAction(Button b, Project.NameKey project, Change.Id id) {
-    super(b);
-    this.project = project;
-    this.id = id;
-  }
-
-  @Override
-  void send(String message) {
-    ChangeApi.abandon(
-        project.get(),
-        id.get(),
-        message,
-        new GerritCallback<ChangeInfo>() {
-          @Override
-          public void onSuccess(ChangeInfo result) {
-            Gerrit.display(PageLinks.toChange(project, id));
-            hide();
-          }
-        });
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ActionMessageBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ActionMessageBox.java
deleted file mode 100644
index 5b3ee29..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ActionMessageBox.java
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-import com.google.gwtexpui.globalkey.client.NpTextArea;
-
-abstract class ActionMessageBox extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, ActionMessageBox> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  interface Style extends CssResource {
-    String popup();
-  }
-
-  private final Button activatingButton;
-  private PopupPanel popup;
-
-  @UiField Style style;
-  @UiField NpTextArea message;
-  @UiField Button send;
-
-  ActionMessageBox(Button button) {
-    this.activatingButton = button;
-    initWidget(uiBinder.createAndBindUi(this));
-    send.setText(button.getText());
-  }
-
-  abstract void send(String message);
-
-  void show() {
-    if (popup != null) {
-      popup.hide();
-      popup = null;
-      return;
-    }
-
-    final PopupPanel p = new PopupPanel(true);
-    p.setStyleName(style.popup());
-    p.addAutoHidePartner(activatingButton.getElement());
-    p.addCloseHandler(
-        new CloseHandler<PopupPanel>() {
-          @Override
-          public void onClose(CloseEvent<PopupPanel> event) {
-            if (popup == p) {
-              popup = null;
-            }
-          }
-        });
-    p.add(this);
-    p.showRelativeTo(activatingButton);
-    GlobalKey.dialog(p);
-    message.setFocus(true);
-    popup = p;
-  }
-
-  void hide() {
-    if (popup != null) {
-      popup.hide();
-      popup = null;
-    }
-  }
-
-  @UiHandler("message")
-  void onMessageKey(KeyPressEvent event) {
-    if ((event.getCharCode() == '\n' || event.getCharCode() == KeyCodes.KEY_ENTER)
-        && event.isControlKeyDown()) {
-      event.preventDefault();
-      event.stopPropagation();
-      onSend(null);
-    }
-  }
-
-  @UiHandler("send")
-  void onSend(@SuppressWarnings("unused") ClickEvent e) {
-    send(message.getValue().trim());
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ActionMessageBox.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ActionMessageBox.ui.xml
deleted file mode 100644
index a9e1bb3..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ActionMessageBox.ui.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'
-    xmlns:c='urn:import:com.google.gwtexpui.globalkey.client'>
-  <ui:with field='res' type='com.google.gerrit.client.change.Resources'/>
-  <ui:style gss='false' type='com.google.gerrit.client.change.ActionMessageBox.Style'>
-    @eval trimColor com.google.gerrit.client.Gerrit.getTheme().trimColor;
-
-    .popup { background-color: trimColor; }
-    .section {
-      padding: 5px 5px;
-      border-bottom: 1px solid #b8b8b8;
-    }
-  </ui:style>
-  <g:HTMLPanel>
-    <div class='{style.section}'>
-      <c:NpTextArea
-         visibleLines='3'
-         characterWidth='40'
-         ui:field='message'/>
-    </div>
-    <div class='{style.section}'>
-      <g:Button ui:field='send'
-          title='(Shortcut: Ctrl-Enter)'
-          styleName='{res.style.button}'>
-        <ui:attribute name='title'/>
-        <div><ui:msg>Send</ui:msg></div>
-      </g:Button>
-    </div>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Actions.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Actions.java
deleted file mode 100644
index e4f5e576..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Actions.java
+++ /dev/null
@@ -1,260 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.actions.ActionButton;
-import com.google.gerrit.client.info.ActionInfo;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.ChangeInfo.CommitInfo;
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-import java.util.TreeSet;
-
-class Actions extends Composite {
-  private static final String[] CORE = {
-    "abandon",
-    "assignee",
-    "cherrypick",
-    "description",
-    "followup",
-    "hashtags",
-    "move",
-    "publish",
-    "rebase",
-    "restore",
-    "revert",
-    "submit",
-    "topic",
-    "private",
-    "/",
-  };
-
-  interface Binder extends UiBinder<FlowPanel, Actions> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  @UiField Button cherrypick;
-  @UiField Button move;
-  @UiField Button rebase;
-  @UiField Button revert;
-  @UiField Button submit;
-
-  @UiField Button abandon;
-  private AbandonAction abandonAction;
-
-  @UiField Button deleteChange;
-
-  @UiField Button markPrivate;
-  @UiField Button unmarkPrivate;
-
-  @UiField Button restore;
-  private RestoreAction restoreAction;
-
-  @UiField Button followUp;
-  private FollowUpAction followUpAction;
-
-  private Change.Id changeId;
-  private ChangeInfo changeInfo;
-  private String revision;
-  private Project.NameKey project;
-  private String topic;
-  private String subject;
-  private String message;
-  private String branch;
-  private String key;
-
-  private boolean rebaseParentNotCurrent = true;
-
-  Actions() {
-    initWidget(uiBinder.createAndBindUi(this));
-    getElement().setId("change_actions");
-  }
-
-  void display(ChangeInfo info, String revision) {
-    this.revision = revision;
-
-    boolean hasUser = Gerrit.isSignedIn();
-    RevisionInfo revInfo = info.revision(revision);
-    CommitInfo commit = revInfo.commit();
-    changeId = info.legacyId();
-    project = info.projectNameKey();
-    topic = info.topic();
-    subject = commit.subject();
-    message = commit.message();
-    branch = info.branch();
-    key = info.changeId();
-    changeInfo = info;
-
-    initChangeActions(info, hasUser);
-
-    NativeMap<ActionInfo> actionMap =
-        revInfo.hasActions() ? revInfo.actions() : NativeMap.<ActionInfo>create();
-    actionMap.copyKeysIntoChildren("id");
-    reloadRevisionActions(actionMap);
-  }
-
-  private void initChangeActions(ChangeInfo info, boolean hasUser) {
-    NativeMap<ActionInfo> actions =
-        info.hasActions() ? info.actions() : NativeMap.<ActionInfo>create();
-    actions.copyKeysIntoChildren("id");
-
-    if (hasUser) {
-      a2b(actions, "abandon", abandon);
-      a2b(actions, "/", deleteChange);
-      a2b(actions, "move", move);
-      a2b(actions, "restore", restore);
-      a2b(actions, "revert", revert);
-      a2b(actions, "followup", followUp);
-      if (info.isPrivate()) {
-        a2b(actions, "private", unmarkPrivate);
-      } else {
-        a2b(actions, "private", markPrivate);
-      }
-      for (String id : filterNonCore(actions)) {
-        add(new ActionButton(info, actions.get(id)));
-      }
-    }
-  }
-
-  void reloadRevisionActions(NativeMap<ActionInfo> actions) {
-    if (!Gerrit.isSignedIn()) {
-      return;
-    }
-    boolean canSubmit = actions.containsKey("submit");
-    if (canSubmit) {
-      ActionInfo action = actions.get("submit");
-      submit.setTitle(action.title());
-      submit.setEnabled(action.enabled());
-      submit.setHTML(new SafeHtmlBuilder().openDiv().append(action.label()).closeDiv());
-      submit.setEnabled(action.enabled());
-    }
-    submit.setVisible(canSubmit);
-
-    a2b(actions, "cherrypick", cherrypick);
-    a2b(actions, "rebase", rebase);
-
-    // The rebase button on change screen is always enabled.
-    // It is the "Rebase" button in the RebaseDialog that might be disabled.
-    rebaseParentNotCurrent = rebase.isEnabled();
-    if (rebase.isVisible()) {
-      rebase.setEnabled(true);
-    }
-    RevisionInfo revInfo = changeInfo.revision(revision);
-    for (String id : filterNonCore(actions)) {
-      add(new ActionButton(changeInfo, revInfo, actions.get(id)));
-    }
-  }
-
-  private void add(ActionButton b) {
-    ((FlowPanel) getWidget()).add(b);
-  }
-
-  private static TreeSet<String> filterNonCore(NativeMap<ActionInfo> m) {
-    TreeSet<String> ids = new TreeSet<>(m.keySet());
-    for (String id : CORE) {
-      ids.remove(id);
-    }
-    return ids;
-  }
-
-  @UiHandler("followUp")
-  void onFollowUp(@SuppressWarnings("unused") ClickEvent e) {
-    if (followUpAction == null) {
-      followUpAction = new FollowUpAction(followUp, project.get(), branch, topic, key);
-    }
-    followUpAction.show();
-  }
-
-  @UiHandler("abandon")
-  void onAbandon(@SuppressWarnings("unused") ClickEvent e) {
-    if (abandonAction == null) {
-      abandonAction = new AbandonAction(abandon, project, changeId);
-    }
-    abandonAction.show();
-  }
-
-  @UiHandler("deleteChange")
-  void onDeleteChange(@SuppressWarnings("unused") ClickEvent e) {
-    if (Window.confirm(Resources.C.deleteChange())) {
-      ChangeActions.delete(project, changeId, deleteChange);
-    }
-  }
-
-  @UiHandler("markPrivate")
-  void onMarkPrivate(@SuppressWarnings("unused") ClickEvent e) {
-    ChangeActions.markPrivate(project, changeId, markPrivate);
-  }
-
-  @UiHandler("unmarkPrivate")
-  void onUnmarkPrivate(@SuppressWarnings("unused") ClickEvent e) {
-    ChangeActions.unmarkPrivate(project, changeId, unmarkPrivate);
-  }
-
-  @UiHandler("restore")
-  void onRestore(@SuppressWarnings("unused") ClickEvent e) {
-    if (restoreAction == null) {
-      restoreAction = new RestoreAction(restore, project, changeId);
-    }
-    restoreAction.show();
-  }
-
-  @UiHandler("rebase")
-  void onRebase(@SuppressWarnings("unused") ClickEvent e) {
-    RebaseAction.call(
-        rebase, project, changeInfo.branch(), changeId, revision, rebaseParentNotCurrent);
-  }
-
-  @UiHandler("submit")
-  void onSubmit(@SuppressWarnings("unused") ClickEvent e) {
-    SubmitAction.call(changeInfo, changeInfo.revision(revision));
-  }
-
-  @UiHandler("cherrypick")
-  void onCherryPick(@SuppressWarnings("unused") ClickEvent e) {
-    CherryPickAction.call(cherrypick, changeInfo, revision, project, message);
-  }
-
-  @UiHandler("move")
-  void onMove(@SuppressWarnings("unused") ClickEvent e) {
-    MoveAction.call(move, changeInfo, project);
-  }
-
-  @UiHandler("revert")
-  void onRevert(@SuppressWarnings("unused") ClickEvent e) {
-    RevertAction.call(revert, changeId, project, revision, subject);
-  }
-
-  private static void a2b(NativeMap<ActionInfo> actions, String a, Button b) {
-    if (actions.containsKey(a)) {
-      b.setVisible(true);
-      ActionInfo actionInfo = actions.get(a);
-      b.setTitle(actionInfo.title());
-      b.setEnabled(actionInfo.enabled());
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Actions.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Actions.ui.xml
deleted file mode 100644
index 8aeba90..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Actions.ui.xml
+++ /dev/null
@@ -1,96 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-  <ui:style gss='false'>
-    @def BUTTON_HEIGHT 14px;
-
-    #change_actions {
-      padding-top: 2px;
-      padding-bottom: 20px;
-    }
-
-    #change_actions button {
-      margin: 6px 3px 0 0;
-      text-align: center;
-      font-size: 8pt;
-      font-weight: bold;
-      border: 2px solid;
-      cursor: pointer;
-      color: rgba(0, 0, 0, 0.15);
-      background-color: #f5f5f5;
-      -webkit-border-radius: 2px;
-      -webkit-box-sizing: content-box;
-    }
-    #change_actions button div {
-      color: #444;
-      min-width: 54px;
-      white-space: nowrap;
-      height: BUTTON_HEIGHT;
-      line-height: BUTTON_HEIGHT;
-    }
-
-    #change_actions button.submit {
-      float: right;
-      background-color: #4d90fe;
-      background-image: -webkit-linear-gradient(top, #4d90fe, #4d90fe);
-    }
-    #change_actions button.submit div {color: #fff;}
-
-    #change_actions button:disabled {
-      font-weight: normal;
-      background-color: #999;
-      background-image: -webkit-linear-gradient(top, #999, #999);
-    }
-  </ui:style>
-
-  <g:FlowPanel>
-    <g:Button ui:field='cherrypick' styleName='' visible='false'>
-      <div><ui:msg>Cherry Pick</ui:msg></div>
-    </g:Button>
-    <g:Button ui:field='move' styleName='' visible='false'>
-      <div><ui:msg>Move Change</ui:msg></div>
-    </g:Button>
-    <g:Button ui:field='rebase' styleName='' visible='false'>
-      <div><ui:msg>Rebase</ui:msg></div>
-    </g:Button>
-    <g:Button ui:field='revert' styleName='' visible='false'>
-      <div><ui:msg>Revert</ui:msg></div>
-    </g:Button>
-    <g:Button ui:field='abandon' styleName='' visible='false'>
-      <div><ui:msg>Abandon</ui:msg></div>
-    </g:Button>
-    <g:Button ui:field='deleteChange' styleName='' visible='false'>
-      <div><ui:msg>Delete Change</ui:msg></div>
-    </g:Button>
-    <g:Button ui:field='restore' styleName='' visible='false'>
-      <div><ui:msg>Restore</ui:msg></div>
-    </g:Button>
-    <g:Button ui:field='followUp' styleName='' visible='false'>
-      <div><ui:msg>Follow-Up</ui:msg></div>
-    </g:Button>
-    <g:Button ui:field='markPrivate' styleName='' visible='false'>
-      <div><ui:msg>Mark Private</ui:msg></div>
-    </g:Button>
-    <g:Button ui:field='unmarkPrivate' styleName='' visible='false'>
-      <div><ui:msg>Unmark Private</ui:msg></div>
-    </g:Button>
-
-    <g:Button ui:field='submit' styleName='{style.submit}' visible='false'/>
-  </g:FlowPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AddFileAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AddFileAction.java
deleted file mode 100644
index 2080a0e..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AddFileAction.java
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-
-class AddFileAction {
-  private final Project.NameKey project;
-  private final Change.Id changeId;
-  private final RevisionInfo revision;
-  private final ChangeScreen.Style style;
-  private final Widget addButton;
-  private final FileTable files;
-
-  private AddFileBox addBox;
-  private PopupPanel popup;
-
-  AddFileAction(
-      Project.NameKey project,
-      Change.Id changeId,
-      RevisionInfo revision,
-      ChangeScreen.Style style,
-      Widget addButton,
-      FileTable files) {
-    this.project = project;
-    this.changeId = changeId;
-    this.revision = revision;
-    this.style = style;
-    this.addButton = addButton;
-    this.files = files;
-  }
-
-  public void onEdit() {
-    if (popup != null) {
-      popup.hide();
-      return;
-    }
-
-    files.unregisterKeys();
-    if (addBox == null) {
-      addBox = new AddFileBox(project, changeId, revision, files);
-    }
-    addBox.clearPath();
-
-    final PopupPanel p = new PopupPanel(true);
-    p.setStyleName(style.replyBox());
-    p.addAutoHidePartner(addButton.getElement());
-    p.addCloseHandler(
-        new CloseHandler<PopupPanel>() {
-          @Override
-          public void onClose(CloseEvent<PopupPanel> event) {
-            if (popup == p) {
-              popup = null;
-            }
-          }
-        });
-    p.add(addBox);
-    p.showRelativeTo(addButton);
-    GlobalKey.dialog(p);
-    addBox.setFocus(true);
-    popup = p;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AddFileBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AddFileBox.java
deleted file mode 100644
index cd862d2..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AddFileBox.java
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Dispatcher;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.client.ui.RemoteSuggestBox;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.event.logical.shared.SelectionEvent;
-import com.google.gwt.event.logical.shared.SelectionHandler;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.Widget;
-
-class AddFileBox extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, AddFileBox> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  private final Project.NameKey project;
-  private final Change.Id changeId;
-  private final RevisionInfo revision;
-  private final FileTable fileTable;
-
-  @UiField Button open;
-  @UiField Button cancel;
-
-  @UiField(provided = true)
-  RemoteSuggestBox path;
-
-  AddFileBox(Project.NameKey project, Change.Id changeId, RevisionInfo revision, FileTable files) {
-    this.project = project;
-    this.changeId = changeId;
-    this.revision = revision;
-    this.fileTable = files;
-
-    path = new RemoteSuggestBox(new PathSuggestOracle(project, changeId, revision));
-    path.addSelectionHandler(
-        new SelectionHandler<String>() {
-          @Override
-          public void onSelection(SelectionEvent<String> event) {
-            open(event.getSelectedItem());
-          }
-        });
-    path.addCloseHandler(
-        new CloseHandler<RemoteSuggestBox>() {
-          @Override
-          public void onClose(CloseEvent<RemoteSuggestBox> event) {
-            hide();
-            fileTable.registerKeys();
-          }
-        });
-
-    initWidget(uiBinder.createAndBindUi(this));
-  }
-
-  void setFocus(boolean focus) {
-    path.setFocus(focus);
-  }
-
-  void clearPath() {
-    path.setText("");
-  }
-
-  @UiHandler("open")
-  void onOpen(@SuppressWarnings("unused") ClickEvent e) {
-    open(path.getText());
-  }
-
-  private void open(String path) {
-    hide();
-    Gerrit.display(
-        Dispatcher.toEditScreen(project, new PatchSet.Id(changeId, revision._number()), path));
-  }
-
-  @UiHandler("cancel")
-  void onCancel(@SuppressWarnings("unused") ClickEvent e) {
-    hide();
-    fileTable.registerKeys();
-  }
-
-  private void hide() {
-    for (Widget w = getParent(); w != null; w = w.getParent()) {
-      if (w instanceof PopupPanel) {
-        ((PopupPanel) w).hide();
-        break;
-      }
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AddFileBox.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AddFileBox.ui.xml
deleted file mode 100644
index c3539bc..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AddFileBox.ui.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:u='urn:import:com.google.gerrit.client.ui'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-  <ui:with field='res' type='com.google.gerrit.client.change.Resources'/>
-  <ui:style gss='false'>
-    .cancel { float: right; }
-  </ui:style>
-  <g:HTMLPanel>
-    <div class='{res.style.section}'>
-      <ui:msg>Path: <u:RemoteSuggestBox ui:field='path' visibleLength='86'/></ui:msg>
-    </div>
-    <div class='{res.style.section}'>
-      <g:Button ui:field='open'
-          title='Open file in editor'
-          styleName='{res.style.button}'>
-        <ui:attribute name='title'/>
-        <div><ui:msg>Open</ui:msg></div>
-      </g:Button>
-      <g:Button ui:field='cancel'
-          styleName='{res.style.button}'
-          addStyleNames='{style.cancel}'>
-          <div>Cancel</div>
-      </g:Button>
-    </div>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Assignee.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Assignee.java
deleted file mode 100644
index a376782..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Assignee.java
+++ /dev/null
@@ -1,239 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.FormatUtil;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.NotSignedInDialog;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.changes.Util;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.ui.InlineHyperlink;
-import com.google.gerrit.client.ui.RemoteSuggestBox;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.event.logical.shared.SelectionEvent;
-import com.google.gwt.event.logical.shared.SelectionHandler;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.EventListener;
-import com.google.gwt.user.client.rpc.StatusCodeException;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.UIObject;
-
-/** Edit assignee using auto-completion. */
-public class Assignee extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, Assignee> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  @UiField Element show;
-  @UiField InlineHyperlink assigneeLink;
-  @UiField Image editAssigneeIcon;
-  @UiField Element form;
-  @UiField Element error;
-
-  @UiField(provided = true)
-  RemoteSuggestBox suggestBox;
-
-  private AssigneeSuggestOracle assigneeSuggestOracle;
-  private Change.Id changeId;
-  private Project.NameKey project;
-  private boolean canEdit;
-  private AccountInfo currentAssignee;
-
-  Assignee() {
-    assigneeSuggestOracle = new AssigneeSuggestOracle();
-    suggestBox = new RemoteSuggestBox(assigneeSuggestOracle);
-    suggestBox.setVisibleLength(55);
-    suggestBox.setHintText(Util.C.approvalTableEditAssigneeHint());
-    suggestBox.addCloseHandler(
-        new CloseHandler<RemoteSuggestBox>() {
-          @Override
-          public void onClose(CloseEvent<RemoteSuggestBox> event) {
-            Assignee.this.onCancel(null);
-          }
-        });
-    suggestBox.addSelectionHandler(
-        new SelectionHandler<String>() {
-          @Override
-          public void onSelection(SelectionEvent<String> event) {
-            editAssignee(event.getSelectedItem());
-          }
-        });
-
-    initWidget(uiBinder.createAndBindUi(this));
-    editAssigneeIcon.addDomHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            onOpenForm();
-          }
-        },
-        ClickEvent.getType());
-  }
-
-  void set(ChangeInfo info) {
-    this.changeId = info.legacyId();
-    this.project = info.projectNameKey();
-    this.canEdit = info.hasActions() && info.actions().containsKey("assignee");
-    assigneeSuggestOracle.setChange(info);
-    setAssignee(info.assignee());
-    editAssigneeIcon.setVisible(canEdit);
-    if (!canEdit) {
-      show.setTitle(null);
-    }
-  }
-
-  void onOpenForm() {
-    UIObject.setVisible(form, true);
-    UIObject.setVisible(show, false);
-    UIObject.setVisible(error, false);
-    editAssigneeIcon.setVisible(false);
-    suggestBox.setFocus(true);
-    if (currentAssignee != null) {
-      suggestBox.setText(FormatUtil.nameEmail(currentAssignee));
-      suggestBox.selectAll();
-    } else {
-      suggestBox.setText("");
-    }
-  }
-
-  void onCloseForm() {
-    UIObject.setVisible(form, false);
-    UIObject.setVisible(show, true);
-    UIObject.setVisible(error, false);
-    editAssigneeIcon.setVisible(true);
-    suggestBox.setFocus(false);
-  }
-
-  @UiHandler("assign")
-  void onEditAssignee(@SuppressWarnings("unused") ClickEvent e) {
-    if (canEdit) {
-      editAssignee(suggestBox.getText());
-    }
-  }
-
-  @UiHandler("cancel")
-  void onCancel(@SuppressWarnings("unused") ClickEvent e) {
-    onCloseForm();
-  }
-
-  private void editAssignee(String assignee) {
-    if (assignee.trim().isEmpty()) {
-      ChangeApi.deleteAssignee(
-          project.get(),
-          changeId.get(),
-          new GerritCallback<AccountInfo>() {
-            @Override
-            public void onSuccess(AccountInfo result) {
-              onCloseForm();
-              setAssignee(null);
-            }
-
-            @Override
-            public void onFailure(Throwable err) {
-              if (isSigninFailure(err)) {
-                new NotSignedInDialog().center();
-              } else {
-                UIObject.setVisible(error, true);
-                error.setInnerText(
-                    err instanceof StatusCodeException
-                        ? ((StatusCodeException) err).getEncodedResponse()
-                        : err.getMessage());
-              }
-            }
-          });
-    } else {
-      ChangeApi.setAssignee(
-          project.get(),
-          changeId.get(),
-          assignee,
-          new GerritCallback<AccountInfo>() {
-            @Override
-            public void onSuccess(AccountInfo result) {
-              onCloseForm();
-              setAssignee(result);
-              Reviewers reviewers = getReviewers();
-              if (reviewers != null) {
-                reviewers.updateReviewerList();
-              }
-            }
-
-            @Override
-            public void onFailure(Throwable err) {
-              if (isSigninFailure(err)) {
-                new NotSignedInDialog().center();
-              } else {
-                UIObject.setVisible(error, true);
-                error.setInnerText(
-                    err instanceof StatusCodeException
-                        ? ((StatusCodeException) err).getEncodedResponse()
-                        : err.getMessage());
-              }
-            }
-          });
-    }
-  }
-
-  private void setAssignee(AccountInfo assignee) {
-    currentAssignee = assignee;
-    assigneeLink.setText(assignee != null ? getName(assignee) : null);
-    assigneeLink.setTargetHistoryToken(
-        assignee != null
-            ? PageLinks.toAssigneeQuery(
-                assignee.name() != null
-                    ? assignee.name()
-                    : assignee.email() != null
-                        ? assignee.email()
-                        : String.valueOf(assignee._accountId()))
-            : "");
-  }
-
-  private Reviewers getReviewers() {
-    Element e = DOM.getParent(getElement());
-    for (e = DOM.getParent(e); e != null; e = DOM.getParent(e)) {
-      EventListener l = DOM.getEventListener(e);
-      if (l instanceof ChangeScreen) {
-        ChangeScreen screen = (ChangeScreen) l;
-        return screen.reviewers;
-      }
-    }
-    return null;
-  }
-
-  private String getName(AccountInfo info) {
-    if (info.name() != null) {
-      return info.name();
-    }
-    if (info.email() != null) {
-      return info.email();
-    }
-    return Gerrit.info().user().anonymousCowardName();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Assignee.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Assignee.ui.xml
deleted file mode 100644
index d5a7239..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Assignee.ui.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:c='urn:import:com.google.gwtexpui.globalkey.client'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'
-    xmlns:u='urn:import:com.google.gerrit.client.ui'>
-  <ui:with field='ico' type='com.google.gerrit.client.GerritResources'/>
-  <ui:with field='res' type='com.google.gerrit.client.change.Resources'/>
-  <ui:style gss='false'>
-    .suggestBox {
-      margin-bottom: 2px;
-    }
-
-    .error {
-      color: #D33D3D;
-      font-weight: bold;
-    }
-
-    .editAssignee,
-    .cancel {
-      cursor: pointer;
-      float: right;
-    }
-  </ui:style>
-  <g:HTMLPanel>
-    <div ui:field='show'>
-      <u:InlineHyperlink ui:field='assigneeLink'
-          title='Search for changes assigned to this user'/>
-      <g:Image ui:field='editAssigneeIcon'
-          resource='{ico.editUser}'
-          styleName='{style.editAssignee}'
-          title='Assign User to Change'/>
-    </div>
-    <div ui:field='form' style='display: none' aria-hidden='true'>
-      <u:RemoteSuggestBox ui:field='suggestBox' styleName='{style.suggestBox}'/>
-      <div ui:field='error'
-           class='{style.error}'
-           style='display: none' aria-hidden='true'/>
-      <div>
-        <g:Button ui:field='assign' styleName='{res.style.button}'>
-          <div>Assign</div>
-        </g:Button>
-        <g:Button ui:field='cancel'
-            styleName='{res.style.button}'
-            addStyleNames='{style.cancel}'>
-          <div>Cancel</div>
-        </g:Button>
-      </div>
-    </div>
-   </g:HTMLPanel>
-  </ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AssigneeSuggestOracle.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AssigneeSuggestOracle.java
deleted file mode 100644
index c8bbfc3..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AssigneeSuggestOracle.java
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.account.AccountApi;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.AccountSuggestOracle.AccountSuggestion;
-import com.google.gerrit.client.ui.SuggestAfterTypingNCharsOracle;
-import com.google.gwt.core.client.JsArray;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/** REST API based suggestion Oracle for assignee */
-public class AssigneeSuggestOracle extends SuggestAfterTypingNCharsOracle {
-
-  private ChangeInfo change;
-
-  public void setChange(ChangeInfo change) {
-    this.change = change;
-  }
-
-  @Override
-  protected void _onRequestSuggestions(Request req, Callback cb) {
-    AccountApi.suggest(
-        getQuery(req),
-        req.getLimit(),
-        new GerritCallback<JsArray<AccountInfo>>() {
-          @Override
-          public void onSuccess(JsArray<AccountInfo> result) {
-            List<AccountSuggestion> r = new ArrayList<>(result.length());
-            for (AccountInfo reviewer : Natives.asList(result)) {
-              r.add(new AccountSuggestion(reviewer, req.getQuery()));
-            }
-            cb.onSuggestionsReady(req, new Response(r));
-          }
-
-          @Override
-          public void onFailure(Throwable err) {
-            List<Suggestion> r = Collections.emptyList();
-            cb.onSuggestionsReady(req, new Response(r));
-          }
-        });
-  }
-
-  private String getQuery(Request req) {
-    StringBuilder query = new StringBuilder();
-    query.append(req.getQuery());
-    if (change != null) {
-      query.append(" cansee:").append(change._number());
-    }
-    return query.toString();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeActions.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeActions.java
deleted file mode 100644
index 0bc74e4..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeActions.java
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Button;
-
-public class ChangeActions {
-
-  static void delete(Project.NameKey project, Change.Id id, Button... draftButtons) {
-    ChangeApi.deleteChange(project.get(), id.get(), mine(draftButtons));
-  }
-
-  static void markPrivate(Project.NameKey project, Change.Id id, Button... draftButtons) {
-    ChangeApi.markPrivate(project.get(), id.get(), cs(project, id, draftButtons));
-  }
-
-  static void unmarkPrivate(Project.NameKey project, Change.Id id, Button... draftButtons) {
-    ChangeApi.unmarkPrivate(project.get(), id.get(), cs(project, id, draftButtons));
-  }
-
-  public static GerritCallback<JavaScriptObject> cs(
-      Project.NameKey project, final Change.Id id, Button... draftButtons) {
-    setEnabled(false, draftButtons);
-    return new GerritCallback<JavaScriptObject>() {
-      @Override
-      public void onSuccess(JavaScriptObject result) {
-        Gerrit.display(PageLinks.toChange(project, id));
-      }
-
-      @Override
-      public void onFailure(Throwable err) {
-        setEnabled(true, draftButtons);
-        if (SubmitFailureDialog.isConflict(err)) {
-          new SubmitFailureDialog(err.getMessage()).center();
-          Gerrit.display(PageLinks.toChange(project, id));
-        } else {
-          super.onFailure(err);
-        }
-      }
-    };
-  }
-
-  private static AsyncCallback<JavaScriptObject> mine(Button... draftButtons) {
-    setEnabled(false, draftButtons);
-    return new GerritCallback<JavaScriptObject>() {
-      @Override
-      public void onSuccess(JavaScriptObject result) {
-        Gerrit.display(PageLinks.MINE);
-      }
-
-      @Override
-      public void onFailure(Throwable err) {
-        setEnabled(true, draftButtons);
-        if (SubmitFailureDialog.isConflict(err)) {
-          new SubmitFailureDialog(err.getMessage()).center();
-          Gerrit.display(PageLinks.MINE);
-        } else {
-          super.onFailure(err);
-        }
-      }
-    };
-  }
-
-  private static void setEnabled(boolean enabled, Button... draftButtons) {
-    if (draftButtons != null) {
-      for (Button b : draftButtons) {
-        b.setEnabled(enabled);
-      }
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeConstants.java
deleted file mode 100644
index ed67846..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeConstants.java
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gwt.i18n.client.Constants;
-
-public interface ChangeConstants extends Constants {
-  String previousChange();
-
-  String nextChange();
-
-  String openChange();
-
-  String reviewedFileTitle();
-
-  String editFileInline();
-
-  String removeFileInline();
-
-  String restoreFileInline();
-
-  String openLastFile();
-
-  String openCommitMessage();
-
-  String patchSet();
-
-  String commit();
-
-  String date();
-
-  String author();
-
-  String notAvailable();
-
-  String relatedChanges();
-
-  String relatedChangesTooltip();
-
-  String conflictingChanges();
-
-  String conflictingChangesTooltip();
-
-  String cherryPicks();
-
-  String cherryPicksTooltip();
-
-  String sameTopic();
-
-  String sameTopicTooltip();
-
-  String submittedTogether();
-
-  String submittedTogetherTooltip();
-
-  String noChanges();
-
-  String indirectAncestor();
-
-  String merged();
-
-  String abandoned();
-
-  String deleteChangeEdit();
-
-  String deleteChange();
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeConstants.properties
deleted file mode 100644
index 9000149..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeConstants.properties
+++ /dev/null
@@ -1,36 +0,0 @@
-previousChange = Previous related change
-nextChange = Next related change
-openChange = Open related change
-reviewedFileTitle = Mark file as reviewed (Shortcut: r)
-editFileInline = Edit file inline
-removeFileInline = Remove file inline
-restoreFileInline = Restore file inline
-
-openLastFile = Open last file
-openCommitMessage = Open commit message
-
-patchSet = Patch Set
-commit = Commit
-date = Date
-author = Author / Committer
-
-notAvailable = N/A
-relatedChanges = Related Changes
-relatedChangesTooltip = Same branch changes connected by Git history
-conflictingChanges = Conflicts With
-conflictingChangesTooltip = Open changes that conflict with this change
-cherryPicks = Cherry-Picks
-cherryPicksTooltip = Changes with the same Change-Id
-sameTopic = Same Topic
-sameTopicTooltip = Changes with the same topic
-submittedTogether = Submitted Together
-submittedTogetherTooltip = Changes submitted together with this change
-noChanges = No Changes
-indirectAncestor = Indirect ancestor
-merged = Merged
-abandoned = Abandoned
-
-deleteChangeEdit = Delete Change Edit?\n\
-  \n\
-  All changes made in the edit revision will be lost.
-deleteChange = Delete Change?
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeMessages.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeMessages.java
deleted file mode 100644
index 4eead56..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeMessages.java
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gwt.i18n.client.Messages;
-
-public interface ChangeMessages extends Messages {
-  String patchSets(String currentlyViewedPatchSet, int currentPatchSet);
-
-  String changeWithNoRevisions(int changeId);
-
-  String relatedChanges(int count);
-
-  String relatedChanges(String count);
-
-  String conflictingChanges(int count);
-
-  String conflictingChanges(String count);
-
-  String cherryPicks(int count);
-
-  String cherryPicks(String count);
-
-  String sameTopic(int count);
-
-  String sameTopic(String count);
-
-  String submittedTogether(int count);
-
-  String submittedTogether(String count);
-
-  String editPatchSet(int patchSet);
-
-  String failedToLoadFileList(String error);
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeMessages.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeMessages.properties
deleted file mode 100644
index 743945d..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeMessages.properties
+++ /dev/null
@@ -1,9 +0,0 @@
-patchSets = Patch Sets ({0}/{1})
-changeWithNoRevisions = Cannot display change {0} because it has no revisions.
-relatedChanges = Related Changes ({0})
-conflictingChanges = Conflicts With ({0})
-cherryPicks = Cherry-Picks ({0})
-sameTopic = Same Topic ({0})
-submittedTogether = Submitted Together ({0})
-editPatchSet = edit:{0}
-failedToLoadFileList = Failed to load file list: {0}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.java
deleted file mode 100644
index ec7bc4a..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.java
+++ /dev/null
@@ -1,1653 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.AvatarImage;
-import com.google.gerrit.client.DiffObject;
-import com.google.gerrit.client.ErrorDialog;
-import com.google.gerrit.client.FormatUtil;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.GerritUiExtensionPoint;
-import com.google.gerrit.client.NotFoundScreen;
-import com.google.gerrit.client.api.ChangeGlue;
-import com.google.gerrit.client.api.ExtensionPanel;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.changes.ChangeList;
-import com.google.gerrit.client.changes.CommentInfo;
-import com.google.gerrit.client.changes.QueryScreen;
-import com.google.gerrit.client.changes.RevisionInfoCache;
-import com.google.gerrit.client.changes.StarredChanges;
-import com.google.gerrit.client.changes.Util;
-import com.google.gerrit.client.diff.DiffApi;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.info.AccountInfo.AvatarInfo;
-import com.google.gerrit.client.info.ActionInfo;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.ChangeInfo.CommitInfo;
-import com.google.gerrit.client.info.ChangeInfo.EditInfo;
-import com.google.gerrit.client.info.ChangeInfo.LabelInfo;
-import com.google.gerrit.client.info.ChangeInfo.MessageInfo;
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.client.info.FileInfo;
-import com.google.gerrit.client.info.GpgKeyInfo;
-import com.google.gerrit.client.info.PushCertificateInfo;
-import com.google.gerrit.client.projects.ConfigInfoCache;
-import com.google.gerrit.client.projects.ConfigInfoCache.Entry;
-import com.google.gerrit.client.rpc.CallbackGroup;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gerrit.client.ui.BranchLink;
-import com.google.gerrit.client.ui.ChangeLink;
-import com.google.gerrit.client.ui.CommentLinkProcessor;
-import com.google.gerrit.client.ui.Hyperlink;
-import com.google.gerrit.client.ui.InlineHyperlink;
-import com.google.gerrit.client.ui.Screen;
-import com.google.gerrit.client.ui.UserActivityMonitor;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.extensions.client.ListChangesOption;
-import com.google.gerrit.extensions.client.SubmitType;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Change.Status;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.dom.client.AnchorElement;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.NativeEvent;
-import com.google.gwt.dom.client.SelectElement;
-import com.google.gwt.dom.client.Style.Display;
-import com.google.gwt.event.dom.client.ChangeEvent;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.EventListener;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.InlineLabel;
-import com.google.gwt.user.client.ui.ListBox;
-import com.google.gwt.user.client.ui.Panel;
-import com.google.gwt.user.client.ui.SimplePanel;
-import com.google.gwt.user.client.ui.ToggleButton;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-import com.google.gwtexpui.globalkey.client.KeyCommand;
-import com.google.gwtexpui.globalkey.client.KeyCommandSet;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-import com.google.gwtorm.client.KeyUtil;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import net.codemirror.lib.CodeMirror;
-
-public class ChangeScreen extends Screen {
-  private static final Logger logger = Logger.getLogger(ChangeScreen.class.getName());
-
-  interface Binder extends UiBinder<HTMLPanel, ChangeScreen> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  interface Style extends CssResource {
-    String avatar();
-
-    String hashtagName();
-
-    String hashtagIcon();
-
-    String highlight();
-
-    String labelName();
-
-    String label_may();
-
-    String label_need();
-
-    String label_ok();
-
-    String label_reject();
-
-    String label_user();
-
-    String pushCertStatus();
-
-    String replyBox();
-
-    String selected();
-
-    String notCurrentPatchSet();
-  }
-
-  static ChangeScreen get(NativeEvent in) {
-    Element e = in.getEventTarget().cast();
-    for (e = DOM.getParent(e); e != null; e = DOM.getParent(e)) {
-      EventListener l = DOM.getEventListener(e);
-      if (l instanceof ChangeScreen) {
-        return (ChangeScreen) l;
-      }
-    }
-    return null;
-  }
-
-  private final Change.Id changeId;
-  @Nullable private Project.NameKey project;
-  private DiffObject base;
-  private String revision;
-  private ChangeInfo changeInfo;
-  private boolean hasDraftComments;
-  private CommentLinkProcessor commentLinkProcessor;
-  private EditInfo edit;
-  private LocalComments lc;
-
-  private List<HandlerRegistration> handlers = new ArrayList<>(4);
-  private UpdateCheckTimer updateCheck;
-  private Timestamp lastDisplayedUpdate;
-  private UpdateAvailableBar updateAvailable;
-  private boolean openReplyBox;
-  private boolean loaded;
-  private FileTable.Mode fileTableMode;
-
-  @UiField HTMLPanel headerLine;
-  @UiField SimplePanel headerExtension;
-  @UiField SimplePanel headerExtensionMiddle;
-  @UiField SimplePanel headerExtensionRight;
-  @UiField Style style;
-  @UiField ToggleButton star;
-  @UiField Anchor permalink;
-
-  @UiField Assignee assignee;
-  @UiField Element assigneeRow;
-  @UiField Element ccText;
-  @UiField Reviewers reviewers;
-  @UiField Hashtags hashtags;
-  @UiField Element hashtagTableRow;
-
-  @UiField FlowPanel ownerPanel;
-  @UiField InlineHyperlink ownerLink;
-
-  @UiField Element uploaderRow;
-  @UiField FlowPanel uploaderPanel;
-  @UiField InlineLabel uploaderName;
-
-  @UiField Element statusText;
-  @UiField Element privateText;
-  @UiField Element wipText;
-  @UiField Image projectSettings;
-  @UiField AnchorElement projectSettingsLink;
-  @UiField InlineHyperlink projectDashboard;
-  @UiField InlineHyperlink branchLink;
-  @UiField Element strategy;
-  @UiField Element submitActionText;
-  @UiField Element notMergeable;
-  @UiField Topic topic;
-  @UiField Element actionText;
-  @UiField Element actionDate;
-  @UiField SimplePanel changeExtension;
-  @UiField SimplePanel relatedExtension;
-  @UiField SimplePanel commitExtension;
-
-  @UiField Actions actions;
-  @UiField Labels labels;
-  @UiField CommitBox commit;
-  @UiField RelatedChanges related;
-  @UiField FileTable files;
-  @UiField ListBox diffBase;
-  @UiField History history;
-  @UiField SimplePanel historyExtensionRight;
-
-  @UiField Button includedIn;
-  @UiField Button patchSets;
-  @UiField Element patchSetsText;
-  @UiField Button download;
-  @UiField Button reply;
-  @UiField Button publishEdit;
-  @UiField Button rebaseEdit;
-  @UiField Button deleteEdit;
-  @UiField Button openAll;
-  @UiField Button editMode;
-  @UiField Button reviewMode;
-  @UiField Button addFile;
-  @UiField Button deleteFile;
-  @UiField Button renameFile;
-  @UiField Button expandAll;
-  @UiField Button collapseAll;
-  @UiField Button hideTaggedComments;
-  @UiField Button showTaggedComments;
-  @UiField QuickApprove quickApprove;
-
-  private ReplyAction replyAction;
-  private IncludedInAction includedInAction;
-  private PatchSetsAction patchSetsAction;
-  private DownloadAction downloadAction;
-  private AddFileAction addFileAction;
-  private DeleteFileAction deleteFileAction;
-  private RenameFileAction renameFileAction;
-
-  public ChangeScreen(
-      @Nullable Project.NameKey project,
-      Change.Id changeId,
-      DiffObject base,
-      String revision,
-      boolean openReplyBox,
-      FileTable.Mode mode) {
-    this.project = project;
-    this.changeId = changeId;
-    this.base = base;
-    this.revision = normalize(revision);
-    this.openReplyBox = openReplyBox;
-    this.fileTableMode = mode;
-    this.lc = new LocalComments(project, changeId);
-    add(uiBinder.createAndBindUi(this));
-  }
-
-  public Project.NameKey getProject() {
-    return project;
-  }
-
-  PatchSet.Id getPatchSetId() {
-    return new PatchSet.Id(changeInfo.legacyId(), changeInfo.revisions().get(revision)._number());
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    loadChangeScreen();
-  }
-
-  private void loadChangeScreen() {
-    if (project == null) {
-      // Load the project if it is not already present. This is the case when the user used a URL
-      // that doesn't include the project. Setting it here will rewrite the URL token to include the
-      // project (visible to the user) and all future API calls made from the change screen will use
-      // project/+/changeId to identify the change.
-      String query = "change:" + changeId.get();
-      ChangeList.query(
-          query,
-          Collections.emptySet(),
-          new AsyncCallback<ChangeList>() {
-            @Override
-            public void onSuccess(ChangeList result) {
-              if (result.length() == 0) {
-                Gerrit.display(getToken(), new NotFoundScreen());
-              } else if (result.length() > 1) {
-                Gerrit.display(PageLinks.toChangeQuery(query), QueryScreen.forQuery(query));
-              } else {
-                // Initialize current screen with newly obtained project
-                project = result.get(0).projectNameKey();
-                loadChangeScreen();
-              }
-            }
-
-            @Override
-            public void onFailure(Throwable caught) {
-              GerritCallback.showFailure(caught);
-            }
-          });
-
-      return;
-    }
-    CallbackGroup group = new CallbackGroup();
-    if (Gerrit.isSignedIn()) {
-      ChangeList.query(
-          "change:" + changeId.get() + " has:draft",
-          Collections.emptySet(),
-          group.add(
-              new AsyncCallback<ChangeList>() {
-                @Override
-                public void onSuccess(ChangeList result) {
-                  hasDraftComments = result.length() > 0;
-                }
-
-                @Override
-                public void onFailure(Throwable caught) {}
-              }));
-      ChangeApi.editWithFiles(
-          Project.NameKey.asStringOrNull(project),
-          changeId.get(),
-          group.add(
-              new AsyncCallback<EditInfo>() {
-                @Override
-                public void onSuccess(EditInfo result) {
-                  edit = result;
-                }
-
-                @Override
-                public void onFailure(Throwable caught) {}
-              }));
-    }
-    loadChangeInfo(
-        true,
-        group.addFinal(
-            new GerritCallback<ChangeInfo>() {
-              @Override
-              public void onSuccess(ChangeInfo info) {
-                info.init();
-                initCurrentRevision(info);
-                final RevisionInfo rev = info.revision(revision);
-                CallbackGroup group = new CallbackGroup();
-                loadCommit(rev, group);
-
-                group.addListener(
-                    new GerritCallback<Void>() {
-                      @Override
-                      public void onSuccess(Void result) {
-                        if (base.isBase() && rev.isMerge()) {
-                          base =
-                              DiffObject.parse(
-                                  info.legacyId(),
-                                  Gerrit.getUserPreferences().defaultBaseForMerges().getBase());
-                        }
-                        loadConfigInfo(info, base);
-                        JsArray<MessageInfo> mAr = info.messages();
-                        for (int i = 0; i < mAr.length(); i++) {
-                          if (mAr.get(i).tag() != null) {
-                            hideTaggedComments.setVisible(true);
-                            break;
-                          }
-                        }
-                      }
-                    });
-                group.done();
-              }
-            }));
-  }
-
-  private RevisionInfo initCurrentRevision(ChangeInfo info) {
-    info.revisions().copyKeysIntoChildren("name");
-    if (edit != null) {
-      edit.setName(edit.commit().commit());
-      info.setEdit(edit);
-      if (edit.hasFiles()) {
-        edit.files().copyKeysIntoChildren("path");
-      }
-      info.revisions().put(edit.name(), RevisionInfo.fromEdit(edit));
-      JsArray<RevisionInfo> list = info.revisions().values();
-
-      // Edit is converted to a regular revision (with number = 0) and
-      // added to the list of revisions. Additionally under certain
-      // circumstances change edit is assigned to be the current revision
-      // and is selected to be shown on the change screen.
-      // We have two different strategies to assign edit to the current ps:
-      // 1. revision == null: no revision is selected, so use the edit only
-      //    if it is based on the latest patch set
-      // 2. edit was selected explicitly from ps drop down:
-      //    use the edit regardless of which patch set it is based on
-      if (revision == null) {
-        RevisionInfo.sortRevisionInfoByNumber(list);
-        RevisionInfo rev = list.get(list.length() - 1);
-        if (rev.isEdit()) {
-          info.setCurrentRevision(rev.name());
-        }
-      } else if (revision.equals("edit") || revision.equals("0")) {
-        for (int i = 0; i < list.length(); i++) {
-          RevisionInfo r = list.get(i);
-          if (r.isEdit()) {
-            info.setCurrentRevision(r.name());
-            break;
-          }
-        }
-      }
-    }
-    return resolveRevisionToDisplay(info);
-  }
-
-  private void addExtensionPoints(ChangeInfo change, RevisionInfo rev, Entry result) {
-    addExtensionPoint(GerritUiExtensionPoint.CHANGE_SCREEN_HEADER, headerExtension, change, rev);
-    addExtensionPoint(
-        GerritUiExtensionPoint.CHANGE_SCREEN_HEADER_RIGHT_OF_BUTTONS,
-        headerExtensionMiddle,
-        change,
-        rev);
-    addExtensionPoint(
-        GerritUiExtensionPoint.CHANGE_SCREEN_HEADER_RIGHT_OF_POP_DOWNS,
-        headerExtensionRight,
-        change,
-        rev);
-    addExtensionPoint(
-        GerritUiExtensionPoint.CHANGE_SCREEN_BELOW_CHANGE_INFO_BLOCK,
-        changeExtension,
-        change,
-        rev,
-        result.getExtensionPanelNames(
-            GerritUiExtensionPoint.CHANGE_SCREEN_BELOW_CHANGE_INFO_BLOCK.toString()));
-    addExtensionPoint(
-        GerritUiExtensionPoint.CHANGE_SCREEN_BELOW_RELATED_INFO_BLOCK,
-        relatedExtension,
-        change,
-        rev);
-    addExtensionPoint(
-        GerritUiExtensionPoint.CHANGE_SCREEN_BELOW_COMMIT_INFO_BLOCK, commitExtension, change, rev);
-    addExtensionPoint(
-        GerritUiExtensionPoint.CHANGE_SCREEN_HISTORY_RIGHT_OF_BUTTONS,
-        historyExtensionRight,
-        change,
-        rev);
-  }
-
-  private void addExtensionPoint(
-      GerritUiExtensionPoint extensionPoint,
-      Panel p,
-      ChangeInfo change,
-      RevisionInfo rev,
-      List<String> panelNames) {
-    ExtensionPanel extensionPanel = new ExtensionPanel(extensionPoint, panelNames);
-    extensionPanel.putObject(GerritUiExtensionPoint.Key.CHANGE_INFO, change);
-    extensionPanel.putObject(GerritUiExtensionPoint.Key.REVISION_INFO, rev);
-    p.add(extensionPanel);
-  }
-
-  private void addExtensionPoint(
-      GerritUiExtensionPoint extensionPoint, Panel p, ChangeInfo change, RevisionInfo rev) {
-    addExtensionPoint(extensionPoint, p, change, rev, Collections.emptyList());
-  }
-
-  private boolean enableSignedPush() {
-    return Gerrit.info().receive().enableSignedPush();
-  }
-
-  void loadChangeInfo(boolean fg, AsyncCallback<ChangeInfo> cb) {
-    RestApi call = ChangeApi.detail(Project.NameKey.asStringOrNull(project), changeId.get());
-    EnumSet<ListChangesOption> opts =
-        EnumSet.of(ListChangesOption.ALL_REVISIONS, ListChangesOption.CHANGE_ACTIONS);
-    if (enableSignedPush()) {
-      opts.add(ListChangesOption.PUSH_CERTIFICATES);
-    }
-    ChangeList.addOptions(call, opts);
-    if (!fg) {
-      call.background();
-    }
-    call.get(cb);
-  }
-
-  void loadRevisionInfo() {
-    RestApi call = ChangeApi.actions(getProject().get(), changeId.get(), revision);
-    call.background();
-    call.get(
-        new GerritCallback<NativeMap<ActionInfo>>() {
-          @Override
-          public void onSuccess(NativeMap<ActionInfo> actionMap) {
-            actionMap.copyKeysIntoChildren("id");
-            renderRevisionInfo(changeInfo, actionMap);
-          }
-        });
-  }
-
-  @Override
-  protected void onUnload() {
-    if (replyAction != null) {
-      replyAction.hide();
-    }
-    if (updateCheck != null) {
-      updateCheck.cancel();
-      updateCheck = null;
-    }
-    for (HandlerRegistration h : handlers) {
-      h.removeHandler();
-    }
-    handlers.clear();
-    super.onUnload();
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    setHeaderVisible(false);
-    Resources.I.style().ensureInjected();
-    star.setVisible(Gerrit.isSignedIn());
-    labels.init(style);
-    reviewers.init(style, ccText);
-    hashtags.init(style);
-  }
-
-  private void initReplyButton(ChangeInfo info, String revision) {
-    if (!info.revision(revision).isEdit()) {
-      reply.setTitle(Gerrit.info().change().replyLabel());
-      reply.setHTML(
-          new SafeHtmlBuilder().openDiv().append(Gerrit.info().change().replyLabel()).closeDiv());
-      if (hasDraftComments || lc.hasReplyComment()) {
-        reply.setStyleName(style.highlight());
-      }
-      reply.setVisible(true);
-    }
-  }
-
-  private void gotoSibling(int offset) {
-    if (offset > 0
-        && changeInfo.currentRevision() != null
-        && changeInfo.currentRevision().equals(revision)) {
-      return;
-    }
-
-    if (offset < 0 && changeInfo.revision(revision)._number() == 1) {
-      return;
-    }
-
-    JsArray<RevisionInfo> revisions = changeInfo.revisions().values();
-    RevisionInfo.sortRevisionInfoByNumber(revisions);
-    for (int i = 0; i < revisions.length(); i++) {
-      if (revision.equals(revisions.get(i).name())) {
-        if (0 <= i + offset && i + offset < revisions.length()) {
-          Gerrit.display(
-              PageLinks.toChange(
-                  project,
-                  new PatchSet.Id(changeInfo.legacyId(), revisions.get(i + offset)._number())));
-          return;
-        }
-        return;
-      }
-    }
-  }
-
-  private void initIncludedInAction(ChangeInfo info) {
-    if (info.status() == Status.MERGED) {
-      includedInAction =
-          new IncludedInAction(
-              info.projectNameKey(), info.legacyId(), style, headerLine, includedIn);
-      includedIn.setVisible(true);
-    }
-  }
-
-  private void updatePatchSetsTextStyle(boolean isPatchSetCurrent) {
-    if (isPatchSetCurrent) {
-      patchSetsText.removeClassName(style.notCurrentPatchSet());
-    } else {
-      patchSetsText.addClassName(style.notCurrentPatchSet());
-    }
-  }
-
-  private void initRevisionsAction(ChangeInfo info, String revision) {
-    int currentPatchSet;
-    if (info.currentRevision() != null && info.revisions().containsKey(info.currentRevision())) {
-      currentPatchSet = info.revision(info.currentRevision())._number();
-    } else {
-      JsArray<RevisionInfo> revList = info.revisions().values();
-      RevisionInfo.sortRevisionInfoByNumber(revList);
-      currentPatchSet = revList.get(revList.length() - 1)._number();
-    }
-
-    String currentlyViewedPatchSet;
-    boolean isPatchSetCurrent = true;
-    String revisionId = info.revision(revision).id();
-    if (revisionId.equals("edit")) {
-      currentlyViewedPatchSet =
-          Resources.M.editPatchSet(RevisionInfo.findEditParent(info.revisions().values()));
-      currentPatchSet = info.revisions().values().length() - 1;
-    } else {
-      currentlyViewedPatchSet = revisionId;
-      if (!currentlyViewedPatchSet.equals(Integer.toString(currentPatchSet))) {
-        isPatchSetCurrent = false;
-      }
-    }
-    patchSetsText.setInnerText(Resources.M.patchSets(currentlyViewedPatchSet, currentPatchSet));
-    updatePatchSetsTextStyle(isPatchSetCurrent);
-    patchSetsAction =
-        new PatchSetsAction(
-            info.projectNameKey(), info.legacyId(), revision, edit, style, headerLine, patchSets);
-  }
-
-  private void initDownloadAction(ChangeInfo info, String revision) {
-    downloadAction = new DownloadAction(info, revision, style, headerLine, download);
-  }
-
-  private void initProjectLinks(ChangeInfo info) {
-    projectSettingsLink.setHref("#" + PageLinks.toProject(info.projectNameKey()));
-    projectSettings.addDomHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            if (Hyperlink.impl.handleAsClick((Event) event.getNativeEvent())) {
-              event.stopPropagation();
-              event.preventDefault();
-              Gerrit.display(PageLinks.toProject(info.projectNameKey()));
-            }
-          }
-        },
-        ClickEvent.getType());
-    projectDashboard.setText(info.project());
-    projectDashboard.setTargetHistoryToken(
-        PageLinks.toProjectDefaultDashboard(info.projectNameKey()));
-  }
-
-  private void initBranchLink(ChangeInfo info) {
-    branchLink.setText(info.branch());
-    branchLink.setTargetHistoryToken(
-        PageLinks.toChangeQuery(
-            BranchLink.query(info.projectNameKey(), info.status(), info.branch(), null)));
-  }
-
-  private void initEditMode(ChangeInfo info, String revision) {
-    if (Gerrit.isSignedIn()) {
-      RevisionInfo rev = info.revision(revision);
-      if (info.status().isOpen()) {
-        if (isEditModeEnabled(info, rev)) {
-          editMode.setVisible(fileTableMode == FileTable.Mode.REVIEW);
-          addFile.setVisible(!editMode.isVisible());
-          deleteFile.setVisible(!editMode.isVisible());
-          renameFile.setVisible(!editMode.isVisible());
-          reviewMode.setVisible(!editMode.isVisible());
-          addFileAction =
-              new AddFileAction(
-                  info.projectNameKey(), changeId, info.revision(revision), style, addFile, files);
-          deleteFileAction =
-              new DeleteFileAction(
-                  info.projectNameKey(), changeId, info.revision(revision), style, addFile);
-          renameFileAction =
-              new RenameFileAction(
-                  info.projectNameKey(), changeId, info.revision(revision), style, addFile);
-        } else {
-          editMode.setVisible(false);
-          addFile.setVisible(false);
-          reviewMode.setVisible(false);
-        }
-
-        if (rev.isEdit()) {
-          if (info.hasEditBasedOnCurrentPatchSet()) {
-            publishEdit.setVisible(true);
-          } else {
-            rebaseEdit.setVisible(true);
-          }
-          deleteEdit.setVisible(true);
-        }
-      } else if (rev.isEdit()) {
-        deleteEdit.setStyleName(style.highlight());
-        deleteEdit.setVisible(true);
-      }
-    }
-  }
-
-  private boolean isEditModeEnabled(ChangeInfo info, RevisionInfo rev) {
-    if (rev.isEdit()) {
-      return true;
-    }
-    if (edit == null) {
-      return revision.equals(info.currentRevision());
-    }
-    return rev._number() == RevisionInfo.findEditParent(info.revisions().values());
-  }
-
-  @UiHandler("publishEdit")
-  void onPublishEdit(@SuppressWarnings("unused") ClickEvent e) {
-    EditActions.publishEdit(getProject(), changeId, publishEdit, rebaseEdit, deleteEdit);
-  }
-
-  @UiHandler("rebaseEdit")
-  void onRebaseEdit(@SuppressWarnings("unused") ClickEvent e) {
-    EditActions.rebaseEdit(getProject(), changeId, publishEdit, rebaseEdit, deleteEdit);
-  }
-
-  @UiHandler("deleteEdit")
-  void onDeleteEdit(@SuppressWarnings("unused") ClickEvent e) {
-    if (Window.confirm(Resources.C.deleteChangeEdit())) {
-      EditActions.deleteEdit(getProject(), changeId, publishEdit, rebaseEdit, deleteEdit);
-    }
-  }
-
-  @Override
-  public void registerKeys() {
-    super.registerKeys();
-
-    KeyCommandSet keysNavigation = new KeyCommandSet(Gerrit.C.sectionNavigation());
-    keysNavigation.add(
-        new KeyCommand(0, 'u', Util.C.upToChangeList()) {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            Gerrit.displayLastChangeList();
-          }
-        });
-    keysNavigation.add(
-        new KeyCommand(0, 'R', Util.C.keyReloadChange()) {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            Gerrit.display(PageLinks.toChange(project, changeId));
-          }
-        });
-    keysNavigation.add(
-        new KeyCommand(0, 'n', Util.C.keyNextPatchSet()) {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            gotoSibling(1);
-          }
-        },
-        new KeyCommand(0, 'p', Util.C.keyPreviousPatchSet()) {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            gotoSibling(-1);
-          }
-        });
-    handlers.add(GlobalKey.add(this, keysNavigation));
-
-    KeyCommandSet keysAction = new KeyCommandSet(Gerrit.C.sectionActions());
-    keysAction.add(
-        new KeyCommand(0, 'a', Util.C.keyPublishComments()) {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            if (Gerrit.isSignedIn()) {
-              onReply(null);
-            } else {
-              Gerrit.doSignIn(getToken());
-            }
-          }
-        });
-    keysAction.add(
-        new KeyCommand(0, 'x', Util.C.keyExpandAllMessages()) {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            onExpandAll(null);
-          }
-        });
-    keysAction.add(
-        new KeyCommand(0, 'z', Util.C.keyCollapseAllMessages()) {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            onCollapseAll(null);
-          }
-        });
-    keysAction.add(
-        new KeyCommand(0, 's', Util.C.changeTableStar()) {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            if (Gerrit.isSignedIn()) {
-              star.setValue(!star.getValue(), true);
-            } else {
-              Gerrit.doSignIn(getToken());
-            }
-          }
-        });
-    keysAction.add(
-        new KeyCommand(0, 'c', Util.C.keyAddReviewers()) {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            if (Gerrit.isSignedIn()) {
-              reviewers.onOpenForm();
-            } else {
-              Gerrit.doSignIn(getToken());
-            }
-          }
-        });
-    keysAction.add(
-        new KeyCommand(0, 't', Util.C.keyEditTopic()) {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            if (Gerrit.isSignedIn()) {
-              // In Firefox this event is mistakenly called when F5 is pressed so
-              // differentiate F5 from 't' by checking the charCode(F5=0, t=116).
-              if (event.getNativeEvent().getCharCode() == 0) {
-                Window.Location.reload();
-                return;
-              }
-              if (topic.canEdit()) {
-                topic.onEdit();
-              }
-            } else {
-              Gerrit.doSignIn(getToken());
-            }
-          }
-        });
-    handlers.add(GlobalKey.add(this, keysAction));
-    files.registerKeys();
-  }
-
-  @Override
-  public void onShowView() {
-    super.onShowView();
-    commit.onShowView();
-    related.setMaxHeight(commit.getElement().getParentElement().getOffsetHeight());
-
-    if (openReplyBox) {
-      onReply();
-    } else {
-      String prior = Gerrit.getPriorView();
-      if (prior != null && prior.startsWith("/c/")) {
-        scrollToPath(prior.substring(3));
-      }
-    }
-
-    ChangeGlue.fireShowChange(changeInfo, changeInfo.revision(revision));
-    CodeMirror.preload();
-    startPoller();
-  }
-
-  private void scrollToPath(String token) {
-    ProjectChangeId cId;
-    try {
-      cId = ProjectChangeId.create(token);
-    } catch (IllegalArgumentException e) {
-      // Scrolling is best-effort.
-      return;
-    }
-    if (!changeId.equals(cId.getChangeId())) {
-      return; // Unrelated URL, do not scroll.
-    }
-
-    // Extract the start of a file path. The patch set is always contained in the URL and separated
-    // by from the changeId by a forward slash. Example: /c/project/+/123/1/folder/file.txt
-    int s = token.indexOf('/', cId.identifierLength() + 1);
-    if (s < 0) {
-      return; // URL does not name a file.
-    }
-
-    int c = token.lastIndexOf(',');
-    if (0 <= c) {
-      token = token.substring(s + 1, c);
-    } else {
-      token = token.substring(s + 1);
-    }
-
-    if (!token.isEmpty()) {
-      files.scrollToPath(KeyUtil.decode(token));
-    }
-  }
-
-  @UiHandler("star")
-  void onToggleStar(ValueChangeEvent<Boolean> e) {
-    StarredChanges.toggleStar(changeId, e.getValue());
-  }
-
-  @UiHandler("includedIn")
-  void onIncludedIn(@SuppressWarnings("unused") ClickEvent e) {
-    includedInAction.show();
-  }
-
-  @UiHandler("download")
-  void onDownload(@SuppressWarnings("unused") ClickEvent e) {
-    downloadAction.show();
-  }
-
-  @UiHandler("patchSets")
-  void onPatchSets(@SuppressWarnings("unused") ClickEvent e) {
-    patchSetsAction.show();
-  }
-
-  @UiHandler("reply")
-  void onReply(@SuppressWarnings("unused") ClickEvent e) {
-    onReply();
-  }
-
-  @UiHandler("permalink")
-  void onReload(ClickEvent e) {
-    e.preventDefault();
-    Gerrit.display(PageLinks.toChange(project, changeId));
-  }
-
-  private void onReply() {
-    if (Gerrit.isSignedIn()) {
-      replyAction.onReply(null);
-    } else {
-      Gerrit.doSignIn(getToken());
-    }
-  }
-
-  @UiHandler("openAll")
-  void onOpenAll(@SuppressWarnings("unused") ClickEvent e) {
-    files.openAll();
-  }
-
-  @UiHandler("editMode")
-  void onEditMode(@SuppressWarnings("unused") ClickEvent e) {
-    fileTableMode = FileTable.Mode.EDIT;
-    refreshFileTable();
-    editMode.setVisible(false);
-    addFile.setVisible(true);
-    deleteFile.setVisible(true);
-    renameFile.setVisible(true);
-    reviewMode.setVisible(true);
-  }
-
-  @UiHandler("reviewMode")
-  void onReviewMode(@SuppressWarnings("unused") ClickEvent e) {
-    fileTableMode = FileTable.Mode.REVIEW;
-    refreshFileTable();
-    editMode.setVisible(true);
-    addFile.setVisible(false);
-    deleteFile.setVisible(false);
-    renameFile.setVisible(false);
-    reviewMode.setVisible(false);
-  }
-
-  @UiHandler("addFile")
-  void onAddFile(@SuppressWarnings("unused") ClickEvent e) {
-    addFileAction.onEdit();
-  }
-
-  @UiHandler("deleteFile")
-  void onDeleteFile(@SuppressWarnings("unused") ClickEvent e) {
-    deleteFileAction.onDelete();
-  }
-
-  @UiHandler("renameFile")
-  void onRenameFile(@SuppressWarnings("unused") ClickEvent e) {
-    renameFileAction.onRename();
-  }
-
-  private void refreshFileTable() {
-    int idx = diffBase.getSelectedIndex();
-    if (0 <= idx) {
-      String n = diffBase.getValue(idx);
-      loadConfigInfo(changeInfo, DiffObject.parse(changeInfo.legacyId(), n));
-    }
-  }
-
-  @UiHandler("showTaggedComments")
-  void onShowTaggedComments(@SuppressWarnings("unused") ClickEvent e) {
-    showTaggedComments.setVisible(false);
-    hideTaggedComments.setVisible(true);
-    int n = history.getWidgetCount();
-    for (int i = 0; i < n; i++) {
-      Message m = ((Message) history.getWidget(i));
-      m.setVisible(true);
-    }
-  }
-
-  @UiHandler("hideTaggedComments")
-  void onHideTaggedComments(@SuppressWarnings("unused") ClickEvent e) {
-    hideTaggedComments.setVisible(false);
-    showTaggedComments.setVisible(true);
-    int n = history.getWidgetCount();
-    for (int i = 0; i < n; i++) {
-      Message m = ((Message) history.getWidget(i));
-      if (m.getMessageInfo().tag() != null) {
-        m.setVisible(false);
-      }
-    }
-  }
-
-  @UiHandler("expandAll")
-  void onExpandAll(@SuppressWarnings("unused") ClickEvent e) {
-    int n = history.getWidgetCount();
-    for (int i = 0; i < n; i++) {
-      ((Message) history.getWidget(i)).setOpen(true);
-    }
-    expandAll.setVisible(false);
-    collapseAll.setVisible(true);
-  }
-
-  @UiHandler("collapseAll")
-  void onCollapseAll(@SuppressWarnings("unused") ClickEvent e) {
-    int n = history.getWidgetCount();
-    for (int i = 0; i < n; i++) {
-      ((Message) history.getWidget(i)).setOpen(false);
-    }
-    expandAll.setVisible(true);
-    collapseAll.setVisible(false);
-  }
-
-  @UiHandler("diffBase")
-  void onChangeRevision(@SuppressWarnings("unused") ChangeEvent e) {
-    int idx = diffBase.getSelectedIndex();
-    if (0 <= idx) {
-      String n = diffBase.getValue(idx);
-      loadConfigInfo(changeInfo, DiffObject.parse(changeInfo.legacyId(), n));
-    }
-  }
-
-  private void loadConfigInfo(ChangeInfo info, DiffObject base) {
-    final RevisionInfo rev = info.revision(revision);
-    if (base.isAutoMerge() && !initCurrentRevision(info).isMerge()) {
-      Gerrit.display(getToken(), new NotFoundScreen());
-    }
-
-    updateToken(info, base, rev);
-
-    RevisionInfo baseRev = resolveRevisionOrPatchSetId(info, base.asString(), null);
-
-    CallbackGroup group = new CallbackGroup();
-    Timestamp lastReply = myLastReply(info);
-    if (rev.isEdit()) {
-      // Comments are filtered for the current revision. Use parent
-      // patch set for edits, as edits themself can never have comments.
-      RevisionInfo p = RevisionInfo.findEditParentRevision(info.revisions().values());
-      List<NativeMap<JsArray<CommentInfo>>> comments = loadComments(p, group);
-      loadFileList(base, baseRev, rev, lastReply, group, comments, null);
-    } else {
-      loadDiff(base, baseRev, rev, lastReply, group);
-    }
-    group.addListener(
-        new AsyncCallback<Void>() {
-          @Override
-          public void onSuccess(Void result) {
-            loadConfigInfo(info, rev);
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            logger.log(
-                Level.SEVERE,
-                "Loading file list and inline comments failed: " + caught.getMessage());
-            loadConfigInfo(info, rev);
-          }
-        });
-    group.done();
-  }
-
-  private void loadConfigInfo(ChangeInfo info, RevisionInfo rev) {
-    if (loaded) {
-      return;
-    }
-
-    RevisionInfoCache.add(changeId, rev);
-    ConfigInfoCache.add(info);
-    ConfigInfoCache.get(
-        info.projectNameKey(),
-        new ScreenLoadCallback<ConfigInfoCache.Entry>(this) {
-          @Override
-          protected void preDisplay(Entry result) {
-            loaded = true;
-            commentLinkProcessor = result.getCommentLinkProcessor();
-            setTheme(result.getTheme());
-            renderChangeInfo(info);
-            loadRevisionInfo();
-          }
-        });
-    ConfigInfoCache.get(
-        info.projectNameKey(),
-        new GerritCallback<Entry>() {
-          @Override
-          public void onSuccess(Entry entry) {
-            addExtensionPoints(info, rev, entry);
-          }
-        });
-  }
-
-  private void updateToken(ChangeInfo info, DiffObject base, RevisionInfo rev) {
-    StringBuilder token =
-        new StringBuilder("/c/")
-            .append(PageLinks.toChangeId(info.projectNameKey(), info.legacyId()))
-            .append("/");
-    if (base.asString() != null) {
-      token.append(base.asString()).append("..");
-    }
-    if (base.asString() != null || !rev.name().equals(info.currentRevision())) {
-      token.append(rev._number());
-    }
-    setToken(token.toString());
-  }
-
-  static Timestamp myLastReply(ChangeInfo info) {
-    if (Gerrit.isSignedIn() && info.messages() != null) {
-      int self = Gerrit.getUserAccount()._accountId();
-      for (int i = info.messages().length() - 1; i >= 0; i--) {
-        MessageInfo m = info.messages().get(i);
-        if (m.author() != null && m.author()._accountId() == self) {
-          return m.date();
-        }
-      }
-    }
-    return null;
-  }
-
-  private void loadDiff(
-      DiffObject base,
-      RevisionInfo baseRev,
-      RevisionInfo rev,
-      Timestamp myLastReply,
-      CallbackGroup group) {
-    List<NativeMap<JsArray<CommentInfo>>> comments = loadComments(rev, group);
-    List<NativeMap<JsArray<CommentInfo>>> drafts = loadDrafts(rev, group);
-    loadFileList(base, baseRev, rev, myLastReply, group, comments, drafts);
-
-    if (Gerrit.isSignedIn() && fileTableMode == FileTable.Mode.REVIEW) {
-      ChangeApi.revision(getProject().get(), changeId.get(), rev.name())
-          .view("files")
-          .addParameterTrue("reviewed")
-          .get(
-              group.add(
-                  new AsyncCallback<JsArrayString>() {
-                    @Override
-                    public void onSuccess(JsArrayString result) {
-                      files.markReviewed(result);
-                    }
-
-                    @Override
-                    public void onFailure(Throwable caught) {}
-                  }));
-    }
-  }
-
-  private void loadFileList(
-      final DiffObject base,
-      final RevisionInfo baseRev,
-      final RevisionInfo rev,
-      final Timestamp myLastReply,
-      CallbackGroup group,
-      final List<NativeMap<JsArray<CommentInfo>>> comments,
-      final List<NativeMap<JsArray<CommentInfo>>> drafts) {
-    DiffApi.list(
-        getProject().get(),
-        changeId.get(),
-        rev.name(),
-        baseRev,
-        group.add(
-            new AsyncCallback<NativeMap<FileInfo>>() {
-              @Override
-              public void onSuccess(NativeMap<FileInfo> m) {
-                files.set(
-                    base,
-                    new PatchSet.Id(changeId, rev._number()),
-                    getProject(),
-                    style,
-                    reply,
-                    fileTableMode,
-                    edit != null);
-                files.setValue(
-                    m,
-                    myLastReply,
-                    comments != null ? comments.get(0) : null,
-                    drafts != null ? drafts.get(0) : null);
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {
-                files.showError(caught);
-              }
-            }));
-  }
-
-  private List<NativeMap<JsArray<CommentInfo>>> loadComments(
-      final RevisionInfo rev, CallbackGroup group) {
-    final List<NativeMap<JsArray<CommentInfo>>> r = new ArrayList<>(1);
-    // TODO(dborowitz): Could eliminate this call by adding an option to include
-    // inline comments in the change detail.
-    ChangeApi.comments(getProject().get(), changeId.get())
-        .get(
-            group.add(
-                new AsyncCallback<NativeMap<JsArray<CommentInfo>>>() {
-                  @Override
-                  public void onSuccess(NativeMap<JsArray<CommentInfo>> result) {
-                    // Return value is used for populating the file table, so only count
-                    // comments for the current revision. Still include all comments in
-                    // the history table.
-                    r.add(filterForRevision(result, rev._number()));
-                    history.addComments(result);
-                  }
-
-                  @Override
-                  public void onFailure(Throwable caught) {}
-                }));
-    return r;
-  }
-
-  private static NativeMap<JsArray<CommentInfo>> filterForRevision(
-      NativeMap<JsArray<CommentInfo>> comments, int id) {
-    NativeMap<JsArray<CommentInfo>> filtered = NativeMap.create();
-    for (String k : comments.keySet()) {
-      JsArray<CommentInfo> allRevisions = comments.get(k);
-      JsArray<CommentInfo> thisRevision = JsArray.createArray().cast();
-      for (int i = 0; i < allRevisions.length(); i++) {
-        CommentInfo c = allRevisions.get(i);
-        if (c.patchSet() == id) {
-          thisRevision.push(c);
-        }
-      }
-      filtered.put(k, thisRevision);
-    }
-    return filtered;
-  }
-
-  private List<NativeMap<JsArray<CommentInfo>>> loadDrafts(RevisionInfo rev, CallbackGroup group) {
-    final List<NativeMap<JsArray<CommentInfo>>> r = new ArrayList<>(1);
-    if (Gerrit.isSignedIn()) {
-      ChangeApi.revision(getProject().get(), changeId.get(), rev.name())
-          .view("drafts")
-          .get(
-              group.add(
-                  new AsyncCallback<NativeMap<JsArray<CommentInfo>>>() {
-                    @Override
-                    public void onSuccess(NativeMap<JsArray<CommentInfo>> result) {
-                      r.add(result);
-                    }
-
-                    @Override
-                    public void onFailure(Throwable caught) {}
-                  }));
-    } else {
-      r.add(NativeMap.<JsArray<CommentInfo>>create());
-    }
-    return r;
-  }
-
-  private void loadCommit(RevisionInfo rev, CallbackGroup group) {
-    if (rev.isEdit() || rev.commit() != null) {
-      return;
-    }
-
-    ChangeApi.commitWithLinks(
-        getProject().get(),
-        changeId.get(),
-        rev.name(),
-        group.add(
-            new AsyncCallback<CommitInfo>() {
-              @Override
-              public void onSuccess(CommitInfo info) {
-                rev.setCommit(info);
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {}
-            }));
-  }
-
-  private void renderSubmitType(Change.Status status, boolean canSubmit, SubmitType submitType) {
-    if (status == Change.Status.NEW && !changeInfo.isWorkInProgress()) {
-      if (canSubmit) {
-        statusText.setInnerText(
-            changeInfo.mergeable() ? Util.C.readyToSubmit() : Util.C.mergeConflict());
-      }
-      setVisible(notMergeable, !changeInfo.mergeable());
-    }
-    submitActionText.setInnerText(com.google.gerrit.client.admin.Util.toLongString(submitType));
-  }
-
-  private RevisionInfo resolveRevisionToDisplay(ChangeInfo info) {
-    RevisionInfo rev = resolveRevisionOrPatchSetId(info, revision, info.currentRevision());
-    if (rev != null) {
-      revision = rev.name();
-      return rev;
-    }
-
-    // the revision is not visible to the calling user (maybe it is a draft?)
-    // or the change is corrupt, take the last revision that was returned,
-    // if no revision was returned display an error
-    JsArray<RevisionInfo> revisions = info.revisions().values();
-    if (revisions.length() > 0) {
-      RevisionInfo.sortRevisionInfoByNumber(revisions);
-      rev = revisions.get(revisions.length() - 1);
-      revision = rev.name();
-      return rev;
-    }
-    new ErrorDialog(Resources.M.changeWithNoRevisions(info.legacyId().get())).center();
-    throw new IllegalStateException("no revision, cannot proceed");
-  }
-
-  /**
-   * Resolve a revision or patch set id string to RevisionInfo. When this view is created from the
-   * changes table, revision is passed as a real revision. When this view is created from side by
-   * side (by closing it with 'u') patch set id is passed.
-   *
-   * @param info change info
-   * @param revOrId revision or patch set id
-   * @param defaultValue value returned when revOrId is null
-   * @return resolved revision or default value
-   */
-  private RevisionInfo resolveRevisionOrPatchSetId(
-      ChangeInfo info, String revOrId, String defaultValue) {
-    int parentNum;
-    if (revOrId == null) {
-      revOrId = defaultValue;
-    } else if ((parentNum = toParentNum(revOrId)) > 0) {
-      CommitInfo commitInfo = info.revision(revision).commit();
-      JsArray<CommitInfo> parents = commitInfo.parents();
-      if (parents.length() >= parentNum) {
-        return RevisionInfo.forParent(-parentNum, parents.get(parentNum - 1));
-      }
-    } else if (!info.revisions().containsKey(revOrId)) {
-      JsArray<RevisionInfo> list = info.revisions().values();
-      for (int i = 0; i < list.length(); i++) {
-        RevisionInfo r = list.get(i);
-        if (revOrId.equals(String.valueOf(r._number()))) {
-          revOrId = r.name();
-          break;
-        }
-      }
-    }
-    return revOrId != null ? info.revision(revOrId) : null;
-  }
-
-  private boolean isSubmittable(ChangeInfo info) {
-    boolean canSubmit = info.status().isOpen() && revision.equals(info.currentRevision());
-    if (canSubmit && info.status() == Change.Status.NEW) {
-      for (String name : info.labels()) {
-        LabelInfo label = info.label(name);
-        switch (label.status()) {
-          case NEED:
-            statusText.setInnerText(Util.M.needs(name));
-            canSubmit = false;
-            break;
-          case REJECT:
-          case IMPOSSIBLE:
-            if (label.blocking()) {
-              statusText.setInnerText(Util.M.blockedOn(name));
-              canSubmit = false;
-            }
-            break;
-          case MAY:
-          case OK:
-          default:
-            break;
-        }
-      }
-    }
-    return canSubmit;
-  }
-
-  private void renderChangeInfo(ChangeInfo info) {
-    RevisionInfo revisionInfo = info.revision(revision);
-    changeInfo = info;
-    lastDisplayedUpdate = info.updated();
-
-    labels.set(info);
-
-    renderOwner(info);
-    renderUploader(info, revisionInfo);
-    renderActionTextDate(info);
-    renderDiffBaseListBox(info);
-    initReplyButton(info, revision);
-    initIncludedInAction(info);
-    initDownloadAction(info, revision);
-    initProjectLinks(info);
-    initBranchLink(info);
-    initEditMode(info, revision);
-    actions.display(info, revision);
-
-    star.setValue(info.starred());
-    permalink.setHref(ChangeLink.permalink(changeId));
-    permalink.setText(String.valueOf(info.legacyId()));
-    topic.set(info, revision);
-    commit.set(commentLinkProcessor, info, revision);
-    related.set(info, revision);
-    reviewers.set(info);
-    assignee.set(info);
-    if (Gerrit.isNoteDbEnabled()) {
-      hashtags.set(info, revision);
-    } else {
-      setVisible(hashtagTableRow, false);
-    }
-
-    StringBuilder sb = new StringBuilder();
-    sb.append(Util.M.changeScreenTitleId(info.idAbbreviated()));
-    if (info.subject() != null) {
-      sb.append(": ");
-      sb.append(info.subject());
-    }
-    setWindowTitle(sb.toString());
-
-    // Although this is related to the revision, we can process it early to
-    // render it faster.
-    if (!info.status().isOpen()
-        || !revision.equals(info.currentRevision())
-        || revisionInfo.isEdit()) {
-      setVisible(strategy, false);
-    }
-
-    // Properly render revision actions initially while waiting for
-    // the callback to populate them correctly.
-    NativeMap<ActionInfo> emptyMap = NativeMap.<ActionInfo>create();
-    initRevisionsAction(info, revision);
-    quickApprove.setVisible(false);
-    actions.reloadRevisionActions(emptyMap);
-
-    boolean current = revision.equals(info.currentRevision()) && !revisionInfo.isEdit();
-
-    if (revisionInfo.isEdit()) {
-      statusText.setInnerText(Util.C.changeEdit());
-    } else if (!current) {
-      statusText.setInnerText(Util.C.notCurrent());
-      labels.setVisible(false);
-    } else {
-      statusText.setInnerText(Util.toLongString(info.status()));
-    }
-
-    if (info.isPrivate()) {
-      privateText.setInnerText(Util.C.isPrivate());
-    }
-
-    if (info.isWorkInProgress()) {
-      wipText.setInnerText(Util.C.isWorkInProgress());
-    }
-
-    if (Gerrit.isSignedIn()) {
-      replyAction =
-          new ReplyAction(
-              info, revision, hasDraftComments, style, commentLinkProcessor, reply, quickApprove);
-    }
-    history.set(commentLinkProcessor, replyAction, changeId, info);
-
-    if (current && info.status().isOpen()) {
-      quickApprove.set(info, revision, replyAction);
-      renderSubmitType(info.status(), isSubmittable(info), info.submitType());
-    } else {
-      quickApprove.setVisible(false);
-    }
-  }
-
-  private void renderRevisionInfo(ChangeInfo info, NativeMap<ActionInfo> actionMap) {
-    initRevisionsAction(info, revision);
-    commit.setParentNotCurrent(
-        actionMap.containsKey("rebase") && actionMap.get("rebase").enabled());
-    actions.reloadRevisionActions(actionMap);
-  }
-
-  private void renderOwner(ChangeInfo info) {
-    // TODO info card hover
-    String name = name(info.owner());
-    if (info.owner().avatar(AvatarInfo.DEFAULT_SIZE) != null) {
-      ownerPanel.insert(new AvatarImage(info.owner()), 0);
-    }
-    ownerLink.setText(name);
-    ownerLink.setTitle(email(info.owner(), name));
-    ownerLink.setTargetHistoryToken(
-        PageLinks.toAccountQuery(
-            info.owner().name() != null
-                ? info.owner().name()
-                : info.owner().email() != null
-                    ? info.owner().email()
-                    : String.valueOf(info.owner()._accountId()),
-            Change.Status.NEW));
-  }
-
-  private void renderUploader(ChangeInfo changeInfo, RevisionInfo revInfo) {
-    AccountInfo uploader = revInfo.uploader();
-    boolean isOwner = uploader == null || uploader._accountId() == changeInfo.owner()._accountId();
-    renderPushCertificate(revInfo, isOwner ? ownerPanel : uploaderPanel);
-    if (isOwner) {
-      uploaderRow.getStyle().setDisplay(Display.NONE);
-      return;
-    }
-    uploaderRow.getStyle().setDisplay(Display.TABLE_ROW);
-
-    if (uploader.avatar(AvatarInfo.DEFAULT_SIZE) != null) {
-      uploaderPanel.insert(new AvatarImage(uploader), 0);
-    }
-    String name = name(uploader);
-    uploaderName.setText(name);
-    uploaderName.setTitle(email(uploader, name));
-  }
-
-  private void renderPushCertificate(RevisionInfo revInfo, FlowPanel panel) {
-    if (!enableSignedPush()) {
-      return;
-    }
-    Image status = new Image();
-    panel.add(status);
-    status.setStyleName(style.pushCertStatus());
-    if (!revInfo.hasPushCertificate() || revInfo.pushCertificate().key() == null) {
-      status.setResource(Gerrit.RESOURCES.question());
-      status.setTitle(Util.C.pushCertMissing());
-      return;
-    }
-    PushCertificateInfo certInfo = revInfo.pushCertificate();
-    GpgKeyInfo.Status s = certInfo.key().status();
-    switch (s) {
-      case BAD:
-        status.setResource(Gerrit.RESOURCES.redNot());
-        status.setTitle(problems(Util.C.pushCertBad(), certInfo));
-        break;
-      case OK:
-        status.setResource(Gerrit.RESOURCES.warning());
-        status.setTitle(problems(Util.C.pushCertOk(), certInfo));
-        break;
-      case TRUSTED:
-        status.setResource(Gerrit.RESOURCES.greenCheck());
-        status.setTitle(Util.C.pushCertTrusted());
-        break;
-    }
-  }
-
-  private static String name(AccountInfo info) {
-    return info.name() != null ? info.name() : Gerrit.info().user().anonymousCowardName();
-  }
-
-  private static String email(AccountInfo info, String name) {
-    return info.email() != null ? info.email() : name;
-  }
-
-  private static String problems(String msg, PushCertificateInfo info) {
-    if (info.key() == null || !info.key().hasProblems() || info.key().problems().length() == 0) {
-      return msg;
-    }
-
-    StringBuilder sb = new StringBuilder();
-    sb.append(msg).append(':');
-    for (String problem : Natives.asList(info.key().problems())) {
-      sb.append('\n').append(problem);
-    }
-    return sb.toString();
-  }
-
-  private void renderActionTextDate(ChangeInfo info) {
-    String action;
-    if (info.created().equals(info.updated())) {
-      action = Util.C.changeInfoBlockUploaded();
-    } else {
-      action = Util.C.changeInfoBlockUpdated();
-    }
-    actionText.setInnerText(action);
-    actionDate.setInnerText(FormatUtil.relativeFormat(info.updated()));
-  }
-
-  private void renderDiffBaseListBox(ChangeInfo info) {
-    JsArray<RevisionInfo> list = info.revisions().values();
-    RevisionInfo.sortRevisionInfoByNumber(list);
-    int selectedIdx = list.length();
-    for (int i = list.length() - 1; i >= 0; i--) {
-      RevisionInfo r = list.get(i);
-      diffBase.addItem(r.id() + ": " + r.name().substring(0, 6), r.id());
-      if (r.name().equals(revision)) {
-        SelectElement.as(diffBase.getElement())
-            .getOptions()
-            .getItem(diffBase.getItemCount() - 1)
-            .setDisabled(true);
-      }
-      if (base.isPatchSet() && base.asPatchSetId().get() == r._number()) {
-        selectedIdx = diffBase.getItemCount() - 1;
-      }
-    }
-
-    RevisionInfo rev = info.revisions().get(revision);
-    JsArray<CommitInfo> parents = rev.commit().parents();
-    if (parents.length() > 1) {
-      diffBase.addItem(Util.C.autoMerge(), DiffObject.AUTO_MERGE);
-      for (int i = 0; i < parents.length(); i++) {
-        int parentNum = i + 1;
-        diffBase.addItem(Util.M.diffBaseParent(parentNum), String.valueOf(-parentNum));
-      }
-
-      if (base.isParent()) {
-        selectedIdx = list.length() + base.getParentNum();
-      }
-    } else {
-      diffBase.addItem(Util.C.baseDiffItem(), "");
-    }
-
-    diffBase.setSelectedIndex(selectedIdx);
-  }
-
-  void showUpdates(ChangeInfo newInfo) {
-    if (!isAttached() || newInfo.updated().equals(lastDisplayedUpdate)) {
-      return;
-    }
-
-    JsArray<MessageInfo> om = changeInfo.messages();
-    JsArray<MessageInfo> nm = newInfo.messages();
-
-    if (om == null) {
-      om = JsArray.createArray().cast();
-    }
-    if (nm == null) {
-      nm = JsArray.createArray().cast();
-    }
-
-    if (om.length() == nm.length()) {
-      return;
-    }
-
-    if (updateAvailable == null) {
-      updateAvailable =
-          new UpdateAvailableBar() {
-            @Override
-            void onShow() {
-              Gerrit.display(PageLinks.toChange(project, changeId));
-            }
-
-            @Override
-            void onIgnore(Timestamp newTime) {
-              lastDisplayedUpdate = newTime;
-            }
-          };
-    }
-    updateAvailable.set(Natives.asList(nm).subList(om.length(), nm.length()), newInfo.updated());
-    if (!updateAvailable.isAttached()) {
-      add(updateAvailable);
-    }
-  }
-
-  private void startPoller() {
-    if (Gerrit.isSignedIn() && 0 < Gerrit.info().change().updateDelay()) {
-      updateCheck = new UpdateCheckTimer(this);
-      updateCheck.schedule();
-      handlers.add(UserActivityMonitor.addValueChangeHandler(updateCheck));
-    }
-  }
-
-  private static String normalize(String r) {
-    return r != null && !r.isEmpty() ? r : null;
-  }
-
-  /**
-   * @param parentToken
-   * @return 1-based parentNum if parentToken is a String which can be parsed as a negative integer
-   *     i.e. "-1", "-2", etc. If parentToken cannot be parsed as a negative integer, return zero.
-   */
-  private static int toParentNum(String parentToken) {
-    try {
-      int n = Integer.parseInt(parentToken);
-      if (n < 0) {
-        return -n;
-      }
-      return 0;
-    } catch (NumberFormatException e) {
-      return 0;
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.ui.xml
deleted file mode 100644
index d629fc2..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.ui.xml
+++ /dev/null
@@ -1,634 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:c='urn:import:com.google.gerrit.client.change'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'
-    xmlns:x='urn:import:com.google.gerrit.client.ui'>
-  <ui:with field='ico' type='com.google.gerrit.client.GerritResources'/>
-  <ui:with field='res' type='com.google.gerrit.client.change.Resources'/>
-  <ui:style gss='false' type='com.google.gerrit.client.change.ChangeScreen.Style'>
-    @eval textColor com.google.gerrit.client.Gerrit.getTheme().textColor;
-    @eval trimColor com.google.gerrit.client.Gerrit.getTheme().trimColor;
-
-    @def COMMIT_WIDTH 560px;
-    @def HEADER_HEIGHT 30px;
-
-    @def BUTTON_HEIGHT 14px;
-
-    .cs2 {
-      margin-bottom: 1em;
-    }
-
-    .headerLine {
-      position: relative;
-      background-color: trimColor;
-      height: HEADER_HEIGHT;
-      margin: 0 -5px;
-      padding: 0 5px;
-    }
-
-    .subjectLine {
-      position: relative;
-      width: COMMIT_WIDTH;
-      height: HEADER_HEIGHT;
-      background-color: trimColor;
-      color: textColor;
-      font-family: sans-serif;
-    }
-    .subjectText {
-      width: 460px;
-      height: HEADER_HEIGHT;
-      line-height: HEADER_HEIGHT;
-      overflow: hidden;
-      text-overflow: ellipsis;
-      white-space: nowrap;
-    }
-
-    .infoLine {
-      position: absolute;
-      top: 0;
-      left: COMMIT_WIDTH;
-      height: HEADER_HEIGHT;
-      padding-left: 25px;
-    }
-
-    .infoLineHeaderButtons {
-      display: inline-block;
-      height: HEADER_HEIGHT;
-    }
-    .statusRight {
-      position: absolute;
-      top: 0;
-      right: 0;
-      height: HEADER_HEIGHT;
-    }
-    .idAndStatus {
-      display: inline-block;
-      position: relative;
-      height: HEADER_HEIGHT;
-    }
-    .star {
-      position: absolute;
-      top: 5px;
-      right: 2px;
-      cursor: pointer;
-      outline: none;
-    }
-    .changeId {
-      width: 300px;
-      white-space: nowrap;
-      line-height: HEADER_HEIGHT;
-      overflow: hidden;
-      text-overflow: ellipsis;
-    }
-    .statusText {
-      font-weight: bold;
-    }
-    .privateText {
-      font-weight: bold;
-    }
-
-    .wipText {
-      font-weight: bold;
-    }
-
-    div.popdown {
-      display: inline-block;
-      margin-top: 2px;
-      margin-left: 5px;
-      margin-right: 25px;
-    }
-
-    .popdown button {
-      cursor: pointer;
-      height: 25px;
-      border: none;
-      background-color: trimColor;
-      margin: 0 0 0 -2px;
-      padding-left: 2px;
-      padding-right: 2px;
-      min-width: 100px;
-    }
-    .popdown button div {
-      padding-left: 6px;
-      padding-right: 6px;
-    }
-    .popdown button div:after {
-      content: " \25bc";
-    }
-    .popdown button.selected {
-      font-weight: bold;
-    }
-    .popdown button:focus {
-      outline: none;
-    }
-
-    .headerButtons button:disabled,
-    #change_infoTable button:disabled,
-    .popdown button:disabled {
-      background-color: #999;
-      background-image: -webkit-linear-gradient(top, #999, #999);
-    }
-
-    .infoTable {
-      border-spacing: 0;
-    }
-
-    .infoTable th {
-      width: 60px;
-      color: #444;
-      font-weight: normal;
-      vertical-align: top;
-      text-align: left;
-      padding: 0 5px 0 0;
-    }
-
-    .projectSettings {
-      float: right;
-      cursor: pointer;
-    }
-
-    .infoColumn {
-      width: 440px;
-      padding-left: 17px;
-      padding-right: 17px;
-      vertical-align: top;
-    }
-
-    #change_infoTable {
-      border-spacing: 0;
-      width: 100%;
-      margin-left: 2px;
-      margin-right: 5px;
-    }
-
-    .notMergeable {
-      float: right;
-      font-weight: bold;
-      color: #d00;
-    }
-
-    .commitColumn, .relatedColumn {
-      padding: 0;
-      vertical-align: top;
-    }
-    .commitColumn { width: COMMIT_WIDTH; }
-    .relatedColumn { width: 375px; }
-
-    .labels {
-      border-spacing: 0;
-      padding: 0;
-    }
-    .labelName {
-      color: #444;
-      vertical-align: top;
-      text-align: left;
-      padding-top: 3px;
-      padding-right: 5px;
-      white-space: nowrap;
-    }
-
-    .label_user {
-      display: inline-block;
-      margin-bottom: 2px;
-      padding: 1px 3px 0px 3px;
-      border-radius: 5px;
-      -webkit-border-radius: 5px;
-      background: trimColor;
-      border: 1px solid trimColor;
-      white-space: nowrap;
-    }
-    .label_user img.avatar {
-      margin: 0 2px 0 0;
-      width: 16px;
-      height: 16px;
-      vertical-align: bottom;
-    }
-    .label_user button {
-      cursor: pointer;
-      padding: 0;
-      margin: 0 0 0 5px;
-      border: 0;
-      background-color: transparent;
-      white-space: nowrap;
-    }
-
-    .label_ok {color: #060;}
-    .label_reject {color: #d14836;}
-    .label_need {color: #000;}
-    .label_may {color: #777;}
-
-    .hashtagName {
-      display: inline-block;
-      height: 15px;
-      margin-bottom: 2px;
-      padding: 1px 3px 1px 3px;
-      border-radius: 5px;
-      -webkit-border-radius: 5px;
-      background: #E2F5FF;
-      border: 1px solid #579FDA;
-      white-space: nowrap;
-    }
-
-    .hashtagName a,
-    .hashtagName button {
-      position: relative;
-      top: -4px;
-    }
-
-    .hashtagName button {
-      cursor: pointer;
-      padding: 0;
-      margin: 0 0 0 5px;
-      border: 0;
-      background-color: transparent;
-      white-space: nowrap;
-    }
-
-    .hashtagIcon img {
-      position: relative;
-      top: 4px;
-    }
-
-    .headerButtons button {
-      margin: 5.286px 3px 0 0;
-      text-align: center;
-      font-size: 8pt;
-      font-weight: bold;
-      cursor: pointer;
-      border: 2px solid;
-      color: rgba(0, 0, 0, 0.15);
-      background-color: #f5f5f5;
-      -webkit-border-radius: 2px;
-      -webkit-box-sizing: content-box;
-    }
-    .headerButtons button div {
-      color: #444;
-      min-width: 54px;
-      white-space: nowrap;
-      height: BUTTON_HEIGHT;
-      line-height: BUTTON_HEIGHT;
-    }
-    button.highlight {
-      background-color: #4d90fe;
-    }
-    button.highlight div { color: #fff; }
-
-    .sectionHeader {
-      position: relative;
-      background-color: trimColor;
-      font-weight: bold;
-      color: textColor;
-      height: 20px;
-      line-height: 20px;
-      margin: 0 -5px;
-      padding: 5px 5px;
-    }
-    .sectionHeader .headerButtons {
-      position: absolute;
-      left: 300px;
-      top: 2px;
-      height: 18px;
-      line-height: 18px;
-      border-left: 1px inset #fff;
-      padding-left: 5px;
-      padding-top: 3px;
-      padding-bottom: 3px;
-    }
-    .sectionHeader button { margin-top: 0; }
-
-    .diffBase {
-      display: inline-block;
-      height: 18px;
-      line-height: 18px;
-      font-size: smaller;
-      font-weight: normal;
-      vertical-align: top;
-    }
-    .diffBase select {
-      margin: 0;
-      border: 2px solid rgba(0, 0, 0, 0.15);
-      height: 20px;
-      font-size: 8pt;
-      font-weight: bold;
-      border-radius: 2px;
-      background-color: #f5f5f5
-    }
-
-    .replyBox {
-      background-color: trimColor;
-    }
-
-    .ownerPanel img, .uploaderPanel img {
-      margin: 0 2px 0 0;
-      width: 16px;
-      height: 16px !important;
-      vertical-align: bottom;
-    }
-
-    .headerExtension {
-      display: inline-block;
-      float: right;
-    }
-
-    .headerExtension>div>div {
-      float: left;
-    }
-
-    .changeExtension {
-      padding-top: 5px;
-    }
-
-    .relatedExtension {
-      padding-top: 5px;
-    }
-
-    .commitExtension {
-      padding-top: 5px;
-    }
-
-    .historyExtension {
-      display: inline-block;
-      float: right;
-    }
-
-    .pushCertStatus {
-      padding-left: 5px;
-    }
-
-    .notCurrentPatchSet {
-      background-color: #FFA62F;
-    }
-  </ui:style>
-
-  <g:HTMLPanel styleName='{style.cs2}'>
-    <g:HTMLPanel styleName='{style.headerLine}' ui:field='headerLine'>
-      <div class='{style.subjectLine}'>
-        <div class='{style.idAndStatus}'>
-          <span class='{style.changeId}'>
-            <ui:msg>Change <g:Anchor ui:field='permalink' title='Reload the change (Shortcut: R)'>
-              <ui:attribute name='title'/>
-            </g:Anchor> - <span ui:field='statusText' class='{style.statusText}'/>
-              <span ui:field='privateText' class='{style.privateText}'/>
-              <span ui:field='wipText' class='{style.wipText}'/></ui:msg>
-          </span>
-          <g:SimplePanel ui:field='headerExtension' styleName='{style.headerExtension}'/>
-        </div>
-      </div>
-
-      <div class='{style.infoLine}'>
-        <div class='{style.headerButtons} {style.infoLineHeaderButtons}'>
-          <g:Button ui:field='reply'
-              styleName=''
-              title=''
-              visible='false'>
-            <ui:attribute name='title'/>
-          </g:Button>
-          <c:QuickApprove ui:field='quickApprove'
-              styleName='{style.highlight}'
-              title='Apply score with one click'>
-            <ui:attribute name='title'/>
-          </c:QuickApprove>
-          <g:Button ui:field='publishEdit'
-              styleName='{style.highlight}' visible='false'>
-            <div><ui:msg>Publish Edit</ui:msg></div>
-          </g:Button>
-          <g:Button ui:field='rebaseEdit'
-              styleName='{style.highlight}' visible='false'>
-            <div><ui:msg>Rebase Edit</ui:msg></div>
-          </g:Button>
-          <g:Button ui:field='deleteEdit' styleName='' visible='false'>
-            <div><ui:msg>Delete Edit</ui:msg></div>
-          </g:Button>
-          <g:SimplePanel ui:field='headerExtensionMiddle' styleName='{style.headerExtension}'/>
-        </div>
-      </div>
-
-      <div class='{style.statusRight}'>
-        <g:FlowPanel styleName='{style.popdown}'>
-          <g:Button ui:field='includedIn' styleName='' visible="false">
-            <div><ui:msg>Included in</ui:msg></div>
-          </g:Button>
-          <g:Button ui:field='patchSets' styleName=''>
-            <div ui:field='patchSetsText'/>
-          </g:Button>
-          <g:Button ui:field='download' styleName=''>
-            <div><ui:msg>Download</ui:msg></div>
-          </g:Button>
-          <g:SimplePanel ui:field='headerExtensionRight' styleName='{style.headerExtension}'/>
-        </g:FlowPanel>
-        <c:StarIcon ui:field='star' styleName='{style.star}' title='Star the change (Shortcut: s)'>
-          <ui:attribute name='title'/>
-        </c:StarIcon>
-      </div>
-    </g:HTMLPanel>
-
-    <table class='{style.infoTable}'>
-      <tr>
-        <td class='{style.commitColumn}'>
-          <c:CommitBox ui:field='commit'/>
-          <g:SimplePanel ui:field='commitExtension' styleName='{style.commitExtension}'/>
-        </td>
-        <td class='{style.infoColumn}'>
-          <table id='change_infoTable'>
-            <tr>
-              <th><ui:msg>Owner</ui:msg></th>
-              <td>
-                <g:FlowPanel ui:field='ownerPanel' styleName='{style.ownerPanel}'>
-                  <x:InlineHyperlink ui:field='ownerLink'/>
-                </g:FlowPanel>
-              </td>
-            </tr>
-            <tr ui:field='uploaderRow'>
-              <th><ui:msg>Uploader</ui:msg></th>
-              <td>
-                <g:FlowPanel ui:field='uploaderPanel' styleName='{style.uploaderPanel}'>
-                  <g:InlineLabel ui:field='uploaderName'/>
-                </g:FlowPanel>
-              </td>
-            </tr>
-            <tr ui:field='assigneeRow'>
-              <th><ui:msg>Assignee</ui:msg></th>
-              <td>
-                <c:Assignee ui:field='assignee'/>
-              </td>
-            </tr>
-            <tr>
-              <th><ui:msg>Reviewers</ui:msg></th>
-              <td>
-                <c:Reviewers ui:field='reviewers'/>
-              </td>
-            </tr>
-            <tr>
-              <th/>
-              <td ui:field='ccText'/>
-            </tr>
-            <tr>
-              <th><ui:msg>Project</ui:msg></th>
-              <td><x:InlineHyperlink ui:field='projectDashboard'
-                     title='Go to project dashboard'>
-                     <ui:attribute name='title'/>
-                  </x:InlineHyperlink>
-                  <a ui:field='projectSettingsLink'
-                     class='{style.projectSettings}'>
-                    <g:Image
-                       ui:field='projectSettings'
-                       resource='{ico.gear}'
-                       title='Go to project settings'>
-                      <ui:attribute name='title'/>
-                    </g:Image>
-                  </a>
-              </td>
-            </tr>
-            <tr>
-              <th><ui:msg>Branch</ui:msg></th>
-              <td><x:InlineHyperlink ui:field='branchLink'
-                     title='Search for changes on this branch'>
-                     <ui:attribute name='title'/>
-                  </x:InlineHyperlink>
-              </td>
-            </tr>
-            <tr>
-              <th><ui:msg>Topic</ui:msg></th>
-              <td><c:Topic ui:field='topic'/></td>
-            </tr>
-            <tr ui:field='strategy'>
-              <th><ui:msg>Strategy</ui:msg></th>
-              <td>
-                <span ui:field='submitActionText'/>
-                <div ui:field='notMergeable'
-                     class='{style.notMergeable}'
-                     style='display: none'
-                     aria-hidden='true'
-                     title='The change cannot be merged due to a path conflict. Rebase the change and upload the rebased commit for review.'>
-                  <ui:attribute name='title'/>
-                  <ui:msg>Cannot Merge</ui:msg>
-                </div>
-              </td>
-            </tr>
-            <tr>
-              <th ui:field='actionText'/>
-              <td ui:field='actionDate'/>
-            </tr>
-            <tr ui:field='hashtagTableRow'>
-              <th><ui:msg>Hashtags</ui:msg></th>
-              <td colspan='2'>
-                <c:Hashtags ui:field='hashtags'/>
-              </td>
-            </tr>
-            <tr><td colspan='2'><c:Actions ui:field='actions'/></td></tr>
-          </table>
-          <hr/>
-          <c:Labels ui:field='labels' styleName='{style.labels}'/>
-          <g:SimplePanel ui:field='changeExtension' styleName='{style.changeExtension}'/>
-          <div id='change_plugins'/>
-        </td>
-        <td class='{style.relatedColumn}'>
-          <c:RelatedChanges ui:field='related'/>
-          <g:SimplePanel ui:field='relatedExtension' styleName='{style.relatedExtension}'/>
-        </td>
-      </tr>
-    </table>
-
-    <div class='{style.sectionHeader} {style.headerButtons}'>
-      <ui:msg>Files</ui:msg>
-      <g:Button ui:field='addFile'
-         title='Add file to this change'
-         styleName=''
-         visible='false'>
-        <ui:attribute name='title'/>
-        <div><ui:msg>Add&#8230;</ui:msg></div>
-      </g:Button>
-      <g:Button ui:field='deleteFile'
-         title='Delete file from the repository'
-         styleName=''
-         visible='false'>
-        <ui:attribute name='title'/>
-        <div><ui:msg>Delete&#8230;</ui:msg></div>
-      </g:Button>
-      <g:Button ui:field='renameFile'
-         title='Rename file in the repository'
-         styleName=''
-         visible='false'>
-        <ui:attribute name='title'/>
-        <div><ui:msg>Rename&#8230;</ui:msg></div>
-      </g:Button>
-      <div class='{style.headerButtons}'>
-        <g:Button ui:field='openAll'
-            styleName=''
-            title='Open each file in a new tab'>
-          <ui:attribute name='title'/>
-          <div><ui:msg>Open All</ui:msg></div>
-        </g:Button>
-        <div class='{style.diffBase}'>
-          <ui:msg>Diff against: <g:ListBox ui:field='diffBase' styleName=''/></ui:msg>
-        </div>
-        <g:Button ui:field='editMode'
-            styleName=''
-            visible='false'
-            title='Switch file table to edit mode'>
-          <ui:attribute name='title'/>
-          <div><ui:msg>Edit</ui:msg></div>
-        </g:Button>
-        <g:Button ui:field='reviewMode'
-            styleName=''
-            visible='false'
-            title='Done with edit mode'>
-          <ui:attribute name='title'/>
-          <div><ui:msg>Done Editing</ui:msg></div>
-        </g:Button>
-      </div>
-    </div>
-    <c:FileTable ui:field='files'/>
-
-    <div class='{style.sectionHeader}'>
-      <ui:msg>History</ui:msg>
-      <div class='{style.headerButtons}'>
-        <g:Button ui:field='expandAll'
-            styleName=''
-            title='Expand all messages in the change history'>
-          <ui:attribute name='title'/>
-          <div><ui:msg>Expand All</ui:msg></div>
-        </g:Button>
-        <g:Button ui:field='collapseAll'
-            styleName=''
-            visible='false'
-            title='Collapse all messages in the change history'>
-          <ui:attribute name='title'/>
-          <div><ui:msg>Collapse All</ui:msg></div>
-        </g:Button>
-        <g:Button ui:field='hideTaggedComments'
-            styleName=''
-            visible='false'
-            title='Hide tagged comments'>
-          <ui:attribute name='title'/>
-          <div><ui:msg>Hide tagged comments</ui:msg></div>
-        </g:Button>
-        <g:Button ui:field='showTaggedComments'
-            styleName=''
-            visible='false'
-            title='Show tagged comments'>
-          <ui:attribute name='title'/>
-          <div><ui:msg>Show tagged comments</ui:msg></div>
-        </g:Button>
-        <g:SimplePanel ui:field='historyExtensionRight' styleName='{style.historyExtension}'/>
-      </div>
-    </div>
-    <c:History ui:field='history'/>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/CherryPickAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/CherryPickAction.java
deleted file mode 100644
index be011d2..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/CherryPickAction.java
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.changes.Util;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.ui.CherryPickDialog;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.PopupPanel;
-
-class CherryPickAction {
-  static void call(
-      final Button b,
-      final ChangeInfo info,
-      final String revision,
-      final Project.NameKey project,
-      final String commitMessage) {
-    // TODO Replace CherryPickDialog with a nicer looking display.
-    b.setEnabled(false);
-    new CherryPickDialog(project) {
-      {
-        sendButton.setText(Util.C.buttonCherryPickChangeSend());
-        if (info.status() == Change.Status.MERGED) {
-          message.setText(Util.M.cherryPickedChangeDefaultMessage(commitMessage.trim(), revision));
-        } else {
-          message.setText(commitMessage.trim());
-        }
-      }
-
-      @Override
-      public void onSend() {
-        ChangeApi.cherrypick(
-            info.project(),
-            info.legacyId().get(),
-            revision,
-            getDestinationBranch(),
-            getMessageText(),
-            new GerritCallback<ChangeInfo>() {
-              @Override
-              public void onSuccess(ChangeInfo result) {
-                sent = true;
-                hide();
-                Gerrit.display(PageLinks.toChange(project, result.legacyId()));
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {
-                enableButtons(true);
-                super.onFailure(caught);
-              }
-            });
-      }
-
-      @Override
-      public void onClose(CloseEvent<PopupPanel> event) {
-        super.onClose(event);
-        b.setEnabled(true);
-      }
-    }.center();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/CommitBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/CommitBox.java
deleted file mode 100644
index 0112579..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/CommitBox.java
+++ /dev/null
@@ -1,219 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.AvatarImage;
-import com.google.gerrit.client.FormatUtil;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.ChangeInfo.CommitInfo;
-import com.google.gerrit.client.info.ChangeInfo.GitPerson;
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.client.info.WebLinkInfo;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.CommentLinkProcessor;
-import com.google.gerrit.client.ui.InlineHyperlink;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.common.PageLinks;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.TableRowElement;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.ScrollPanel;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwtexpui.clippy.client.CopyableLabel;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-
-class CommitBox extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, CommitBox> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  interface Style extends CssResource {
-    String collapsed();
-
-    String expanded();
-
-    String clippy();
-
-    String parentWebLink();
-  }
-
-  @UiField Style style;
-  @UiField FlowPanel authorPanel;
-  @UiField FlowPanel committerPanel;
-  @UiField Image mergeCommit;
-  @UiField CopyableLabel commitName;
-  @UiField FlowPanel webLinkPanel;
-  @UiField TableRowElement firstParent;
-  @UiField FlowPanel parentCommits;
-  @UiField FlowPanel parentWebLinks;
-  @UiField InlineHyperlink authorNameEmail;
-  @UiField Element authorDate;
-  @UiField InlineHyperlink committerNameEmail;
-  @UiField Element committerDate;
-  @UiField CopyableLabel idText;
-  @UiField HTML text;
-  @UiField ScrollPanel scroll;
-  @UiField Button more;
-  @UiField Element parentNotCurrentText;
-  private boolean expanded;
-
-  CommitBox() {
-    initWidget(uiBinder.createAndBindUi(this));
-    addStyleName(style.collapsed());
-  }
-
-  void onShowView() {
-    more.setVisible(scroll.getMaximumVerticalScrollPosition() > 0);
-  }
-
-  @UiHandler("more")
-  void onMore(@SuppressWarnings("unused") ClickEvent e) {
-    if (expanded) {
-      removeStyleName(style.expanded());
-      addStyleName(style.collapsed());
-    } else {
-      removeStyleName(style.collapsed());
-      addStyleName(style.expanded());
-    }
-    expanded = !expanded;
-  }
-
-  void set(CommentLinkProcessor commentLinkProcessor, ChangeInfo change, String revision) {
-    RevisionInfo revInfo = change.revision(revision);
-    CommitInfo commit = revInfo.commit();
-
-    commitName.setText(revision);
-    idText.setText("Change-Id: " + change.changeId());
-    idText.setPreviewText(change.changeId());
-
-    formatLink(commit.author(), authorPanel, authorNameEmail, authorDate, change);
-    formatLink(commit.committer(), committerPanel, committerNameEmail, committerDate, change);
-    text.setHTML(
-        commentLinkProcessor.apply(new SafeHtmlBuilder().append(commit.message()).linkify()));
-    setWebLinks(webLinkPanel, revInfo.commit());
-
-    if (revInfo.commit().parents().length() > 1) {
-      mergeCommit.setVisible(true);
-    }
-
-    setParents(revInfo.commit().parents());
-  }
-
-  void setParentNotCurrent(boolean parentNotCurrent) {
-    // display the orange ball if parent has moved on (not current)
-    UIObject.setVisible(parentNotCurrentText, parentNotCurrent);
-    parentNotCurrentText.setInnerText(parentNotCurrent ? "\u25CF" : "");
-  }
-
-  private void setWebLinks(FlowPanel panel, CommitInfo commit) {
-    JsArray<WebLinkInfo> links = commit.webLinks();
-    if (links != null) {
-      for (WebLinkInfo link : Natives.asList(links)) {
-        panel.add(link.toAnchor());
-      }
-    }
-  }
-
-  private void setParents(JsArray<CommitInfo> commits) {
-    setVisible(firstParent, true);
-    TableRowElement next = firstParent;
-    TableRowElement previous = null;
-    for (CommitInfo c : Natives.asList(commits)) {
-      if (next == firstParent) {
-        CopyableLabel copyLabel = getCommitLabel(c);
-        parentCommits.add(copyLabel);
-        setWebLinks(parentWebLinks, c);
-      } else {
-        next.appendChild(DOM.createTD());
-        Element td1 = DOM.createTD();
-        td1.appendChild(getCommitLabel(c).getElement());
-        next.appendChild(td1);
-        FlowPanel linksPanel = new FlowPanel();
-        linksPanel.addStyleName(style.parentWebLink());
-        setWebLinks(linksPanel, c);
-        Element td2 = DOM.createTD();
-        td2.appendChild(linksPanel.getElement());
-        next.appendChild(td2);
-        previous.getParentElement().insertAfter(next, previous);
-      }
-      previous = next;
-      next = DOM.createTR().cast();
-    }
-  }
-
-  private CopyableLabel getCommitLabel(CommitInfo c) {
-    CopyableLabel copyLabel;
-    copyLabel = new CopyableLabel(c.commit());
-    copyLabel.setTitle(c.subject());
-    copyLabel.setStyleName(style.clippy());
-    return copyLabel;
-  }
-
-  private static void formatLink(
-      GitPerson person, FlowPanel p, InlineHyperlink name, Element date, ChangeInfo change) {
-    // only try to fetch the avatar image for author and committer if an avatar
-    // plugin is installed, if the change owner has no avatar info assume that
-    // no avatar plugin is installed
-    if (change.owner().hasAvatarInfo()) {
-      AvatarImage avatar;
-      if (sameEmail(change.owner(), person)) {
-        avatar = new AvatarImage(change.owner());
-      } else {
-        avatar = new AvatarImage(AccountInfo.create(0, person.name(), person.email(), null));
-      }
-      p.insert(avatar, 0);
-    }
-
-    name.setText(renderName(person));
-    name.setTargetHistoryToken(PageLinks.toAccountQuery(owner(person), change.status()));
-    date.setInnerText(FormatUtil.mediumFormat(person.date()));
-  }
-
-  private static String renderName(GitPerson person) {
-    return person.name() + " <" + person.email() + ">";
-  }
-
-  private static String owner(GitPerson person) {
-    if (person.email() != null) {
-      return person.email();
-    } else if (person.name() != null) {
-      return person.name();
-    } else {
-      return "";
-    }
-  }
-
-  private static boolean sameEmail(@Nullable AccountInfo p1, @Nullable GitPerson p2) {
-    return p1 != null
-        && p2 != null
-        && p1.email() != null
-        && p2.email() != null
-        && p1.email().equals(p2.email());
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/CommitBox.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/CommitBox.ui.xml
deleted file mode 100644
index 5f476be..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/CommitBox.ui.xml
+++ /dev/null
@@ -1,198 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'
-    xmlns:x='urn:import:com.google.gerrit.client.ui'
-    xmlns:clippy='urn:import:com.google.gwtexpui.clippy.client'>
-  <ui:with field='ico' type='com.google.gerrit.client.GerritResources'/>
-  <ui:image field="toggle" src="moreLess.png"/>
-  <ui:style gss='false' type='com.google.gerrit.client.change.CommitBox.Style'>
-    @eval trimColor com.google.gerrit.client.Gerrit.getTheme().trimColor;
-
-    .collapsed .scroll { height: 250px }
-    .scroll, .more { width: 560px }
-    .scroll {
-      border-right: 1px solid trimColor;
-      border-bottom: 1px solid trimColor;
-    }
-
-    .text {
-      font-family: monospace;
-      white-space: pre;
-    }
-
-    .more {
-      height: 8px;
-      line-height: 8px;
-      text-align: center;
-    }
-    .moreButton {
-      padding: 0 5px 0 5px;
-      margin: 0;
-      border: none;
-      height: 8px;
-      background-color: #F7F7F7;
-    }
-    .moreButton:focus {
-      outline: none;
-    }
-
-    @sprite .toggle {
-      gwt-image: "toggle";
-      width: 13px;
-      height: 8px;
-      padding: 0;
-    }
-    .collapsed .toggle { background-position: -13px -8px }
-    .expanded .toggle { background-position: 0px -8px }
-    .collapsed button:hover .toggle { background-position: -13px 0px }
-    .expanded button:hover .toggle { background-position: 0px 0px }
-
-    .header {
-      border-spacing: 0;
-      padding: 0;
-      width: 560px;
-    }
-    .header th { width: 72px; }
-    .header td { white-space: nowrap; }
-    .date { width: 132px; }
-
-    .clippy {
-      position: relative;
-    }
-    .clippy div {
-      position: absolute;
-      top: 0px;
-      right: -16px;
-    }
-    <!-- To make room for the copyableLabel from the adjacent column -->
-    .webLinkPanel a:first-child {
-      margin-left:16px;
-    }
-    .webLinkPanel>a {
-      margin-left:2px;
-    }
-
-    .parentWebLink a:first-child {
-      margin-left:16px;
-    }
-    .parentWebLink>a {
-      margin-left:2px;
-    }
-
-    .commit {
-      margin-right: 3px;
-      float: left;
-    }
-
-    .userPanel img {
-      margin: 0 2px 0 0;
-      width: 16px;
-      height: 16px !important;
-      vertical-align: bottom;
-    }
-
-    .parent {
-      margin-right: 3px;
-      float: left;
-    }
-    .parentNotCurrent {
-      color: #FFA62F;   <!-- orange -->
-      font-weight: bold;
-    }
-
-  </ui:style>
-  <g:HTMLPanel>
-    <g:ScrollPanel styleName='{style.scroll}' ui:field='scroll'>
-      <g:HTML styleName='{style.text}' ui:field='text'/>
-    </g:ScrollPanel>
-    <div class='{style.more}'>
-      <g:Button ui:field='more'
-          styleName='{style.moreButton}'
-          title='Expand/Collapse'>
-        <ui:attribute name='title'/>
-        <div class='{style.toggle}'/>
-      </g:Button>
-    </div>
-    <table class='{style.header}'>
-      <tr>
-        <th><ui:msg>Author</ui:msg></th>
-        <td>
-          <g:FlowPanel ui:field='authorPanel' styleName='{style.userPanel}'>
-            <x:InlineHyperlink ui:field='authorNameEmail'
-              title='Search for changes by this user'>
-              <ui:attribute name='title'/>
-            </x:InlineHyperlink>
-          </g:FlowPanel>
-        </td>
-        <td ui:field='authorDate' class='{style.date}' colspan="2"/>
-      </tr>
-      <tr>
-        <th><ui:msg>Committer</ui:msg></th>
-        <td>
-          <g:FlowPanel ui:field='committerPanel' styleName='{style.userPanel}'>
-            <x:InlineHyperlink ui:field='committerNameEmail'
-              title='Search for changes by this user'>
-              <ui:attribute name='title'/>
-            </x:InlineHyperlink>
-          </g:FlowPanel>
-        </td>
-        <td ui:field='committerDate' class='{style.date}' colspan="2"/>
-      </tr>
-      <tr>
-        <th>
-          <div class='{style.commit}'>
-            <ui:msg>Commit</ui:msg>
-          </div>
-          <g:Image
-              ui:field='mergeCommit'
-              resource='{ico.merge}'
-              visible='false'
-              title='Merge Commit'>
-            <ui:attribute name='title'/>
-          </g:Image>
-        </th>
-        <td><clippy:CopyableLabel styleName='{style.clippy}' ui:field='commitName'/></td>
-        <td>
-            <g:FlowPanel ui:field='webLinkPanel' styleName='{style.webLinkPanel}'/>
-        </td>
-      </tr>
-      <tr ui:field='firstParent' style='display: none'>
-        <th>
-          <div class='{style.parent}'>
-            <ui:msg>Parent(s)</ui:msg>
-          </div>
-          <div ui:field='parentNotCurrentText'
-              title='Not current - rebase possible'
-              class='{style.parentNotCurrent}'
-              style='display: none' aria-hidden='true'/>
-        </th>
-        <td>
-          <g:FlowPanel ui:field='parentCommits'/>
-        </td>
-        <td>
-          <g:FlowPanel ui:field='parentWebLinks' styleName='{style.parentWebLink}'/>
-        </td>
-      </tr>
-      <tr>
-        <th><ui:msg>Change-Id</ui:msg></th>
-        <td><clippy:CopyableLabel styleName='{style.clippy}' ui:field='idText'/></td>
-      </tr>
-    </table>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DeleteFileAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DeleteFileAction.java
deleted file mode 100644
index 9369c18..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DeleteFileAction.java
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-
-class DeleteFileAction {
-  private final Project.NameKey project;
-  private final Change.Id changeId;
-  private final RevisionInfo revision;
-  private final ChangeScreen.Style style;
-  private final Widget deleteButton;
-
-  private DeleteFileBox deleteBox;
-  private PopupPanel popup;
-
-  DeleteFileAction(
-      Project.NameKey project,
-      Change.Id changeId,
-      RevisionInfo revision,
-      ChangeScreen.Style style,
-      Widget deleteButton) {
-    this.project = project;
-    this.changeId = changeId;
-    this.revision = revision;
-    this.style = style;
-    this.deleteButton = deleteButton;
-  }
-
-  void onDelete() {
-    if (popup != null) {
-      popup.hide();
-      return;
-    }
-
-    if (deleteBox == null) {
-      deleteBox = new DeleteFileBox(project, changeId, revision);
-    }
-    deleteBox.clearPath();
-
-    final PopupPanel p = new PopupPanel(true);
-    p.setStyleName(style.replyBox());
-    p.addAutoHidePartner(deleteButton.getElement());
-    p.addCloseHandler(
-        new CloseHandler<PopupPanel>() {
-          @Override
-          public void onClose(CloseEvent<PopupPanel> event) {
-            if (popup == p) {
-              popup = null;
-            }
-          }
-        });
-    p.add(deleteBox);
-    p.showRelativeTo(deleteButton);
-    GlobalKey.dialog(p);
-    deleteBox.setFocus(true);
-    popup = p;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DeleteFileBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DeleteFileBox.java
deleted file mode 100644
index 1885293..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DeleteFileBox.java
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.VoidResult;
-import com.google.gerrit.client.changes.ChangeEditApi;
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.client.ui.RemoteSuggestBox;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.event.logical.shared.SelectionEvent;
-import com.google.gwt.event.logical.shared.SelectionHandler;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.Widget;
-
-class DeleteFileBox extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, DeleteFileBox> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  private final Project.NameKey project;
-  private final Change.Id changeId;
-
-  @UiField Button delete;
-  @UiField Button cancel;
-
-  @UiField(provided = true)
-  RemoteSuggestBox path;
-
-  DeleteFileBox(Project.NameKey project, Change.Id changeId, RevisionInfo revision) {
-    this.project = project;
-    this.changeId = changeId;
-
-    path = new RemoteSuggestBox(new PathSuggestOracle(project, changeId, revision));
-    path.addSelectionHandler(
-        new SelectionHandler<String>() {
-          @Override
-          public void onSelection(SelectionEvent<String> event) {
-            delete(event.getSelectedItem());
-          }
-        });
-    path.addCloseHandler(
-        new CloseHandler<RemoteSuggestBox>() {
-          @Override
-          public void onClose(CloseEvent<RemoteSuggestBox> event) {
-            hide();
-          }
-        });
-
-    initWidget(uiBinder.createAndBindUi(this));
-  }
-
-  void setFocus(boolean focus) {
-    path.setFocus(focus);
-  }
-
-  void clearPath() {
-    path.setText("");
-  }
-
-  @UiHandler("delete")
-  void onDelete(@SuppressWarnings("unused") ClickEvent e) {
-    delete(path.getText());
-  }
-
-  private void delete(String path) {
-    hide();
-    ChangeEditApi.delete(
-        project.get(),
-        changeId.get(),
-        path,
-        new AsyncCallback<VoidResult>() {
-          @Override
-          public void onSuccess(VoidResult result) {
-            Gerrit.display(PageLinks.toChangeInEditMode(project, changeId));
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {}
-        });
-  }
-
-  @UiHandler("cancel")
-  void onCancel(@SuppressWarnings("unused") ClickEvent e) {
-    hide();
-  }
-
-  private void hide() {
-    for (Widget w = getParent(); w != null; w = w.getParent()) {
-      if (w instanceof PopupPanel) {
-        ((PopupPanel) w).hide();
-        break;
-      }
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DeleteFileBox.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DeleteFileBox.ui.xml
deleted file mode 100644
index 9e79f752..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DeleteFileBox.ui.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:u='urn:import:com.google.gerrit.client.ui'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-  <ui:with field='res' type='com.google.gerrit.client.change.Resources'/>
-  <ui:style gss='false'>
-    .cancel { float: right; }
-  </ui:style>
-  <g:HTMLPanel>
-    <div class='{res.style.section}'>
-      <ui:msg>Path: <u:RemoteSuggestBox ui:field='path' visibleLength='86'/></ui:msg>
-    </div>
-    <div class='{res.style.section}'>
-      <g:Button ui:field='delete'
-          title='Delete file from the repository'
-          styleName='{res.style.button}'>
-        <ui:attribute name='title'/>
-        <div><ui:msg>Delete</ui:msg></div>
-      </g:Button>
-      <g:Button ui:field='cancel'
-          styleName='{res.style.button}'
-          addStyleNames='{style.cancel}'>
-          <div>Cancel</div>
-      </g:Button>
-    </div>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DownloadAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DownloadAction.java
deleted file mode 100644
index 8e4ea84..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DownloadAction.java
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwt.user.client.ui.Widget;
-
-class DownloadAction extends RightSidePopdownAction {
-  private final DownloadBox downloadBox;
-
-  DownloadAction(
-      ChangeInfo info,
-      String revision,
-      ChangeScreen.Style style,
-      UIObject relativeTo,
-      Widget downloadButton) {
-    super(style, relativeTo, downloadButton);
-    this.downloadBox =
-        new DownloadBox(
-            info, revision, new PatchSet.Id(info.legacyId(), info.revision(revision)._number()));
-  }
-
-  @Override
-  Widget getWidget() {
-    return downloadBox;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DownloadBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DownloadBox.java
deleted file mode 100644
index 547f3d5..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DownloadBox.java
+++ /dev/null
@@ -1,261 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.account.AccountApi;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.changes.ChangeList;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.ChangeInfo.EditInfo;
-import com.google.gerrit.client.info.ChangeInfo.FetchInfo;
-import com.google.gerrit.client.info.GeneralPreferences;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.extensions.client.ListChangesOption;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.event.dom.client.ChangeEvent;
-import com.google.gwt.event.dom.client.ChangeHandler;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.FlexTable;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.InlineLabel;
-import com.google.gwt.user.client.ui.ListBox;
-import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.clippy.client.CopyableLabel;
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.Iterator;
-import java.util.List;
-
-class DownloadBox extends VerticalPanel {
-  private final ChangeInfo change;
-  private final String revision;
-  private final PatchSet.Id psId;
-  private final FlexTable commandTable;
-  private final ListBox scheme;
-  private NativeMap<FetchInfo> fetch;
-
-  DownloadBox(ChangeInfo change, String revision, PatchSet.Id psId) {
-    this.change = change;
-    this.revision = revision;
-    this.psId = psId;
-    this.commandTable = new FlexTable();
-    this.scheme = new ListBox();
-    this.scheme.addChangeHandler(
-        new ChangeHandler() {
-          @Override
-          public void onChange(ChangeEvent event) {
-            renderCommands();
-            if (Gerrit.isSignedIn()) {
-              saveScheme();
-            }
-          }
-        });
-
-    setStyleName(Gerrit.RESOURCES.css().downloadBox());
-    commandTable.setStyleName(Gerrit.RESOURCES.css().downloadBoxTable());
-    scheme.setStyleName(Gerrit.RESOURCES.css().downloadBoxScheme());
-    add(commandTable);
-  }
-
-  @Override
-  protected void onLoad() {
-    if (fetch == null) {
-      if (psId.get() == 0) {
-        ChangeApi.editWithCommands(change.project(), change.legacyId().get())
-            .get(
-                new AsyncCallback<EditInfo>() {
-                  @Override
-                  public void onSuccess(EditInfo result) {
-                    fetch = result.fetch();
-                    renderScheme();
-                  }
-
-                  @Override
-                  public void onFailure(Throwable caught) {}
-                });
-      } else {
-        RestApi call = ChangeApi.detail(change.project(), change.legacyId().get());
-        ChangeList.addOptions(
-            call,
-            EnumSet.of(
-                revision.equals(change.currentRevision())
-                    ? ListChangesOption.CURRENT_REVISION
-                    : ListChangesOption.ALL_REVISIONS,
-                ListChangesOption.DOWNLOAD_COMMANDS));
-        call.get(
-            new AsyncCallback<ChangeInfo>() {
-              @Override
-              public void onSuccess(ChangeInfo result) {
-                fetch = result.revision(revision).fetch();
-                renderScheme();
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {}
-            });
-      }
-    }
-  }
-
-  private void renderCommands() {
-    commandTable.removeAllRows();
-
-    if (scheme.getItemCount() > 0) {
-      FetchInfo fetchInfo = fetch.get(scheme.getValue(scheme.getSelectedIndex()));
-      for (String commandName : fetchInfo.commands().sortedKeys()) {
-        CopyableLabel copyLabel = new CopyableLabel(fetchInfo.command(commandName));
-        copyLabel.setStyleName(Gerrit.RESOURCES.css().downloadBoxCopyLabel());
-        insertCommand(commandName, copyLabel);
-      }
-    }
-    if (change.revision(revision).commit().parents().length() == 1) {
-      insertPatch();
-    }
-    insertArchive();
-    insertCommand(null, scheme);
-  }
-
-  private void insertPatch() {
-    String id = revision.substring(0, 7);
-    Anchor patchBase64 = new Anchor(id + ".diff.base64");
-    patchBase64.setHref(
-        new RestApi("/changes/")
-            .id(psId.getParentKey().get())
-            .view("revisions")
-            .id(revision)
-            .view("patch")
-            .addParameterTrue("download")
-            .url());
-
-    Anchor patchZip = new Anchor(id + ".diff.zip");
-    patchZip.setHref(
-        new RestApi("/changes/")
-            .id(psId.getParentKey().get())
-            .view("revisions")
-            .id(revision)
-            .view("patch")
-            .addParameterTrue("zip")
-            .url());
-
-    HorizontalPanel p = new HorizontalPanel();
-    p.add(patchBase64);
-    InlineLabel spacer = new InlineLabel("|");
-    spacer.setStyleName(Gerrit.RESOURCES.css().downloadBoxSpacer());
-    p.add(spacer);
-    p.add(patchZip);
-    insertCommand("Patch-File", p);
-  }
-
-  private void insertArchive() {
-    List<String> activated = Gerrit.info().download().archives();
-    if (activated.isEmpty()) {
-      return;
-    }
-
-    List<Anchor> anchors = new ArrayList<>(activated.size());
-    for (String f : activated) {
-      Anchor archive = new Anchor(f);
-      archive.setHref(
-          new RestApi("/changes/")
-              .id(psId.getParentKey().get())
-              .view("revisions")
-              .id(revision)
-              .view("archive")
-              .addParameter("format", f)
-              .url());
-      anchors.add(archive);
-    }
-
-    HorizontalPanel p = new HorizontalPanel();
-    Iterator<Anchor> it = anchors.iterator();
-    while (it.hasNext()) {
-      Anchor a = it.next();
-      p.add(a);
-      if (it.hasNext()) {
-        InlineLabel spacer = new InlineLabel("|");
-        spacer.setStyleName(Gerrit.RESOURCES.css().downloadBoxSpacer());
-        p.add(spacer);
-      }
-    }
-    insertCommand("Archive", p);
-  }
-
-  private void insertCommand(String commandName, Widget w) {
-    int row = commandTable.getRowCount();
-    commandTable.insertRow(row);
-    commandTable
-        .getCellFormatter()
-        .addStyleName(row, 0, Gerrit.RESOURCES.css().downloadBoxTableCommandColumn());
-    if (commandName != null) {
-      commandTable.setText(row, 0, commandName);
-    }
-    if (w != null) {
-      commandTable.setWidget(row, 1, w);
-    }
-  }
-
-  private void renderScheme() {
-    for (String id : fetch.sortedKeys()) {
-      scheme.addItem(id);
-    }
-    if (scheme.getItemCount() == 0) {
-      scheme.setVisible(false);
-    } else {
-      if (scheme.getItemCount() == 1) {
-        scheme.setSelectedIndex(0);
-        scheme.setVisible(false);
-      } else {
-        int select = 0;
-        String find = Gerrit.getUserPreferences().downloadScheme();
-        if (find != null) {
-          for (int i = 0; i < scheme.getItemCount(); i++) {
-            if (find.equals(scheme.getValue(i))) {
-              select = i;
-              break;
-            }
-          }
-        }
-        scheme.setSelectedIndex(select);
-      }
-    }
-    renderCommands();
-  }
-
-  private void saveScheme() {
-    String schemeStr = scheme.getValue(scheme.getSelectedIndex());
-    GeneralPreferences prefs = Gerrit.getUserPreferences();
-    if (Gerrit.isSignedIn() && !schemeStr.equals(prefs.downloadScheme())) {
-      prefs.downloadScheme(schemeStr);
-      GeneralPreferences in = GeneralPreferences.create();
-      in.downloadScheme(schemeStr);
-      AccountApi.self()
-          .view("preferences")
-          .put(
-              in,
-              new AsyncCallback<JavaScriptObject>() {
-                @Override
-                public void onSuccess(JavaScriptObject result) {}
-
-                @Override
-                public void onFailure(Throwable caught) {}
-              });
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/EditActions.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/EditActions.java
deleted file mode 100644
index f075c16..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/EditActions.java
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.user.client.ui.Button;
-
-public class EditActions {
-
-  static void deleteEdit(Project.NameKey project, Change.Id id, Button... editButtons) {
-    ChangeApi.deleteEdit(project.get(), id.get(), cs(project, id, editButtons));
-  }
-
-  static void publishEdit(Project.NameKey project, Change.Id id, Button... editButtons) {
-    ChangeApi.publishEdit(project.get(), id.get(), cs(project, id, editButtons));
-  }
-
-  static void rebaseEdit(Project.NameKey project, Change.Id id, Button... editButtons) {
-    ChangeApi.rebaseEdit(project.get(), id.get(), cs(project, id, editButtons));
-  }
-
-  public static GerritCallback<JavaScriptObject> cs(
-      Project.NameKey project, final Change.Id id, Button... editButtons) {
-    setEnabled(false, editButtons);
-    return new GerritCallback<JavaScriptObject>() {
-      @Override
-      public void onSuccess(JavaScriptObject result) {
-        Gerrit.display(PageLinks.toChange(project, id));
-      }
-
-      @Override
-      public void onFailure(Throwable err) {
-        setEnabled(true, editButtons);
-        if (SubmitFailureDialog.isConflict(err)) {
-          new SubmitFailureDialog(err.getMessage()).center();
-          Gerrit.display(PageLinks.toChange(project, id));
-        } else {
-          super.onFailure(err);
-        }
-      }
-    };
-  }
-
-  private static void setEnabled(boolean enabled, Button... editButtons) {
-    if (editButtons != null) {
-      for (Button b : editButtons) {
-        b.setEnabled(enabled);
-      }
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileComments.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileComments.java
deleted file mode 100644
index 083c824..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileComments.java
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Dispatcher;
-import com.google.gerrit.client.changes.CommentInfo;
-import com.google.gerrit.client.ui.CommentLinkProcessor;
-import com.google.gerrit.client.ui.InlineHyperlink;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import java.util.List;
-
-class FileComments extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, FileComments> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  @UiField InlineHyperlink path;
-  @UiField FlowPanel comments;
-
-  FileComments(
-      CommentLinkProcessor clp,
-      Project.NameKey project,
-      PatchSet.Id defaultPs,
-      String title,
-      List<CommentInfo> list) {
-    initWidget(uiBinder.createAndBindUi(this));
-
-    path.setTargetHistoryToken(url(project, defaultPs, list.get(0)));
-    path.setText(title);
-    for (CommentInfo c : list) {
-      comments.add(new LineComment(clp, project, defaultPs, c));
-    }
-  }
-
-  private static String url(Project.NameKey project, PatchSet.Id ps, CommentInfo info) {
-    return Dispatcher.toPatch(project, null, ps, info.path());
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileComments.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileComments.ui.xml
deleted file mode 100644
index e463e95..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileComments.ui.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:c='urn:import:com.google.gerrit.client.ui'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-  <ui:style gss='false'>
-    .box {
-    }
-    .path {
-      display: block;
-      white-space: nowrap;
-    }
-    .comments {
-      margin-left: 1em;
-    }
-  </ui:style>
-
-  <g:HTMLPanel styleName='{style.box}'>
-    <c:InlineHyperlink styleName='{style.path}' ui:field='path'/>
-    <g:FlowPanel styleName='{style.comments}' ui:field='comments'/>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileTable.java
deleted file mode 100644
index 30554b6..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileTable.java
+++ /dev/null
@@ -1,940 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import static com.google.gerrit.client.FormatUtil.formatAbsBytes;
-import static com.google.gerrit.client.FormatUtil.formatAbsPercentage;
-import static com.google.gerrit.client.FormatUtil.formatBytes;
-import static com.google.gerrit.client.FormatUtil.formatPercentage;
-
-import com.google.gerrit.client.DiffObject;
-import com.google.gerrit.client.Dispatcher;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.VoidResult;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.changes.ChangeEditApi;
-import com.google.gerrit.client.changes.CommentInfo;
-import com.google.gerrit.client.changes.ReviewInfo;
-import com.google.gerrit.client.changes.Util;
-import com.google.gerrit.client.info.FileInfo;
-import com.google.gerrit.client.patches.PatchUtil;
-import com.google.gerrit.client.rpc.CallbackGroup;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.client.ui.NavigationTable;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.extensions.client.Side;
-import com.google.gerrit.reviewdb.client.Patch;
-import com.google.gerrit.reviewdb.client.Patch.ChangeType;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.RepeatingCommand;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.InputElement;
-import com.google.gwt.dom.client.NativeEvent;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.resources.client.ClientBundle;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.EventListener;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
-import com.google.gwt.user.client.ui.ImageResourceRenderer;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.user.client.ui.impl.HyperlinkImpl;
-import com.google.gwtexpui.globalkey.client.KeyCommand;
-import com.google.gwtexpui.progress.client.ProgressBar;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-import java.sql.Timestamp;
-
-public class FileTable extends FlowPanel {
-  private static final FileTableResources R = GWT.create(FileTableResources.class);
-
-  interface FileTableResources extends ClientBundle {
-    @Source("file_table.css")
-    FileTableCss css();
-  }
-
-  interface FileTableCss extends CssResource {
-    String table();
-
-    String nohover();
-
-    String pointer();
-
-    String reviewed();
-
-    String status();
-
-    String pathColumn();
-
-    String commonPrefix();
-
-    String renameCopySource();
-
-    String draftColumn();
-
-    String newColumn();
-
-    String commentColumn();
-
-    String deltaColumn1();
-
-    String deltaColumn2();
-
-    String inserted();
-
-    String deleted();
-
-    String restoreDelete();
-
-    String error();
-  }
-
-  public enum Mode {
-    REVIEW,
-    EDIT
-  }
-
-  private static final String DELETE;
-  private static final String RESTORE;
-  private static final String REVIEWED;
-  private static final String OPEN;
-  private static final int C_PATH = 3;
-  private static final HyperlinkImpl link = GWT.create(HyperlinkImpl.class);
-
-  static {
-    DELETE = DOM.createUniqueId().replace('-', '_');
-    RESTORE = DOM.createUniqueId().replace('-', '_');
-    REVIEWED = DOM.createUniqueId().replace('-', '_');
-    OPEN = DOM.createUniqueId().replace('-', '_');
-    init(DELETE, RESTORE, REVIEWED, OPEN);
-  }
-
-  private static native void init(String d, String t, String r, String o) /*-{
-    $wnd[d] = $entry(function(e,i) {
-      @com.google.gerrit.client.change.FileTable::onDelete(Lcom/google/gwt/dom/client/NativeEvent;I)(e,i)
-    });
-    $wnd[t] = $entry(function(e,i) {
-      @com.google.gerrit.client.change.FileTable::onRestore(Lcom/google/gwt/dom/client/NativeEvent;I)(e,i)
-    });
-    $wnd[r] = $entry(function(e,i) {
-      @com.google.gerrit.client.change.FileTable::onReviewed(Lcom/google/gwt/dom/client/NativeEvent;I)(e,i)
-    });
-    $wnd[o] = $entry(function(e,i) {
-      return @com.google.gerrit.client.change.FileTable::onOpen(Lcom/google/gwt/dom/client/NativeEvent;I)(e,i);
-    });
-  }-*/;
-
-  private static void onDelete(NativeEvent e, int idx) {
-    MyTable t = getMyTable(e);
-    if (t != null) {
-      t.onDelete(idx);
-    }
-  }
-
-  private static boolean onRestore(NativeEvent e, int idx) {
-    MyTable t = getMyTable(e);
-    if (t != null) {
-      t.onRestore(idx);
-      e.preventDefault();
-      e.stopPropagation();
-      return false;
-    }
-    return true;
-  }
-
-  private static void onReviewed(NativeEvent e, int idx) {
-    MyTable t = getMyTable(e);
-    if (t != null) {
-      t.onReviewed(InputElement.as(Element.as(e.getEventTarget())), idx);
-    }
-  }
-
-  private static boolean onOpen(NativeEvent e, int idx) {
-    if (link.handleAsClick(e.<Event>cast())) {
-      MyTable t = getMyTable(e);
-      if (t != null) {
-        t.onOpenRow(1 + idx);
-        e.preventDefault();
-        e.stopPropagation();
-        return false;
-      }
-    }
-    return true;
-  }
-
-  private static MyTable getMyTable(NativeEvent event) {
-    Element e = event.getEventTarget().cast();
-    for (e = DOM.getParent(e); e != null; e = DOM.getParent(e)) {
-      EventListener l = DOM.getEventListener(e);
-      if (l instanceof MyTable) {
-        return (MyTable) l;
-      }
-    }
-    return null;
-  }
-
-  private DiffObject base;
-  private PatchSet.Id curr;
-  private Project.NameKey project;
-  private MyTable table;
-  private boolean register;
-  private JsArrayString reviewed;
-  private String scrollToPath;
-  private ChangeScreen.Style style;
-  private Widget replyButton;
-  private boolean editExists;
-  private Mode mode;
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    R.css().ensureInjected();
-  }
-
-  public void set(
-      DiffObject base,
-      PatchSet.Id curr,
-      Project.NameKey project,
-      ChangeScreen.Style style,
-      Widget replyButton,
-      Mode mode,
-      boolean editExists) {
-    this.base = base;
-    this.curr = curr;
-    this.project = project;
-    this.style = style;
-    this.replyButton = replyButton;
-    this.mode = mode;
-    this.editExists = editExists;
-  }
-
-  void setValue(
-      NativeMap<FileInfo> fileMap,
-      Timestamp myLastReply,
-      @Nullable NativeMap<JsArray<CommentInfo>> comments,
-      @Nullable NativeMap<JsArray<CommentInfo>> drafts) {
-    JsArray<FileInfo> list = fileMap.values();
-    FileInfo.sortFileInfoByPath(list);
-
-    DisplayCommand cmd = new DisplayCommand(fileMap, list, myLastReply, comments, drafts);
-    if (cmd.execute()) {
-      cmd.showProgressBar();
-      Scheduler.get().scheduleIncremental(cmd);
-    }
-  }
-
-  void showError(Throwable t) {
-    clear();
-    Label l = new Label(Resources.M.failedToLoadFileList(t.getMessage()));
-    add(l);
-    l.setStyleName(R.css().error());
-  }
-
-  void markReviewed(JsArrayString reviewed) {
-    if (table != null) {
-      table.markReviewed(reviewed);
-    } else {
-      this.reviewed = reviewed;
-    }
-  }
-
-  void unregisterKeys() {
-    register = false;
-
-    if (table != null) {
-      table.setRegisterKeys(false);
-    }
-  }
-
-  void registerKeys() {
-    register = true;
-
-    if (table != null) {
-      table.setRegisterKeys(true);
-    }
-  }
-
-  void scrollToPath(String path) {
-    if (table != null) {
-      table.scrollToPath(path);
-    } else {
-      scrollToPath = path;
-    }
-  }
-
-  void openAll() {
-    if (table != null) {
-      String self = Gerrit.selfRedirect(null);
-      for (FileInfo info : Natives.asList(table.list)) {
-        if (canOpen(info.path())) {
-          Window.open(self + "#" + url(info), "_blank", null);
-        }
-      }
-    }
-  }
-
-  private boolean canOpen(String path) {
-    return mode != Mode.EDIT || !Patch.isMagic(path) || Patch.COMMIT_MSG.equals(path);
-  }
-
-  private void setTable(MyTable table) {
-    clear();
-    add(table);
-    this.table = table;
-
-    if (register) {
-      table.setRegisterKeys(true);
-    }
-    if (reviewed != null) {
-      table.markReviewed(reviewed);
-      reviewed = null;
-    }
-    if (scrollToPath != null) {
-      table.scrollToPath(scrollToPath);
-      scrollToPath = null;
-    }
-  }
-
-  private String url(FileInfo info) {
-    return info.binary()
-        ? Dispatcher.toUnified(project, base, curr, info.path())
-        : mode == Mode.REVIEW
-            ? Dispatcher.toPatch(project, base, curr, info.path())
-            : Dispatcher.toEditScreen(project, curr, info.path());
-  }
-
-  private final class MyTable extends NavigationTable<FileInfo> {
-    private final NativeMap<FileInfo> map;
-    private final JsArray<FileInfo> list;
-
-    MyTable(NativeMap<FileInfo> map, JsArray<FileInfo> list) {
-      this.map = map;
-      this.list = list;
-      table.setWidth("");
-
-      keysNavigation.add(
-          new PrevKeyCommand(0, 'k', Util.C.patchTablePrev()),
-          new NextKeyCommand(0, 'j', Util.C.patchTableNext()));
-      keysNavigation.add(new OpenKeyCommand(0, 'o', Util.C.patchTableOpenDiff()));
-      keysNavigation.add(new OpenKeyCommand(0, KeyCodes.KEY_ENTER, Util.C.patchTableOpenDiff()));
-
-      keysNavigation.add(
-          new OpenFileCommand(list.length() - 1, 0, '[', Resources.C.openLastFile()),
-          new OpenFileCommand(0, 0, ']', Resources.C.openCommitMessage()));
-
-      keysAction.add(
-          new KeyCommand(0, 'r', PatchUtil.C.toggleReviewed()) {
-            @Override
-            public void onKeyPress(KeyPressEvent event) {
-              int row = getCurrentRow();
-              if (1 <= row && row <= MyTable.this.list.length()) {
-                FileInfo info = MyTable.this.list.get(row - 1);
-                InputElement b = getReviewed(info);
-                boolean c = !b.isChecked();
-                setReviewed(info, c);
-                b.setChecked(c);
-              }
-            }
-          });
-
-      setSavePointerId((!base.isBase() ? base.asString() + ".." : "") + curr.toString());
-    }
-
-    void onDelete(int idx) {
-      String path = list.get(idx).path();
-      ChangeEditApi.delete(
-          project.get(),
-          curr.getParentKey().get(),
-          path,
-          new AsyncCallback<VoidResult>() {
-            @Override
-            public void onSuccess(VoidResult result) {
-              Gerrit.display(PageLinks.toChangeInEditMode(project, curr.getParentKey()));
-            }
-
-            @Override
-            public void onFailure(Throwable caught) {}
-          });
-    }
-
-    void onRestore(int idx) {
-      String path = list.get(idx).path();
-      ChangeEditApi.restore(
-          project.get(),
-          curr.getParentKey().get(),
-          path,
-          new AsyncCallback<VoidResult>() {
-            @Override
-            public void onSuccess(VoidResult result) {
-              Gerrit.display(PageLinks.toChangeInEditMode(project, curr.getParentKey()));
-            }
-
-            @Override
-            public void onFailure(Throwable caught) {}
-          });
-    }
-
-    void onReviewed(InputElement checkbox, int idx) {
-      setReviewed(list.get(idx), checkbox.isChecked());
-    }
-
-    private void setReviewed(FileInfo info, boolean r) {
-      RestApi api =
-          ChangeApi.revision(project.get(), curr).view("files").id(info.path()).view("reviewed");
-      if (r) {
-        api.put(CallbackGroup.<ReviewInfo>emptyCallback());
-      } else {
-        api.delete(CallbackGroup.<ReviewInfo>emptyCallback());
-      }
-    }
-
-    void markReviewed(JsArrayString reviewed) {
-      for (int i = 0; i < reviewed.length(); i++) {
-        FileInfo info = map.get(reviewed.get(i));
-        if (info != null) {
-          getReviewed(info).setChecked(true);
-        }
-      }
-    }
-
-    private InputElement getReviewed(FileInfo info) {
-      CellFormatter fmt = table.getCellFormatter();
-      Element e = fmt.getElement(1 + info._row(), 1);
-      return InputElement.as(e.getFirstChildElement());
-    }
-
-    void scrollToPath(String path) {
-      FileInfo info = map.get(path);
-      if (info != null) {
-        movePointerTo(1 + info._row(), true);
-      }
-    }
-
-    @Override
-    protected Object getRowItemKey(FileInfo item) {
-      return item.path();
-    }
-
-    @Override
-    protected int findRow(Object id) {
-      FileInfo info = map.get((String) id);
-      return info != null ? 1 + info._row() : -1;
-    }
-
-    @Override
-    protected FileInfo getRowItem(int row) {
-      if (1 <= row && row <= list.length()) {
-        return list.get(row - 1);
-      }
-      return null;
-    }
-
-    @Override
-    protected void onOpenRow(int row) {
-      if (1 <= row && row <= list.length()) {
-        FileInfo info = list.get(row - 1);
-        if (canOpen(info.path())) {
-          Gerrit.display(url(info));
-        }
-      }
-    }
-
-    @Override
-    protected void onCellSingleClick(Event event, int row, int column) {
-      if (column == C_PATH && link.handleAsClick(event)) {
-        onOpenRow(row);
-      } else {
-        super.onCellSingleClick(event, row, column);
-      }
-    }
-
-    private class OpenFileCommand extends KeyCommand {
-      private final int index;
-
-      OpenFileCommand(int index, int modifiers, char c, String helpText) {
-        super(modifiers, c, helpText);
-        this.index = index;
-      }
-
-      @Override
-      public void onKeyPress(KeyPressEvent event) {
-        FileInfo info = list.get(index);
-        if (canOpen(info.path())) {
-          Gerrit.display(url(info));
-        }
-      }
-    }
-  }
-
-  private final class DisplayCommand implements RepeatingCommand {
-    private final SafeHtmlBuilder sb = new SafeHtmlBuilder();
-    private final MyTable myTable;
-    private final JsArray<FileInfo> list;
-    private final Timestamp myLastReply;
-    private final NativeMap<JsArray<CommentInfo>> comments;
-    private final NativeMap<JsArray<CommentInfo>> drafts;
-    private final boolean hasUser;
-    private final boolean showChangeSizeBars;
-    private boolean attached;
-    private int row;
-    private double start;
-    private ProgressBar meter;
-    private String lastPath = "";
-
-    private boolean hasBinaryFile;
-    private boolean hasNonBinaryFile;
-    private int inserted;
-    private int deleted;
-    private long binOldSize;
-    private long bytesInserted;
-    private long bytesDeleted;
-
-    private DisplayCommand(
-        NativeMap<FileInfo> map,
-        JsArray<FileInfo> list,
-        Timestamp myLastReply,
-        @Nullable NativeMap<JsArray<CommentInfo>> comments,
-        @Nullable NativeMap<JsArray<CommentInfo>> drafts) {
-      this.myTable = new MyTable(map, list);
-      this.list = list;
-      this.myLastReply = myLastReply;
-      this.comments = comments;
-      this.drafts = drafts;
-      this.hasUser = Gerrit.isSignedIn();
-      this.showChangeSizeBars = Gerrit.getUserPreferences().sizeBarInChangeTable();
-      myTable.addStyleName(R.css().table());
-    }
-
-    @Override
-    public boolean execute() {
-      boolean attachedNow = isAttached();
-      if (!attached && attachedNow) {
-        // Remember that we have been attached at least once. If
-        // later we find we aren't attached we should stop running.
-        attached = true;
-      } else if (attached && !attachedNow) {
-        // If the user navigated away, we aren't in the DOM anymore.
-        // Don't continue to render.
-        return false;
-      }
-
-      start = System.currentTimeMillis();
-      if (row == 0) {
-        header(sb);
-        computeInsertedDeleted();
-      }
-      while (row < list.length()) {
-        FileInfo info = list.get(row);
-        info._row(row);
-        render(sb, info);
-        if ((++row % 10) == 0 && longRunning()) {
-          updateMeter();
-          return true;
-        }
-      }
-      footer(sb);
-      myTable.resetHtml(sb);
-      myTable.finishDisplay();
-      setTable(myTable);
-      return false;
-    }
-
-    private void computeInsertedDeleted() {
-      inserted = 0;
-      deleted = 0;
-      binOldSize = 0;
-      bytesInserted = 0;
-      bytesDeleted = 0;
-      for (int i = 0; i < list.length(); i++) {
-        FileInfo info = list.get(i);
-        if (!Patch.isMagic(info.path())) {
-          if (!info.binary()) {
-            hasNonBinaryFile = true;
-            inserted += info.linesInserted();
-            deleted += info.linesDeleted();
-          } else {
-            hasBinaryFile = true;
-            binOldSize += info.size() - info.sizeDelta();
-            if (info.sizeDelta() >= 0) {
-              bytesInserted += info.sizeDelta();
-            } else {
-              bytesDeleted += info.sizeDelta();
-            }
-          }
-        }
-      }
-    }
-
-    void showProgressBar() {
-      if (meter == null) {
-        meter = new ProgressBar(Util.M.loadingPatchSet(curr.get()));
-        FileTable.this.clear();
-        FileTable.this.add(meter);
-      }
-      updateMeter();
-    }
-
-    void updateMeter() {
-      if (meter != null) {
-        int n = list.length();
-        meter.setValue((100 * row) / n);
-      }
-    }
-
-    private boolean longRunning() {
-      return System.currentTimeMillis() - start > 200;
-    }
-
-    private void header(SafeHtmlBuilder sb) {
-      sb.openTr().setStyleName(R.css().nohover());
-      sb.openTh().setStyleName(R.css().pointer()).closeTh();
-      if (mode == Mode.REVIEW) {
-        sb.openTh().setStyleName(R.css().reviewed()).closeTh();
-      } else {
-        sb.openTh().setStyleName(R.css().restoreDelete()).closeTh();
-      }
-      sb.openTh().setStyleName(R.css().status()).closeTh();
-      sb.openTh().append(Util.C.patchTableColumnName()).closeTh();
-      sb.openTh().setAttribute("colspan", 3).append(Util.C.patchTableColumnComments()).closeTh();
-      sb.openTh().setAttribute("colspan", 2).append(Util.C.patchTableColumnSize()).closeTh();
-      sb.closeTr();
-    }
-
-    private void render(SafeHtmlBuilder sb, FileInfo info) {
-      sb.openTr();
-      sb.openTd().setStyleName(R.css().pointer()).closeTd();
-      if (mode == Mode.REVIEW) {
-        columnReviewed(sb, info);
-      } else {
-        columnDeleteRestore(sb, info);
-      }
-      columnStatus(sb, info);
-      columnPath(sb, info);
-      columnComments(sb, info);
-      columnDelta1(sb, info);
-      columnDelta2(sb, info);
-      sb.closeTr();
-    }
-
-    private void columnReviewed(SafeHtmlBuilder sb, FileInfo info) {
-      sb.openTd().setStyleName(R.css().reviewed());
-      if (hasUser) {
-        sb.openElement("input")
-            .setAttribute("title", Resources.C.reviewedFileTitle())
-            .setAttribute("type", "checkbox")
-            .setAttribute("onclick", REVIEWED + "(event," + info._row() + ")")
-            .closeSelf();
-      }
-      sb.closeTd();
-    }
-
-    private void columnDeleteRestore(SafeHtmlBuilder sb, FileInfo info) {
-      sb.openTd().setStyleName(R.css().restoreDelete());
-      if (hasUser) {
-        if (!Patch.isMagic(info.path())) {
-          boolean editable = isEditable(info);
-          sb.openDiv()
-              .openElement("button")
-              .setAttribute("title", Resources.C.restoreFileInline())
-              .setAttribute("onclick", RESTORE + "(event," + info._row() + ")")
-              .append(new ImageResourceRenderer().render(Gerrit.RESOURCES.editUndo()))
-              .closeElement("button");
-          if (editable) {
-            sb.openElement("button")
-                .setAttribute("title", Resources.C.removeFileInline())
-                .setAttribute("onclick", DELETE + "(event," + info._row() + ")")
-                .append(new ImageResourceRenderer().render(Gerrit.RESOURCES.redNot()))
-                .closeElement("button");
-          }
-          sb.closeDiv();
-        }
-      }
-      sb.closeTd();
-    }
-
-    private boolean isEditable(FileInfo info) {
-      String status = info.status();
-      return status == null || !ChangeType.DELETED.matches(status);
-    }
-
-    private void columnStatus(SafeHtmlBuilder sb, FileInfo info) {
-      sb.openTd().setStyleName(R.css().status());
-      if (!Patch.isMagic(info.path())
-          && info.status() != null
-          && !ChangeType.MODIFIED.matches(info.status())) {
-        sb.append(info.status());
-      }
-      sb.closeTd();
-    }
-
-    private void columnPath(SafeHtmlBuilder sb, FileInfo info) {
-      String path = info.path();
-
-      sb.openTd().setStyleName(R.css().pathColumn());
-
-      if (!canOpen(path)) {
-        sb.openDiv();
-        appendPath(path);
-        sb.closeDiv();
-        sb.closeTd();
-        return;
-      }
-
-      sb.openAnchor();
-
-      if (mode == Mode.EDIT && !isEditable(info)) {
-        sb.setAttribute("onclick", RESTORE + "(event," + info._row() + ")");
-      } else {
-        sb.setAttribute("href", "#" + url(info))
-            .setAttribute("onclick", OPEN + "(event," + info._row() + ")");
-      }
-      appendPath(path);
-      sb.closeAnchor();
-      if (info.oldPath() != null) {
-        sb.br();
-        sb.openSpan().setStyleName(R.css().renameCopySource()).append(info.oldPath()).closeSpan();
-      }
-      sb.closeTd();
-    }
-
-    private void appendPath(String path) {
-      if (Patch.COMMIT_MSG.equals(path)) {
-        sb.append(Util.C.commitMessage());
-      } else if (Patch.MERGE_LIST.equals(path)) {
-        sb.append(Util.C.mergeList());
-      } else if (Gerrit.getUserPreferences().muteCommonPathPrefixes()) {
-        int commonPrefixLen = commonPrefix(path);
-        if (commonPrefixLen > 0) {
-          sb.openSpan()
-              .setStyleName(R.css().commonPrefix())
-              .append(path.substring(0, commonPrefixLen))
-              .closeSpan();
-        }
-        sb.append(path.substring(commonPrefixLen));
-        lastPath = path;
-      } else {
-        sb.append(path);
-      }
-    }
-
-    private int commonPrefix(String path) {
-      for (int n = path.length(); n > 0; ) {
-        int s = path.lastIndexOf('/', n);
-        if (s < 0) {
-          return 0;
-        }
-
-        String p = path.substring(0, s + 1);
-        if (lastPath.startsWith(p)) {
-          return s + 1;
-        }
-        n = s - 1;
-      }
-      return 0;
-    }
-
-    private void columnComments(SafeHtmlBuilder sb, FileInfo info) {
-      JsArray<CommentInfo> cList = filterForParent(get(info.path(), comments));
-      JsArray<CommentInfo> dList = filterForParent(get(info.path(), drafts));
-
-      sb.openTd().setStyleName(R.css().draftColumn());
-      if (dList.length() > 0) {
-        sb.append("drafts: ").append(dList.length());
-      }
-      sb.closeTd();
-
-      int cntAll = cList.length();
-      int cntNew = 0;
-      if (myLastReply != null) {
-        for (int i = cntAll - 1; i >= 0; i--) {
-          CommentInfo m = cList.get(i);
-          if (m.updated().compareTo(myLastReply) > 0) {
-            cntNew++;
-          } else {
-            break;
-          }
-        }
-      }
-
-      sb.openTd().setStyleName(R.css().newColumn());
-      if (cntNew > 0) {
-        sb.append("new: ").append(cntNew);
-      }
-      sb.closeTd();
-
-      sb.openTd().setStyleName(R.css().commentColumn());
-      if (cntAll - cntNew > 0) {
-        sb.append("comments: ").append(cntAll - cntNew);
-      }
-      sb.closeTd();
-    }
-
-    private JsArray<CommentInfo> filterForParent(JsArray<CommentInfo> list) {
-      JsArray<CommentInfo> result = JsArray.createArray().cast();
-      for (CommentInfo c : Natives.asList(list)) {
-        if (c.side() == Side.REVISION) {
-          result.push(c);
-        } else if (base.isBaseOrAutoMerge() && !c.hasParent()) {
-          result.push(c);
-        } else if (base.isParent() && c.parent() == base.getParentNum()) {
-          result.push(c);
-        }
-      }
-      return result;
-    }
-
-    private JsArray<CommentInfo> get(String p, NativeMap<JsArray<CommentInfo>> m) {
-      JsArray<CommentInfo> r = null;
-      if (m != null) {
-        r = m.get(p);
-      }
-      if (r == null) {
-        r = JsArray.createArray().cast();
-      }
-      return r;
-    }
-
-    private void columnDelta1(SafeHtmlBuilder sb, FileInfo info) {
-      sb.openTd().setStyleName(R.css().deltaColumn1());
-      if (!Patch.isMagic(info.path()) && !info.binary()) {
-        if (showChangeSizeBars) {
-          sb.append(info.linesInserted() + info.linesDeleted());
-        } else if (!ChangeType.DELETED.matches(info.status())) {
-          if (ChangeType.ADDED.matches(info.status())) {
-            sb.append(info.linesInserted()).append(" lines");
-          } else {
-            sb.append("+").append(info.linesInserted()).append(", -").append(info.linesDeleted());
-          }
-        }
-      } else if (info.binary()) {
-        sb.append(formatBytes(info.sizeDelta()));
-        long oldSize = info.size() - info.sizeDelta();
-        if (oldSize != 0) {
-          sb.append(" (").append(formatPercentage(oldSize, info.sizeDelta())).append(")");
-        }
-      }
-      sb.closeTd();
-    }
-
-    private void columnDelta2(SafeHtmlBuilder sb, FileInfo info) {
-      sb.openTd().setStyleName(R.css().deltaColumn2());
-      if (showChangeSizeBars
-          && !Patch.isMagic(info.path())
-          && !info.binary()
-          && (info.linesInserted() != 0 || info.linesDeleted() != 0)) {
-        int w = 80;
-        int t = inserted + deleted;
-        int i = Math.max(5, (int) (((double) w) * info.linesInserted() / t));
-        int d = Math.max(5, (int) (((double) w) * info.linesDeleted() / t));
-
-        sb.setAttribute(
-            "title", Util.M.patchTableSize_LongModify(info.linesInserted(), info.linesDeleted()));
-
-        if (0 < info.linesInserted()) {
-          sb.openDiv()
-              .setStyleName(R.css().inserted())
-              .setAttribute("style", "width:" + i + "px")
-              .closeDiv();
-        }
-        if (0 < info.linesDeleted()) {
-          sb.openDiv()
-              .setStyleName(R.css().deleted())
-              .setAttribute("style", "width:" + d + "px")
-              .closeDiv();
-        }
-      }
-      sb.closeTd();
-    }
-
-    private void footer(SafeHtmlBuilder sb) {
-      sb.openTr().setStyleName(R.css().nohover());
-      sb.openTh().setStyleName(R.css().pointer()).closeTh();
-      if (mode == Mode.REVIEW) {
-        sb.openTh().setStyleName(R.css().reviewed()).closeTh();
-      } else {
-        sb.openTh().setStyleName(R.css().restoreDelete()).closeTh();
-      }
-      sb.openTh().setStyleName(R.css().status()).closeTh();
-      sb.openTd().closeTd(); // path
-      sb.openTd().setAttribute("colspan", 3).closeTd(); // comments
-
-      // delta1
-      sb.openTh().setStyleName(R.css().deltaColumn1());
-      if (hasNonBinaryFile) {
-        sb.append(Util.M.patchTableSize_Modify(inserted, deleted));
-      }
-      if (hasBinaryFile) {
-        if (hasNonBinaryFile) {
-          sb.br();
-        }
-        if (binOldSize != 0) {
-          sb.append(
-              Util.M.patchTableSize_ModifyBinaryFilesWithPercentages(
-                  formatAbsBytes(bytesInserted),
-                  formatAbsPercentage(binOldSize, bytesInserted),
-                  formatAbsBytes(bytesDeleted),
-                  formatAbsPercentage(binOldSize, bytesDeleted)));
-        } else {
-          sb.append(
-              Util.M.patchTableSize_ModifyBinaryFiles(
-                  formatAbsBytes(bytesInserted), formatAbsBytes(bytesDeleted)));
-        }
-      }
-      sb.closeTh();
-
-      // delta2
-      sb.openTh().setStyleName(R.css().deltaColumn2());
-      if (showChangeSizeBars) {
-        int w = 80;
-        int t = inserted + deleted;
-        int i = Math.max(1, (int) (((double) w) * inserted / t));
-        int d = Math.max(1, (int) (((double) w) * deleted / t));
-        if (i + d > w && i > d) {
-          i = w - d;
-        } else if (i + d > w && d > i) {
-          d = w - i;
-        }
-        if (0 < inserted) {
-          sb.openDiv()
-              .setStyleName(R.css().inserted())
-              .setAttribute("style", "width:" + i + "px")
-              .closeDiv();
-        }
-        if (0 < deleted) {
-          sb.openDiv()
-              .setStyleName(R.css().deleted())
-              .setAttribute("style", "width:" + d + "px")
-              .closeDiv();
-        }
-      }
-      sb.closeTh();
-
-      sb.closeTr();
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FollowUpAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FollowUpAction.java
deleted file mode 100644
index a4c90b8..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FollowUpAction.java
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.common.PageLinks;
-import com.google.gwt.user.client.ui.Button;
-
-class FollowUpAction extends ActionMessageBox {
-  private final String project;
-  private final String branch;
-  private final String topic;
-  private final String base;
-
-  FollowUpAction(Button b, String project, String branch, String topic, String key) {
-    super(b);
-    this.project = project;
-    this.branch = branch;
-    this.topic = topic;
-    this.base = project + "~" + branch + "~" + key;
-  }
-
-  @Override
-  void send(String message) {
-    ChangeApi.createChange(
-        project,
-        branch,
-        topic,
-        message,
-        base,
-        new GerritCallback<ChangeInfo>() {
-          @Override
-          public void onSuccess(ChangeInfo result) {
-            Gerrit.display(PageLinks.toChange(result.projectNameKey(), result.legacyId()));
-            hide();
-          }
-        });
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Hashtags.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Hashtags.java
deleted file mode 100644
index 1044828..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Hashtags.java
+++ /dev/null
@@ -1,272 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.NativeEvent;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyDownEvent;
-import com.google.gwt.event.dom.client.KeyDownHandler;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.rpc.StatusCodeException;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.ImageResourceRenderer;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwtexpui.globalkey.client.NpTextBox;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-import java.util.Iterator;
-
-public class Hashtags extends Composite {
-
-  interface Binder extends UiBinder<HTMLPanel, Hashtags> {}
-
-  private static final int VISIBLE_LENGTH = 55;
-  private static final Binder uiBinder = GWT.create(Binder.class);
-  private static final String REMOVE;
-  private static final String DATA_ID = "data-id";
-
-  private PatchSet.Id psId;
-  private boolean canEdit;
-
-  static {
-    REMOVE = DOM.createUniqueId().replace('-', '_');
-    init(REMOVE);
-  }
-
-  private static native void init(String r) /*-{
-    $wnd[r] = $entry(function(e) {
-      @com.google.gerrit.client.change.Hashtags::onRemove(Lcom/google/gwt/dom/client/NativeEvent;)(e)
-    });
-  }-*/;
-
-  private static void onRemove(NativeEvent event) {
-    String hashtags = getDataId(event);
-    if (hashtags != null) {
-      final ChangeScreen screen = ChangeScreen.get(event);
-      final PatchSet.Id psId = screen.getPatchSetId();
-      ChangeApi.hashtags(screen.getProject().get(), psId.getParentKey().get())
-          .post(
-              PostInput.create(null, hashtags),
-              new GerritCallback<JavaScriptObject>() {
-                @Override
-                public void onSuccess(JavaScriptObject result) {
-                  if (screen.isCurrentView()) {
-                    Gerrit.display(PageLinks.toChange(screen.getProject(), psId));
-                  }
-                }
-              });
-    }
-  }
-
-  private static String getDataId(NativeEvent event) {
-    Element e = event.getEventTarget().cast();
-    while (e != null) {
-      String v = e.getAttribute(DATA_ID);
-      if (!v.isEmpty()) {
-        return v;
-      }
-      e = e.getParentElement();
-    }
-    return null;
-  }
-
-  @UiField Element hashtagsText;
-  @UiField Image addHashtagIcon;
-  @UiField Element form;
-  @UiField Element error;
-  @UiField NpTextBox hashtagTextBox;
-
-  private ChangeScreen.Style style;
-  private Change.Id changeId;
-  private Project.NameKey project;
-
-  public Hashtags() {
-
-    initWidget(uiBinder.createAndBindUi(this));
-
-    hashtagTextBox.setVisibleLength(VISIBLE_LENGTH);
-    hashtagTextBox.addKeyDownHandler(
-        new KeyDownHandler() {
-          @Override
-          public void onKeyDown(KeyDownEvent e) {
-            if (e.getNativeKeyCode() == KeyCodes.KEY_ESCAPE) {
-              onCancel(null);
-            } else if (e.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
-              onAdd(null);
-            }
-          }
-        });
-
-    addHashtagIcon.addDomHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            onOpenForm();
-          }
-        },
-        ClickEvent.getType());
-  }
-
-  void init(ChangeScreen.Style style) {
-    this.style = style;
-  }
-
-  void set(ChangeInfo info, String revision) {
-    psId = new PatchSet.Id(info.legacyId(), info.revisions().get(revision)._number());
-    project = info.projectNameKey();
-
-    canEdit = info.hasActions() && info.actions().containsKey("hashtags");
-    this.changeId = info.legacyId();
-    display(info);
-    addHashtagIcon.setVisible(canEdit);
-  }
-
-  void onOpenForm() {
-    UIObject.setVisible(form, true);
-    UIObject.setVisible(error, false);
-    addHashtagIcon.setVisible(false);
-    hashtagTextBox.setFocus(true);
-  }
-
-  private void display(ChangeInfo info) {
-    hashtagsText.setInnerSafeHtml(formatHashtags(info));
-  }
-
-  private void display(JsArrayString hashtags) {
-    hashtagsText.setInnerSafeHtml(formatHashtags(hashtags));
-  }
-
-  private SafeHtmlBuilder formatHashtags(ChangeInfo info) {
-    if (info.hashtags() != null) {
-      return formatHashtags(info.hashtags());
-    }
-    return new SafeHtmlBuilder();
-  }
-
-  private SafeHtmlBuilder formatHashtags(JsArrayString hashtags) {
-    SafeHtmlBuilder html = new SafeHtmlBuilder();
-    Iterator<String> itr = Natives.asList(hashtags).iterator();
-    while (itr.hasNext()) {
-      String hashtagName = itr.next();
-      html.openSpan()
-          .setAttribute(DATA_ID, hashtagName)
-          .setStyleName(style.hashtagName())
-          .openAnchor()
-          .setAttribute("href", "#" + PageLinks.toChangeQuery("hashtag:\"" + hashtagName + "\""))
-          .setAttribute("role", "listitem")
-          .openSpan()
-          .setStyleName(style.hashtagIcon())
-          .append(new ImageResourceRenderer().render(Gerrit.RESOURCES.hashtag()))
-          .closeSpan()
-          .append(" ")
-          .append(hashtagName)
-          .closeAnchor();
-      if (canEdit) {
-        html.openElement("button")
-            .setAttribute("title", "Remove hashtag")
-            .setAttribute("onclick", REMOVE + "(event)")
-            .append("×")
-            .closeElement("button");
-      }
-      html.closeSpan();
-      if (itr.hasNext()) {
-        html.append(' ');
-      }
-    }
-    return html;
-  }
-
-  @UiHandler("cancel")
-  void onCancel(@SuppressWarnings("unused") ClickEvent e) {
-    addHashtagIcon.setVisible(true);
-    UIObject.setVisible(form, false);
-    hashtagTextBox.setFocus(false);
-  }
-
-  @UiHandler("add")
-  void onAdd(@SuppressWarnings("unused") ClickEvent e) {
-    String hashtag = hashtagTextBox.getText();
-    if (!hashtag.isEmpty()) {
-      addHashtag(hashtag);
-    }
-  }
-
-  private void addHashtag(String hashtags) {
-    ChangeApi.hashtags(project.get(), changeId.get())
-        .post(
-            PostInput.create(hashtags, null),
-            new GerritCallback<JsArrayString>() {
-              @Override
-              public void onSuccess(JsArrayString result) {
-                Gerrit.display(
-                    PageLinks.toChange(project, psId.getParentKey(), String.valueOf(psId.get())));
-              }
-
-              @Override
-              public void onFailure(Throwable err) {
-                UIObject.setVisible(error, true);
-                error.setInnerText(
-                    err instanceof StatusCodeException
-                        ? ((StatusCodeException) err).getEncodedResponse()
-                        : err.getMessage());
-                hashtagTextBox.setEnabled(true);
-              }
-            });
-  }
-
-  public static class PostInput extends JavaScriptObject {
-    public static PostInput create(String add, String remove) {
-      PostInput input = createObject().cast();
-      input.init(toJsArrayString(add), toJsArrayString(remove));
-      return input;
-    }
-
-    private static JsArrayString toJsArrayString(String commaSeparated) {
-      if (commaSeparated == null || commaSeparated.equals("")) {
-        return null;
-      }
-      JsArrayString array = JsArrayString.createArray().cast();
-      for (String hashtag : commaSeparated.split(",")) {
-        array.push(hashtag.trim());
-      }
-      return array;
-    }
-
-    private native void init(JsArrayString add, JsArrayString remove) /*-{
-      this.add = add;
-      this.remove = remove;
-    }-*/;
-
-    protected PostInput() {}
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Hashtags.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Hashtags.ui.xml
deleted file mode 100644
index c0bfd1c..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Hashtags.ui.xml
+++ /dev/null
@@ -1,82 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:c='urn:import:com.google.gwtexpui.globalkey.client'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-  <ui:with field='ico' type='com.google.gerrit.client.GerritResources'/>
-  <ui:with field='res' type='com.google.gerrit.client.change.Resources'/>
-  <ui:style gss='false'>
-    button.openAdd {
-      margin: 3px 3px 0 0;
-      float: right;
-      color: rgba(0, 0, 0, 0.15);
-      background-color: #f5f5f5;
-      background-image: -webkit-linear-gradient(top, #f5f5f5, #f1f1f1);
-      -webkit-border-radius: 2px;
-      -moz-border-radius: 2px;
-      border-radius: 2px;
-      -webkit-box-sizing: content-box;
-      -moz-box-sizing: content-box;
-      box-sizing: content-box;
-    }
-    button.openAdd div {
-      width: auto;
-      color: #444;
-    }
-
-    .hashtagTextBox {
-      margin-bottom: 2px;
-    }
-
-    .error {
-      color: #D33D3D;
-      font-weight: bold;
-    }
-
-    .addHashtag,
-    .cancel {
-      cursor: pointer;
-      float: right;
-    }
-  </ui:style>
-  <g:HTMLPanel>
-    <div>
-      <span ui:field='hashtagsText'/>
-      <g:Image ui:field='addHashtagIcon'
-        resource='{ico.addHashtag}'
-        styleName='{style.addHashtag}'
-        title='Add Hashtag'/>
-    </div>
-    <div ui:field='form' style='display: none' aria-hidden='true'>
-      <c:NpTextBox ui:field='hashtagTextBox' styleName='{style.hashtagTextBox}'/>
-      <div ui:field='error'
-           class='{style.error}'
-           style='display: none' aria-hidden='true'/>
-      <div>
-        <g:Button ui:field='add' styleName='{res.style.button}'>
-          <div>Add</div>
-        </g:Button>
-        <g:Button ui:field='cancel'
-            styleName='{res.style.button}'
-            addStyleNames='{style.cancel}'>
-          <div>Cancel</div>
-        </g:Button>
-      </div>
-    </div>
-   </g:HTMLPanel>
-  </ui:UiBinder>
\ No newline at end of file
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/History.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/History.java
deleted file mode 100644
index 55e021f..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/History.java
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.changes.CommentInfo;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.ChangeInfo.MessageInfo;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.CommentLinkProcessor;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Widget;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-class History extends FlowPanel {
-  private CommentLinkProcessor clp;
-  private ReplyAction replyAction;
-  private Change.Id changeId;
-  private Project.NameKey project;
-
-  private final Map<Integer, List<CommentInfo>> byAuthor = new HashMap<>();
-
-  void set(CommentLinkProcessor clp, ReplyAction ra, Change.Id id, ChangeInfo info) {
-    this.clp = clp;
-    this.replyAction = ra;
-    this.changeId = id;
-    this.project = info.projectNameKey();
-
-    JsArray<MessageInfo> messages = info.messages();
-    if (messages != null) {
-      for (MessageInfo msg : Natives.asList(messages)) {
-        Message ui = new Message(this, msg);
-        ui.addComments(comments(msg));
-        add(ui);
-      }
-      autoOpen(ChangeScreen.myLastReply(info));
-    }
-  }
-
-  private void autoOpen(Timestamp lastReply) {
-    if (lastReply == null) {
-      for (Widget child : getChildren()) {
-        ((Message) child).autoOpen();
-      }
-    } else {
-      for (int i = getChildren().size() - 1; i >= 0; i--) {
-        Message ui = (Message) getChildren().get(i);
-        MessageInfo msg = ui.getMessageInfo();
-        if (lastReply.compareTo(msg.date()) < 0) {
-          ui.autoOpen();
-        } else {
-          break;
-        }
-      }
-    }
-  }
-
-  CommentLinkProcessor getCommentLinkProcessor() {
-    return clp;
-  }
-
-  Change.Id getChangeId() {
-    return changeId;
-  }
-
-  Project.NameKey getProject() {
-    return project;
-  }
-
-  void replyTo(MessageInfo info) {
-    replyAction.onReply(info);
-  }
-
-  void addComments(NativeMap<JsArray<CommentInfo>> map) {
-    for (String path : map.keySet()) {
-      for (CommentInfo c : Natives.asList(map.get(path))) {
-        c.path(path);
-        if (c.author() != null) {
-          int authorId = c.author()._accountId();
-          List<CommentInfo> l = byAuthor.get(authorId);
-          if (l == null) {
-            l = new ArrayList<>();
-            byAuthor.put(authorId, l);
-          }
-          l.add(c);
-        }
-      }
-    }
-  }
-
-  private List<CommentInfo> comments(MessageInfo msg) {
-    if (msg.author() == null) {
-      return Collections.emptyList();
-    }
-
-    int authorId = msg.author()._accountId();
-    List<CommentInfo> list = byAuthor.get(authorId);
-    if (list == null) {
-      return Collections.emptyList();
-    }
-
-    Timestamp when = msg.date();
-    List<CommentInfo> match = new ArrayList<>();
-    List<CommentInfo> other = new ArrayList<>();
-    for (CommentInfo c : list) {
-      if (c.updated().compareTo(when) <= 0) {
-        match.add(c);
-      } else {
-        other.add(c);
-      }
-    }
-    if (match.isEmpty()) {
-      return Collections.emptyList();
-    } else if (other.isEmpty()) {
-      byAuthor.remove(authorId);
-    } else {
-      byAuthor.put(authorId, other);
-    }
-    return match;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInAction.java
deleted file mode 100644
index 5557f90..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInAction.java
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwt.user.client.ui.Widget;
-
-class IncludedInAction extends RightSidePopdownAction {
-  private final IncludedInBox includedInBox;
-
-  IncludedInAction(
-      Project.NameKey project,
-      Change.Id changeId,
-      ChangeScreen.Style style,
-      UIObject relativeTo,
-      Widget includedInButton) {
-    super(style, relativeTo, includedInButton);
-    this.includedInBox = new IncludedInBox(project, changeId);
-  }
-
-  @Override
-  Widget getWidget() {
-    return includedInBox;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInBox.java
deleted file mode 100644
index 9751f54..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInBox.java
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.info.ChangeInfo.IncludedInInfo;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.dom.client.Document;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.TableCellElement;
-import com.google.gwt.dom.client.TableElement;
-import com.google.gwt.dom.client.TableRowElement;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.safehtml.shared.SafeHtml;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-
-class IncludedInBox extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, IncludedInBox> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  interface Style extends CssResource {
-    String includedInElement();
-  }
-
-  private final Project.NameKey project;
-  private final Change.Id changeId;
-  private boolean loaded;
-
-  @UiField Style style;
-  @UiField TableElement table;
-  @UiField Element branches;
-  @UiField Element tags;
-
-  IncludedInBox(Project.NameKey project, Change.Id changeId) {
-    this.project = project;
-    this.changeId = changeId;
-    initWidget(uiBinder.createAndBindUi(this));
-  }
-
-  @Override
-  protected void onLoad() {
-    if (!loaded) {
-      ChangeApi.includedIn(
-          project.get(),
-          changeId.get(),
-          new AsyncCallback<IncludedInInfo>() {
-            @Override
-            public void onSuccess(IncludedInInfo r) {
-              branches.setInnerSafeHtml(formatList(r.branches()));
-              tags.setInnerSafeHtml(formatList(r.tags()));
-              for (String n : r.externalNames()) {
-                JsArrayString external = r.external(n);
-                if (external.length() > 0) {
-                  appendRow(n, external);
-                }
-              }
-              loaded = true;
-            }
-
-            @Override
-            public void onFailure(Throwable caught) {}
-          });
-    }
-  }
-
-  private SafeHtml formatList(JsArrayString l) {
-    SafeHtmlBuilder html = new SafeHtmlBuilder();
-    int size = l.length();
-    for (int i = 0; i < size; i++) {
-      html.openSpan().addStyleName(style.includedInElement()).append(l.get(i)).closeSpan();
-      if (i < size - 1) {
-        html.append(", ");
-      }
-    }
-    return html;
-  }
-
-  private void appendRow(String title, JsArrayString l) {
-    TableRowElement row = table.insertRow(-1);
-    TableCellElement th = Document.get().createTHElement();
-    th.setInnerText(title);
-    row.appendChild(th);
-    row.insertCell(-1).setInnerSafeHtml(formatList(l));
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInBox.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInBox.ui.xml
deleted file mode 100644
index 36ac734..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInBox.ui.xml
+++ /dev/null
@@ -1,77 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-  <ui:style gss='false' type='com.google.gerrit.client.change.IncludedInBox.Style'>
-    .includedInBox {
-      min-width: 300px;
-      max-width: 580px;
-      margin: 5px;
-    }
-
-    .includedInTable {
-      border-spacing: 0;
-    }
-
-    .includedInTable th {
-      width: 60px;
-      color: #444;
-      font-weight: normal;
-      vertical-align: top;
-      text-align: left;
-      padding-right: 5px;
-    }
-
-    .includedInElement {
-      font-size: smaller;
-      font-family: monospace;
-    }
-
-    .includedInElement span {
-      width: 500px;
-      white-space: nowrap;
-      display: inline-block;
-      overflow: hidden;
-      text-overflow: ellipsis;
-    }
-
-    .includedInElement .gwt-TextBox {
-      padding: 0;
-      margin: 0;
-      border: 0;
-      max-height: 18px;
-      width: 500px;
-    }
-
-    .includedInElement div {
-      float: right;
-    }
-  </ui:style>
-  <g:HTMLPanel styleName='{style.includedInBox}'>
-    <table class='{style.includedInTable}' ui:field='table'>
-      <tr>
-        <th><ui:msg>Branches</ui:msg></th>
-          <td ui:field='branches'/>
-      </tr>
-      <tr>
-        <th><ui:msg>Tags</ui:msg></th>
-          <td ui:field='tags'/>
-      </tr>
-    </table>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Labels.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Labels.java
deleted file mode 100644
index 801a927..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Labels.java
+++ /dev/null
@@ -1,354 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import static java.util.stream.Collectors.collectingAndThen;
-import static java.util.stream.Collectors.toCollection;
-import static java.util.stream.Collectors.toList;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.changes.Util;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.info.AccountInfo.AvatarInfo;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.ChangeInfo.ApprovalInfo;
-import com.google.gerrit.client.info.ChangeInfo.LabelInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.common.data.LabelValue;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.NativeEvent;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.safehtml.client.SafeHtml;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/** Displays a table of label and reviewer scores. */
-class Labels extends Grid {
-  private static final String DATA_ID = "data-id";
-  private static final String DATA_VOTE = "data-vote";
-  private static final String REMOVE_REVIEWER;
-  private static final String REMOVE_VOTE;
-
-  static {
-    REMOVE_REVIEWER = DOM.createUniqueId().replace('-', '_');
-    REMOVE_VOTE = DOM.createUniqueId().replace('-', '_');
-    init(REMOVE_REVIEWER, REMOVE_VOTE);
-  }
-
-  private static native void init(String r, String v) /*-{
-    $wnd[r] = $entry(function(e) {
-      @com.google.gerrit.client.change.Labels::onRemoveReviewer(Lcom/google/gwt/dom/client/NativeEvent;)(e)
-    });
-    $wnd[v] = $entry(function(e) {
-      @com.google.gerrit.client.change.Labels::onRemoveVote(Lcom/google/gwt/dom/client/NativeEvent;)(e)
-    });
-  }-*/;
-
-  private static void onRemoveReviewer(NativeEvent event) {
-    Integer user = getDataId(event);
-    if (user != null) {
-      final ChangeScreen screen = ChangeScreen.get(event);
-      final Change.Id changeId = screen.getPatchSetId().getParentKey();
-      ChangeApi.reviewer(screen.getProject().get(), changeId.get(), user)
-          .delete(
-              new GerritCallback<JavaScriptObject>() {
-                @Override
-                public void onSuccess(JavaScriptObject result) {
-                  if (screen.isCurrentView()) {
-                    Gerrit.display(PageLinks.toChange(screen.getProject(), changeId));
-                  }
-                }
-              });
-    }
-  }
-
-  private static void onRemoveVote(NativeEvent event) {
-    Integer user = getDataId(event);
-    String vote = getVoteId(event);
-    if (user != null && vote != null) {
-      final ChangeScreen screen = ChangeScreen.get(event);
-      final Change.Id changeId = screen.getPatchSetId().getParentKey();
-      ChangeApi.vote(screen.getProject().get(), changeId.get(), user, vote)
-          .delete(
-              new GerritCallback<JavaScriptObject>() {
-                @Override
-                public void onSuccess(JavaScriptObject result) {
-                  if (screen.isCurrentView()) {
-                    Gerrit.display(PageLinks.toChange(screen.getProject(), changeId));
-                  }
-                }
-              });
-    }
-  }
-
-  private static Integer getDataId(NativeEvent event) {
-    Element e = event.getEventTarget().cast();
-    while (e != null) {
-      String v = e.getAttribute(DATA_ID);
-      if (!v.isEmpty()) {
-        return Integer.parseInt(v);
-      }
-      e = e.getParentElement();
-    }
-    return null;
-  }
-
-  private static String getVoteId(NativeEvent event) {
-    Element e = event.getEventTarget().cast();
-    while (e != null) {
-      String v = e.getAttribute(DATA_VOTE);
-      if (!v.isEmpty()) {
-        return v;
-      }
-      e = e.getParentElement();
-    }
-    return null;
-  }
-
-  private ChangeScreen.Style style;
-
-  void init(ChangeScreen.Style style) {
-    this.style = style;
-  }
-
-  void set(ChangeInfo info) {
-    List<String> names =
-        info.labels()
-            .stream()
-            .sorted()
-            .collect(collectingAndThen(toList(), Collections::unmodifiableList));
-    Set<Integer> removable = info.removableReviewerIds();
-
-    resize(names.size(), 2);
-
-    for (int row = 0; row < names.size(); row++) {
-      String name = names.get(row);
-      LabelInfo label = info.label(name);
-      setText(row, 0, name);
-      if (label.all() != null) {
-        setWidget(row, 1, renderUsers(label, removable));
-      }
-      getCellFormatter().setStyleName(row, 0, style.labelName());
-      getCellFormatter().addStyleName(row, 0, getStyleForLabel(label));
-    }
-  }
-
-  private Widget renderUsers(LabelInfo label, Set<Integer> removable) {
-    Map<Integer, List<ApprovalInfo>> m = new HashMap<>(4);
-    int approved = 0;
-    int rejected = 0;
-
-    for (ApprovalInfo ai : Natives.asList(label.all())) {
-      if (ai.value() != 0) {
-        List<ApprovalInfo> l = m.get(Integer.valueOf(ai.value()));
-        if (l == null) {
-          l = new ArrayList<>(label.all().length());
-          m.put(Integer.valueOf(ai.value()), l);
-        }
-        l.add(ai);
-
-        if (isRejected(label, ai)) {
-          rejected = ai.value();
-        } else if (isApproved(label, ai)) {
-          approved = ai.value();
-        }
-      }
-    }
-
-    SafeHtmlBuilder html = new SafeHtmlBuilder();
-    for (Integer v : sort(m.keySet(), approved, rejected)) {
-      if (!html.isEmpty()) {
-        html.br();
-      }
-
-      String val = LabelValue.formatValue(v.shortValue());
-      html.openSpan();
-      html.setAttribute("title", label.valueText(val));
-      if (v.intValue() == approved) {
-        html.setStyleName(style.label_ok());
-      } else if (v.intValue() == rejected) {
-        html.setStyleName(style.label_reject());
-      }
-      html.append(val).append(" ");
-      html.append(formatUserList(style, m.get(v), removable, label.name(), null));
-      html.closeSpan();
-    }
-    return html.toBlockWidget();
-  }
-
-  private static List<Integer> sort(Set<Integer> keySet, int a, int b) {
-    List<Integer> r = keySet.stream().sorted().collect(toCollection(ArrayList::new));
-    if (keySet.contains(a)) {
-      r.remove(Integer.valueOf(a));
-      r.add(0, a);
-    } else if (keySet.contains(b)) {
-      r.remove(Integer.valueOf(b));
-      r.add(0, b);
-    }
-    return r;
-  }
-
-  private static boolean isApproved(LabelInfo label, ApprovalInfo ai) {
-    return label.approved() != null && label.approved()._accountId() == ai._accountId();
-  }
-
-  private static boolean isRejected(LabelInfo label, ApprovalInfo ai) {
-    return label.rejected() != null && label.rejected()._accountId() == ai._accountId();
-  }
-
-  private String getStyleForLabel(LabelInfo label) {
-    switch (label.status()) {
-      case OK:
-        return style.label_ok();
-      case NEED:
-        return style.label_need();
-      case REJECT:
-      case IMPOSSIBLE:
-        return style.label_reject();
-      default:
-      case MAY:
-        return style.label_may();
-    }
-  }
-
-  static SafeHtml formatUserList(
-      ChangeScreen.Style style,
-      Collection<? extends AccountInfo> in,
-      Set<Integer> removable,
-      String label,
-      Map<Integer, VotableInfo> votable) {
-    List<AccountInfo> users =
-        in.stream()
-            .sorted(
-                new Comparator<AccountInfo>() {
-                  @Override
-                  public int compare(AccountInfo a, AccountInfo b) {
-                    String as = name(a);
-                    String bs = name(b);
-                    if (as.isEmpty()) {
-                      return 1;
-                    } else if (bs.isEmpty()) {
-                      return -1;
-                    }
-                    return as.compareTo(bs);
-                  }
-
-                  private String name(AccountInfo a) {
-                    if (a.name() != null) {
-                      return a.name();
-                    } else if (a.email() != null) {
-                      return a.email();
-                    }
-                    return "";
-                  }
-                })
-            .collect(collectingAndThen(toList(), Collections::unmodifiableList));
-
-    SafeHtmlBuilder html = new SafeHtmlBuilder();
-    Iterator<? extends AccountInfo> itr = users.iterator();
-    while (itr.hasNext()) {
-      AccountInfo ai = itr.next();
-      AvatarInfo img = ai.avatar(AvatarInfo.DEFAULT_SIZE);
-      String name;
-      if (ai.name() != null) {
-        name = ai.name();
-      } else if (ai.email() != null) {
-        name = ai.email();
-      } else {
-        name = Integer.toString(ai._accountId());
-      }
-
-      String votableCategories = "";
-      if (votable != null) {
-        VotableInfo vi = votable.get(ai._accountId());
-        if (vi != null) {
-          Set<String> s = vi.votableLabels();
-          if (!s.isEmpty()) {
-            StringBuilder sb = new StringBuilder(Util.C.votable());
-            sb.append(" ");
-            for (Iterator<String> it = vi.votableLabels().iterator(); it.hasNext(); ) {
-              sb.append(it.next());
-              if (it.hasNext()) {
-                sb.append(", ");
-              }
-            }
-            votableCategories = sb.toString();
-          }
-        }
-      }
-      html.openSpan()
-          .setAttribute("role", "listitem")
-          .setAttribute(DATA_ID, ai._accountId())
-          .setAttribute("title", getTitle(ai, votableCategories))
-          .setStyleName(style.label_user());
-      if (label != null) {
-        html.setAttribute(DATA_VOTE, label);
-      }
-      if (img != null) {
-        html.openElement("img").setStyleName(style.avatar()).setAttribute("src", img.url());
-        if (img.width() > 0) {
-          html.setAttribute("width", img.width());
-        }
-        if (img.height() > 0) {
-          html.setAttribute("height", img.height());
-        }
-        html.closeSelf();
-      }
-      html.append(name);
-      if (removable.contains(ai._accountId())) {
-        html.openElement("button");
-        if (label != null) {
-          html.setAttribute("title", Util.M.removeVote(label))
-              .setAttribute("onclick", REMOVE_VOTE + "(event)");
-        } else {
-          html.setAttribute("title", Util.M.removeReviewer(name))
-              .setAttribute("onclick", REMOVE_REVIEWER + "(event)");
-        }
-        html.append("×").closeElement("button");
-      }
-      html.closeSpan();
-      if (itr.hasNext()) {
-        html.append(' ');
-      }
-    }
-    return html;
-  }
-
-  private static String getTitle(AccountInfo ai, String votableCategories) {
-    String title = ai.email() != null ? ai.email() : "";
-    if (!votableCategories.isEmpty()) {
-      if (!title.isEmpty()) {
-        title += " ";
-      }
-      title += votableCategories;
-    }
-    return title;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/LineComment.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/LineComment.java
deleted file mode 100644
index 5a0cc59..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/LineComment.java
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Dispatcher;
-import com.google.gerrit.client.api.ApiGlue;
-import com.google.gerrit.client.changes.CommentInfo;
-import com.google.gerrit.client.diff.DisplaySide;
-import com.google.gerrit.client.ui.CommentLinkProcessor;
-import com.google.gerrit.client.ui.InlineHyperlink;
-import com.google.gerrit.extensions.client.Side;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-
-class LineComment extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, LineComment> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  @UiField Element sideLoc;
-  @UiField Element psLoc;
-  @UiField Element psNum;
-  @UiField Element fileLoc;
-  @UiField Element lineLoc;
-  @UiField InlineHyperlink line;
-  @UiField Element message;
-
-  LineComment(
-      CommentLinkProcessor clp, Project.NameKey project, PatchSet.Id defaultPs, CommentInfo info) {
-    initWidget(uiBinder.createAndBindUi(this));
-
-    PatchSet.Id ps;
-    if (info.patchSet() != defaultPs.get()) {
-      ps = new PatchSet.Id(defaultPs.getParentKey(), info.patchSet());
-      psNum.setInnerText(Integer.toString(info.patchSet()));
-      sideLoc.removeFromParent();
-      sideLoc = null;
-    } else if (info.side() == Side.PARENT) {
-      ps = defaultPs;
-      psLoc.removeFromParent();
-      psLoc = null;
-      psNum = null;
-    } else {
-      ps = defaultPs;
-      sideLoc.removeFromParent();
-      sideLoc = null;
-      psLoc.removeFromParent();
-      psLoc = null;
-      psNum = null;
-    }
-
-    if (info.hasLine()) {
-      fileLoc.removeFromParent();
-      fileLoc = null;
-
-      line.setTargetHistoryToken(url(project, ps, info));
-      line.setText(Integer.toString(info.line()));
-
-    } else {
-      lineLoc.removeFromParent();
-      lineLoc = null;
-      line = null;
-    }
-
-    if (info.message() != null) {
-      message.setInnerSafeHtml(
-          clp.apply(new SafeHtmlBuilder().append(info.message().trim()).wikify()));
-      ApiGlue.fireEvent("comment", message);
-    }
-  }
-
-  private static String url(Project.NameKey project, PatchSet.Id ps, CommentInfo info) {
-    return Dispatcher.toPatch(
-        project,
-        null,
-        ps,
-        info.path(),
-        info.side() == Side.PARENT ? DisplaySide.A : DisplaySide.B,
-        info.line());
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/LineComment.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/LineComment.ui.xml
deleted file mode 100644
index f33ba51..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/LineComment.ui.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:c='urn:import:com.google.gerrit.client.ui'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-  <ui:style gss='false'>
-    .box {
-      position: relative;
-    }
-    .location {
-      position: absolute;
-      top: 0;
-      left: 0;
-      font-weight: bold;
-    }
-    .message {
-      margin-left: 135px;
-    }
-  </ui:style>
-
-  <g:HTMLPanel styleName='{style.box}'>
-    <div class='{style.location}'>
-      <span ui:field='sideLoc'><ui:msg>Base, </ui:msg></span>
-      <span ui:field='psLoc'><ui:msg>PS<span ui:field='psNum'/>, </ui:msg></span>
-      <span ui:field='fileLoc'><ui:msg>File Comment</ui:msg></span>
-      <span ui:field='lineLoc'><ui:msg>Line <c:InlineHyperlink ui:field='line'/>:</ui:msg></span>
-    </div>
-    <div class='{style.message}' ui:field='message'/>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/LocalComments.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/LocalComments.java
deleted file mode 100644
index d2f031a..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/LocalComments.java
+++ /dev/null
@@ -1,276 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.changes.CommentApi;
-import com.google.gerrit.client.changes.CommentInfo;
-import com.google.gerrit.client.diff.CommentRange;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.extensions.client.Side;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.storage.client.Storage;
-import com.google.gwt.user.client.Cookies;
-import java.util.ArrayList;
-import java.util.Collection;
-
-public class LocalComments {
-  @Nullable private final Project.NameKey project;
-  private final Change.Id changeId;
-  private final PatchSet.Id psId;
-  private final StorageBackend storage;
-
-  private static class InlineComment {
-    @Nullable final Project.NameKey project;
-    final PatchSet.Id psId;
-    final CommentInfo commentInfo;
-
-    InlineComment(@Nullable Project.NameKey project, PatchSet.Id psId, CommentInfo commentInfo) {
-      this.project = project;
-      this.psId = psId;
-      this.commentInfo = commentInfo;
-    }
-  }
-
-  private static class StorageBackend {
-    private final Storage storageBackend;
-
-    StorageBackend() {
-      storageBackend =
-          (Storage.isLocalStorageSupported())
-              ? Storage.getLocalStorageIfSupported()
-              : Storage.getSessionStorageIfSupported();
-    }
-
-    String getItem(String key) {
-      if (storageBackend == null) {
-        return Cookies.getCookie(key);
-      }
-      return storageBackend.getItem(key);
-    }
-
-    void setItem(String key, String value) {
-      if (storageBackend == null) {
-        Cookies.setCookie(key, value);
-        return;
-      }
-      storageBackend.setItem(key, value);
-    }
-
-    void removeItem(String key) {
-      if (storageBackend == null) {
-        Cookies.removeCookie(key);
-        return;
-      }
-      storageBackend.removeItem(key);
-    }
-
-    Collection<String> getKeys() {
-      if (storageBackend == null) {
-        return Cookies.getCookieNames();
-      }
-      ArrayList<String> result = new ArrayList<>(storageBackend.getLength());
-      for (int i = 0; i < storageBackend.getLength(); i++) {
-        result.add(storageBackend.key(i));
-      }
-      return result;
-    }
-  }
-
-  public LocalComments(@Nullable Project.NameKey project, Change.Id changeId) {
-    this.project = project;
-    this.changeId = changeId;
-    this.psId = null;
-    this.storage = new StorageBackend();
-  }
-
-  public LocalComments(@Nullable Project.NameKey project, PatchSet.Id psId) {
-    this.project = project;
-    this.changeId = psId.getParentKey();
-    this.psId = psId;
-    this.storage = new StorageBackend();
-  }
-
-  public String getReplyComment() {
-    String comment = storage.getItem(getReplyCommentName());
-    storage.removeItem(getReplyCommentName());
-    return comment;
-  }
-
-  public void setReplyComment(String comment) {
-    storage.setItem(getReplyCommentName(), comment.trim());
-  }
-
-  public boolean hasReplyComment() {
-    return storage.getKeys().contains(getReplyCommentName());
-  }
-
-  public void removeReplyComment() {
-    if (hasReplyComment()) {
-      storage.removeItem(getReplyCommentName());
-    }
-  }
-
-  private String getReplyCommentName() {
-    return "savedReplyComment~" + PageLinks.toChangeId(project, changeId);
-  }
-
-  public static void saveInlineComments() {
-    final StorageBackend storage = new StorageBackend();
-    for (String cookie : storage.getKeys()) {
-      if (isInlineComment(cookie)) {
-        InlineComment input = getInlineComment(cookie);
-        if (input.commentInfo.id() == null) {
-          CommentApi.createDraft(
-              Project.NameKey.asStringOrNull(input.project),
-              input.psId,
-              input.commentInfo,
-              new GerritCallback<CommentInfo>() {
-                @Override
-                public void onSuccess(CommentInfo result) {
-                  storage.removeItem(cookie);
-                }
-              });
-        } else {
-          CommentApi.updateDraft(
-              Project.NameKey.asStringOrNull(input.project),
-              input.psId,
-              input.commentInfo.id(),
-              input.commentInfo,
-              new GerritCallback<CommentInfo>() {
-                @Override
-                public void onSuccess(CommentInfo result) {
-                  storage.removeItem(cookie);
-                }
-
-                @Override
-                public void onFailure(Throwable caught) {
-                  if (RestApi.isNotFound(caught)) {
-                    // the draft comment, that was supposed to be updated,
-                    // was deleted in the meantime
-                    storage.removeItem(cookie);
-                  } else {
-                    super.onFailure(caught);
-                  }
-                }
-              });
-        }
-      }
-    }
-  }
-
-  public void setInlineComment(CommentInfo comment) {
-    String name = getInlineCommentName(comment);
-    if (name == null) {
-      // Failed to get the store key -- so we can't continue.
-      return;
-    }
-    storage.setItem(name, comment.message().trim());
-  }
-
-  public boolean hasInlineComments() {
-    for (String cookie : storage.getKeys()) {
-      if (isInlineComment(cookie)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  private static boolean isInlineComment(String key) {
-    return key.startsWith("patchCommentEdit~")
-        || key.startsWith("patchReply~")
-        || key.startsWith("patchComment~");
-  }
-
-  private static InlineComment getInlineComment(String key) {
-    String path;
-    Side side;
-    int line;
-    CommentRange range;
-    StorageBackend storage = new StorageBackend();
-
-    String[] elements = key.split("~");
-    int offset = 1;
-    if (key.startsWith("patchReply~") || key.startsWith("patchCommentEdit~")) {
-      offset = 2;
-    }
-    ProjectChangeId id = ProjectChangeId.create(elements[offset + 0]);
-    PatchSet.Id psId = new PatchSet.Id(id.getChangeId(), Integer.parseInt(elements[offset + 1]));
-    path = atob(elements[offset + 2]);
-    side = (Side.PARENT.toString().equals(elements[offset + 3])) ? Side.PARENT : Side.REVISION;
-    range = null;
-    if (elements[offset + 4].startsWith("R")) {
-      String rangeStart = elements[offset + 4].substring(1);
-      String rangeEnd = elements[offset + 5];
-      String[] split = rangeStart.split(",");
-      int sl = Integer.parseInt(split[0]);
-      int sc = Integer.parseInt(split[1]);
-      split = rangeEnd.split(",");
-      int el = Integer.parseInt(split[0]);
-      int ec = Integer.parseInt(split[1]);
-      range = CommentRange.create(sl, sc, el, ec);
-      line = sl;
-    } else {
-      line = Integer.parseInt(elements[offset + 4]);
-    }
-    CommentInfo info = CommentInfo.create(path, side, line, range, false);
-    info.message(storage.getItem(key));
-    if (key.startsWith("patchReply~")) {
-      info.inReplyTo(elements[1]);
-    } else if (key.startsWith("patchCommentEdit~")) {
-      info.id(elements[1]);
-    }
-    InlineComment inlineComment = new InlineComment(id.getProject(), psId, info);
-    return inlineComment;
-  }
-
-  private String getInlineCommentName(CommentInfo comment) {
-    if (psId == null) {
-      return null;
-    }
-    String result = "patchComment~";
-    if (comment.id() != null) {
-      result = "patchCommentEdit~" + comment.id() + "~";
-    } else if (comment.inReplyTo() != null) {
-      result = "patchReply~" + comment.inReplyTo() + "~";
-    }
-
-    result += PageLinks.toChangeId(project, changeId);
-    result += "~" + psId.getId() + "~" + btoa(comment.path()) + "~" + comment.side() + "~";
-    if (comment.hasRange()) {
-      result +=
-          "R"
-              + comment.range().startLine()
-              + ","
-              + comment.range().startCharacter()
-              + "~"
-              + comment.range().endLine()
-              + ","
-              + comment.range().endCharacter();
-    } else {
-      result += comment.line();
-    }
-    return result;
-  }
-
-  private static native String btoa(String a) /*-{ return btoa(a); }-*/;
-
-  private static native String atob(String b) /*-{ return atob(b); }-*/;
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Message.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Message.java
deleted file mode 100644
index cadaf97..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Message.java
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.AvatarImage;
-import com.google.gerrit.client.FormatUtil;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.api.ApiGlue;
-import com.google.gerrit.client.changes.CommentInfo;
-import com.google.gerrit.client.changes.Util;
-import com.google.gerrit.client.info.ChangeInfo.MessageInfo;
-import com.google.gerrit.client.ui.CommentLinkProcessor;
-import com.google.gerrit.reviewdb.client.Patch;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.Style.Visibility;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
-class Message extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, Message> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  interface Style extends CssResource {
-    String closed();
-  }
-
-  @UiField Style style;
-  @UiField HTMLPanel header;
-  @UiField Element name;
-  @UiField Element summary;
-  @UiField Element date;
-  @UiField Button reply;
-  @UiField Element message;
-  @UiField FlowPanel comments;
-
-  private final History history;
-  private final MessageInfo info;
-  private List<CommentInfo> commentList;
-  private boolean autoOpen;
-
-  @UiField(provided = true)
-  AvatarImage avatar;
-
-  Message(History parent, MessageInfo info) {
-    if (info.author() != null) {
-      avatar = new AvatarImage(info.author());
-      avatar.setSize("", "");
-    } else {
-      avatar = new AvatarImage();
-    }
-
-    initWidget(uiBinder.createAndBindUi(this));
-    header.addDomHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            setOpen(!isOpen());
-          }
-        },
-        ClickEvent.getType());
-
-    this.history = parent;
-    this.info = info;
-
-    setName(false);
-    date.setInnerText(FormatUtil.shortFormatDayTime(info.date()));
-    if (info.message() != null) {
-      String msg = info.message().trim();
-      summary.setInnerText(msg);
-      message.setInnerSafeHtml(
-          history.getCommentLinkProcessor().apply(new SafeHtmlBuilder().append(msg).wikify()));
-      ApiGlue.fireEvent("comment", message);
-    } else {
-      reply.getElement().getStyle().setVisibility(Visibility.HIDDEN);
-    }
-  }
-
-  @UiHandler("reply")
-  void onReply(ClickEvent e) {
-    e.stopPropagation();
-
-    if (Gerrit.isSignedIn()) {
-      history.replyTo(info);
-    } else {
-      Gerrit.doSignIn(com.google.gwt.user.client.History.getToken());
-    }
-  }
-
-  MessageInfo getMessageInfo() {
-    return info;
-  }
-
-  private boolean isOpen() {
-    return UIObject.isVisible(message);
-  }
-
-  void setOpen(boolean open) {
-    if (open && info._revisionNumber() > 0 && !commentList.isEmpty()) {
-      renderComments(commentList);
-      commentList = Collections.emptyList();
-    }
-    setName(open);
-
-    UIObject.setVisible(summary, !open);
-    UIObject.setVisible(message, open);
-    comments.setVisible(open && comments.getWidgetCount() > 0);
-    if (open) {
-      removeStyleName(style.closed());
-    } else {
-      addStyleName(style.closed());
-    }
-  }
-
-  private void setName(boolean open) {
-    name.setInnerText(
-        open ? authorName(info) : com.google.gerrit.common.FormatUtil.elide(authorName(info), 20));
-  }
-
-  void autoOpen() {
-    if (commentList == null) {
-      autoOpen = true;
-    } else if (!commentList.isEmpty()) {
-      setOpen(true);
-    }
-  }
-
-  void addComments(List<CommentInfo> list) {
-    if (isOpen()) {
-      renderComments(list);
-      comments.setVisible(comments.getWidgetCount() > 0);
-      commentList = Collections.emptyList();
-    } else {
-      commentList = list;
-      if (autoOpen && !commentList.isEmpty()) {
-        setOpen(true);
-      }
-    }
-  }
-
-  private void renderComments(List<CommentInfo> list) {
-    CommentLinkProcessor clp = history.getCommentLinkProcessor();
-    PatchSet.Id ps = new PatchSet.Id(history.getChangeId(), info._revisionNumber());
-    TreeMap<String, List<CommentInfo>> m = byPath(list);
-    List<CommentInfo> l = m.remove(Patch.COMMIT_MSG);
-    if (l != null) {
-      comments.add(new FileComments(clp, history.getProject(), ps, Util.C.commitMessage(), l));
-    }
-    l = m.remove(Patch.MERGE_LIST);
-    if (l != null) {
-      comments.add(new FileComments(clp, history.getProject(), ps, Util.C.mergeList(), l));
-    }
-    for (Map.Entry<String, List<CommentInfo>> e : m.entrySet()) {
-      comments.add(new FileComments(clp, history.getProject(), ps, e.getKey(), e.getValue()));
-    }
-  }
-
-  private static TreeMap<String, List<CommentInfo>> byPath(List<CommentInfo> list) {
-    TreeMap<String, List<CommentInfo>> m = new TreeMap<>();
-    for (CommentInfo c : list) {
-      List<CommentInfo> l = m.get(c.path());
-      if (l == null) {
-        l = new ArrayList<>();
-        m.put(c.path(), l);
-      }
-      l.add(c);
-    }
-    return m;
-  }
-
-  static String authorName(MessageInfo info) {
-    if (info.author() != null) {
-      if (info.author().name() != null) {
-        return info.author().name();
-      }
-      return Gerrit.info().user().anonymousCowardName();
-    }
-    return Util.C.messageNoAuthor();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Message.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Message.ui.xml
deleted file mode 100644
index e362c07..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Message.ui.xml
+++ /dev/null
@@ -1,136 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:c='urn:import:com.google.gerrit.client'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-  <ui:style gss='false' type='com.google.gerrit.client.change.Message.Style'>
-    .messageBox {
-      position: relative;
-      width: 1168px;
-      padding: 2px 0 2px 0;
-      border-left: 1px solid #e3e9ff;
-      border-right: 1px solid #e3e9ff;
-      border-bottom: 1px solid #e3e9ff;
-      -webkit-border-bottom-left-radius: 8px;
-      -webkit-border-bottom-right-radius: 8px;
-    }
-
-    .header {
-      cursor: pointer;
-    }
-
-    .avatar {
-      position: absolute;
-      width: 26px;
-      height: 26px;
-    }
-    .closed .avatar {
-      position: absolute;
-      top: 0;
-      left: -1px;
-      width: 20px;
-      height: 20px;
-    }
-
-    .contents {
-      margin-left: 28px;
-      position: relative;
-    }
-
-    .contents p,
-    .contents blockquote {
-      -webkit-margin-before: 0;
-      -webkit-margin-after: 0.3em;
-       white-space: pre-wrap;
-    }
-
-    .name {
-      white-space: nowrap;
-      font-weight: bold;
-    }
-    .closed .name {
-      width: 150px;
-      overflow: hidden;
-      font-weight: normal;
-    }
-
-    .summary {
-      color: #777;
-      position: absolute;
-      top: 0;
-      left: 150px;
-      width: 880px;
-      overflow: hidden;
-      text-overflow: ellipsis;
-      white-space: nowrap;
-    }
-
-    .date {
-      white-space: nowrap;
-      position: absolute;
-      top: 0;
-      right: 18px;
-    }
-
-    .reply {
-      position: absolute;
-      top: 0;
-      right: 1px;
-      cursor: pointer;
-      outline: none;
-      border: none;
-      background: transparent;
-      margin: 0;
-      padding: 0;
-      line-height: 15px;
-      font-family: Arial Unicode MS, sans-serif;
-      font-size: 18px;
-    }
-    .closed .reply {
-      visibility: hidden;
-    }
-    .comment {
-    }
-  </ui:style>
-
-  <g:HTMLPanel
-      styleName='{style.messageBox}'
-      addStyleNames='{style.closed}'>
-    <c:AvatarImage ui:field='avatar' styleName='{style.avatar}'/>
-    <div class='{style.contents}'>
-      <g:HTMLPanel ui:field='header' styleName='{style.header}'>
-        <div class='{style.name}' ui:field='name'/>
-        <div ui:field='summary' class='{style.summary}'/>
-        <div class='{style.date}' ui:field='date'/>
-        <g:Button styleName='{style.reply}'
-            ui:field='reply'
-            title='Reply to this message'>
-          <ui:attribute name='title'/>
-          <div>&#x21a9;</div>
-        </g:Button>
-      </g:HTMLPanel>
-      <div style='overflow: auto'>
-        <div ui:field='message'
-            aria-hidden='true'
-            style='display: NONE'
-            styleName='{style.comment}'/>
-        <g:FlowPanel ui:field='comments' visible='false'/>
-      </div>
-    </div>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/MoveAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/MoveAction.java
deleted file mode 100644
index e3e9525..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/MoveAction.java
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (C) 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.changes.Util;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.ui.MoveDialog;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.PopupPanel;
-
-class MoveAction {
-  static void call(Button b, ChangeInfo info, Project.NameKey project) {
-    b.setEnabled(false);
-    new MoveDialog(project) {
-      {
-        sendButton.setText(Util.C.moveChangeSend());
-      }
-
-      @Override
-      public void onSend() {
-        ChangeApi.move(
-            info.project(),
-            info.legacyId().get(),
-            getDestinationBranch(),
-            getMessageText(),
-            new GerritCallback<ChangeInfo>() {
-              @Override
-              public void onSuccess(ChangeInfo result) {
-                sent = true;
-                hide();
-                Gerrit.display(PageLinks.toChange(project, result.legacyId()));
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {
-                enableButtons(true);
-                super.onFailure(caught);
-              }
-            });
-      }
-
-      @Override
-      public void onClose(CloseEvent<PopupPanel> event) {
-        super.onClose(event);
-        b.setEnabled(true);
-      }
-    }.center();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PatchSetsAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PatchSetsAction.java
deleted file mode 100644
index faf2516..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PatchSetsAction.java
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.info.ChangeInfo.EditInfo;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwt.user.client.ui.Widget;
-
-class PatchSetsAction extends RightSidePopdownAction {
-  private final PatchSetsBox revisionBox;
-
-  PatchSetsAction(
-      Project.NameKey project,
-      Change.Id changeId,
-      String revision,
-      EditInfo edit,
-      ChangeScreen.Style style,
-      UIObject relativeTo,
-      Widget downloadButton) {
-    super(style, relativeTo, downloadButton);
-    this.revisionBox = new PatchSetsBox(project, changeId, revision, edit);
-  }
-
-  @Override
-  Widget getWidget() {
-    return revisionBox;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PatchSetsBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PatchSetsBox.java
deleted file mode 100644
index 35cab4e..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PatchSetsBox.java
+++ /dev/null
@@ -1,233 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.FormatUtil;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.changes.ChangeList;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.ChangeInfo.CommitInfo;
-import com.google.gerrit.client.info.ChangeInfo.EditInfo;
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.client.ui.FancyFlexTableImpl;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.extensions.client.ListChangesOption;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.NativeEvent;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.EventListener;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlexTable;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.user.client.ui.impl.HyperlinkImpl;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-import java.util.Collections;
-import java.util.EnumSet;
-
-class PatchSetsBox extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, PatchSetsBox> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  private static final String OPEN;
-  private static final HyperlinkImpl link = GWT.create(HyperlinkImpl.class);
-
-  static {
-    OPEN = DOM.createUniqueId().replace('-', '_');
-    init(OPEN);
-  }
-
-  private static native void init(String o) /*-{
-    $wnd[o] = $entry(function(e,i) {
-      return @com.google.gerrit.client.change.PatchSetsBox::onOpen(Lcom/google/gwt/dom/client/NativeEvent;I)(e,i);
-    });
-  }-*/;
-
-  private static boolean onOpen(NativeEvent e, int idx) {
-    if (link.handleAsClick(e.<Event>cast())) {
-      PatchSetsBox t = getRevisionBox(e);
-      if (t != null) {
-        t.onOpenRow(idx);
-        e.preventDefault();
-        return false;
-      }
-    }
-    return true;
-  }
-
-  private static PatchSetsBox getRevisionBox(NativeEvent event) {
-    Element e = event.getEventTarget().cast();
-    for (e = DOM.getParent(e); e != null; e = DOM.getParent(e)) {
-      EventListener l = DOM.getEventListener(e);
-      if (l instanceof PatchSetsBox) {
-        return (PatchSetsBox) l;
-      }
-    }
-    return null;
-  }
-
-  interface Style extends CssResource {
-    String current();
-
-    String legacy_id();
-
-    String commit();
-
-    String draft_comment();
-  }
-
-  private final Change.Id changeId;
-  private final Project.NameKey project;
-  private final String revision;
-  private final EditInfo edit;
-  private boolean loaded;
-  private JsArray<RevisionInfo> revisions;
-
-  @UiField FlexTable table;
-  @UiField Style style;
-
-  PatchSetsBox(Project.NameKey project, Change.Id changeId, String revision, EditInfo edit) {
-    this.project = project;
-    this.changeId = changeId;
-    this.revision = revision;
-    this.edit = edit;
-    initWidget(uiBinder.createAndBindUi(this));
-  }
-
-  @Override
-  protected void onLoad() {
-    if (!loaded) {
-      RestApi call = ChangeApi.detail(project.get(), changeId.get());
-      ChangeList.addOptions(
-          call, EnumSet.of(ListChangesOption.ALL_COMMITS, ListChangesOption.ALL_REVISIONS));
-      call.get(
-          new AsyncCallback<ChangeInfo>() {
-            @Override
-            public void onSuccess(ChangeInfo result) {
-              if (edit != null) {
-                edit.setName(edit.commit().commit());
-                result.revisions().put(edit.name(), RevisionInfo.fromEdit(edit));
-              }
-              render(result.revisions());
-              loaded = true;
-            }
-
-            @Override
-            public void onFailure(Throwable caught) {}
-          });
-    }
-  }
-
-  private void onOpenRow(int idx) {
-    closeParent();
-    Gerrit.display(url(revisions.get(idx)));
-  }
-
-  private void render(NativeMap<RevisionInfo> map) {
-    map.copyKeysIntoChildren("name");
-
-    revisions = map.values();
-    RevisionInfo.sortRevisionInfoByNumber(revisions);
-    Collections.reverse(Natives.asList(revisions));
-
-    SafeHtmlBuilder sb = new SafeHtmlBuilder();
-    header(sb);
-    for (int i = 0; i < revisions.length(); i++) {
-      revision(sb, i, revisions.get(i));
-    }
-
-    GWT.<FancyFlexTableImpl>create(FancyFlexTableImpl.class).resetHtml(table, sb);
-  }
-
-  private void header(SafeHtmlBuilder sb) {
-    sb.openTr()
-        .openTh()
-        .setStyleName(style.legacy_id())
-        .append(Resources.C.patchSet())
-        .closeTh()
-        .openTh()
-        .append(Resources.C.commit())
-        .closeTh()
-        .openTh()
-        .append(Resources.C.date())
-        .closeTh()
-        .openTh()
-        .append(Resources.C.author())
-        .closeTh()
-        .closeTr();
-  }
-
-  private void revision(SafeHtmlBuilder sb, int index, RevisionInfo r) {
-    CommitInfo c = r.commit();
-    sb.openTr();
-    if (revision.equals(r.name())) {
-      sb.setStyleName(style.current());
-    }
-
-    sb.openTd().setStyleName(style.legacy_id());
-    sb.append(r.id());
-    sb.closeTd();
-
-    sb.openTd()
-        .setStyleName(style.commit())
-        .openAnchor()
-        .setAttribute("href", "#" + url(r))
-        .setAttribute("onclick", OPEN + "(event," + index + ")")
-        .append(r.name().substring(0, 10))
-        .closeAnchor()
-        .closeTd();
-
-    sb.openTd().append(FormatUtil.shortFormatDayTime(c.committer().date())).closeTd();
-
-    String an = c.author() != null ? c.author().name() : "";
-    String cn = c.committer() != null ? c.committer().name() : "";
-    sb.openTd();
-    sb.append(an);
-    if (!"".equals(an) && !"".equals(cn) && !an.equals(cn)) {
-      sb.append(" / ").append(cn);
-    }
-    sb.closeTd();
-
-    sb.closeTr();
-  }
-
-  private String url(RevisionInfo r) {
-    return PageLinks.toChange(project, changeId, r.id());
-  }
-
-  private void closeParent() {
-    for (Widget w = getParent(); w != null; w = w.getParent()) {
-      if (w instanceof PopupPanel) {
-        ((PopupPanel) w).hide(true);
-        break;
-      }
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PatchSetsBox.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PatchSetsBox.ui.xml
deleted file mode 100644
index 7537aa4..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PatchSetsBox.ui.xml
+++ /dev/null
@@ -1,76 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-  <ui:with field='res' type='com.google.gerrit.client.change.Resources'/>
-  <ui:style gss='false' type='com.google.gerrit.client.change.PatchSetsBox.Style'>
-    @eval selectionColor com.google.gerrit.client.Gerrit.getTheme().selectionColor;
-
-    .revisionBox {
-      min-width: 300px;
-      margin: 10px 0px 5px 5px;
-    }
-
-    .scroll {
-      min-width: 300px;
-      height: 200px;
-    }
-
-    .table {
-      border-spacing: 0;
-      width: 100%;
-    }
-
-    .table td, .table th {
-      padding-left: 5px;
-      padding-right: 5px;
-      border-right: 2px solid #ddd;
-      white-space: nowrap;
-    }
-
-    .table tr.current {
-      background-color: selectionColor;
-    }
-    .table tr.current a {
-      pointer-events: none;
-      color: #000;
-    }
-
-    .legacy_id {
-      min-width: 50px;
-      text-align: right;
-      font-weight: bold;
-    }
-
-    .commit {
-      font-family: monospace;
-    }
-
-    .draft_comment {
-      margin: 0 2px 0 0;
-      width: 16px;
-      height: 16px;
-      vertical-align: bottom;
-    }
-  </ui:style>
-  <g:HTMLPanel styleName='{style.revisionBox}'>
-    <g:ScrollPanel styleName='{style.scroll}'>
-      <g:FlexTable ui:field='table' styleName='{style.table}'/>
-    </g:ScrollPanel>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PathSuggestOracle.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PathSuggestOracle.java
deleted file mode 100644
index 7668f0f..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PathSuggestOracle.java
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtexpui.safehtml.client.HighlightSuggestOracle;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-class PathSuggestOracle extends HighlightSuggestOracle {
-
-  private final Project.NameKey project;
-  private final Change.Id changeId;
-  private final RevisionInfo revision;
-
-  PathSuggestOracle(Project.NameKey project, Change.Id changeId, RevisionInfo revision) {
-    this.project = project;
-    this.changeId = changeId;
-    this.revision = revision;
-  }
-
-  @Override
-  protected void onRequestSuggestions(Request req, Callback cb) {
-    RestApi api = ChangeApi.revision(project.get(), changeId.get(), revision.name()).view("files");
-    if (req.getQuery() != null) {
-      api.addParameter("q", req.getQuery() == null ? "" : req.getQuery());
-    }
-    api.background()
-        .get(
-            new AsyncCallback<JsArrayString>() {
-              @Override
-              public void onSuccess(JsArrayString result) {
-                List<Suggestion> r = new ArrayList<>();
-                for (String path : Natives.asList(result)) {
-                  r.add(new PathSuggestion(path));
-                }
-                cb.onSuggestionsReady(req, new Response(r));
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {
-                List<Suggestion> none = Collections.emptyList();
-                cb.onSuggestionsReady(req, new Response(none));
-              }
-            });
-  }
-
-  private static class PathSuggestion implements Suggestion {
-    private final String path;
-
-    PathSuggestion(String path) {
-      this.path = path;
-    }
-
-    @Override
-    public String getDisplayString() {
-      return path;
-    }
-
-    @Override
-    public String getReplacementString() {
-      return path;
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ProjectChangeId.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ProjectChangeId.java
deleted file mode 100644
index 684867b..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ProjectChangeId.java
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright (C) 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import java.util.Objects;
-
-/** Provides logic for parsing a numeric change id and project from a URL. */
-public class ProjectChangeId {
-
-  /** Parses a {@link ProjectChangeId} from it's string representation. */
-  public static ProjectChangeId create(String token) {
-    String mutableToken = token;
-    // Try parsing /c/project/+/numericChangeId where token is project/+/numericChangeId
-    int delimiter = mutableToken.indexOf(PageLinks.PROJECT_CHANGE_DELIMITER);
-    Project.NameKey project = null;
-    if (delimiter > 0) {
-      project = new Project.NameKey(token.substring(0, delimiter));
-      mutableToken =
-          mutableToken.substring(delimiter + PageLinks.PROJECT_CHANGE_DELIMITER.length());
-    }
-
-    // Try parsing /c/numericChangeId where token is numericChangeId
-    int s = mutableToken.indexOf('/');
-    if (s > 0) {
-      mutableToken = mutableToken.substring(0, s);
-    }
-    // Special case: project/+/1233,edit/
-    s = mutableToken.indexOf(",edit");
-    if (s > 0) {
-      mutableToken = mutableToken.substring(0, s);
-    }
-    Integer cId = tryParse(mutableToken);
-    if (cId != null) {
-      return new ProjectChangeId(project, new Change.Id(cId));
-    }
-
-    throw new IllegalArgumentException(token + " is not a valid change identifier");
-  }
-
-  @Nullable private final Project.NameKey project;
-  private final Change.Id changeId;
-
-  @VisibleForTesting
-  ProjectChangeId(@Nullable Project.NameKey project, Change.Id changeId) {
-    this.project = project;
-    this.changeId = changeId;
-  }
-
-  @Nullable
-  public Project.NameKey getProject() {
-    return project;
-  }
-
-  public Change.Id getChangeId() {
-    return changeId;
-  }
-
-  /**
-   * Calculate the length of the string representation of the change ID that was parsed from the
-   * token.
-   *
-   * @return the length of the {@link com.google.gerrit.reviewdb.client.Change.Id} if no project was
-   *     parsed from the token. The length of {@link
-   *     com.google.gerrit.reviewdb.client.Project.NameKey} + the delimiter + the length of {@link
-   *     com.google.gerrit.reviewdb.client.Change.Id} otherwise.
-   */
-  public int identifierLength() {
-    if (project == null) {
-      return String.valueOf(changeId).length();
-    }
-    return PageLinks.toChangeId(project, changeId).length();
-  }
-
-  @Override
-  public boolean equals(Object obj) {
-    if (obj instanceof ProjectChangeId) {
-      ProjectChangeId other = (ProjectChangeId) obj;
-      return Objects.equals(changeId, other.changeId) && Objects.equals(project, other.project);
-    }
-    return false;
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(changeId, project);
-  }
-
-  @Override
-  public String toString() {
-    return "ProjectChangeId.Result{changeId: " + changeId + ", project: " + project + "}";
-  }
-
-  private static Integer tryParse(String s) {
-    try {
-      return Integer.parseInt(s);
-    } catch (NumberFormatException e) {
-      return null;
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/QuickApprove.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/QuickApprove.java
deleted file mode 100644
index 56cc7a7..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/QuickApprove.java
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.changes.ReviewInput;
-import com.google.gerrit.client.changes.ReviewInput.DraftHandling;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.ChangeInfo.LabelInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-
-/** Applies a label with one mouse click. */
-class QuickApprove extends Button implements ClickHandler {
-  private Change.Id changeId;
-  private Project.NameKey project;
-  private String revision;
-  private ReviewInput input;
-  private ReplyAction replyAction;
-
-  QuickApprove() {
-    addClickHandler(this);
-  }
-
-  void set(ChangeInfo info, String commit, ReplyAction action) {
-    if (!info.hasPermittedLabels() || !info.status().isOpen()) {
-      // Quick approve needs at least one label on an open change.
-      setVisible(false);
-      return;
-    }
-    if (info.revision(commit).isEdit()) {
-      setVisible(false);
-      return;
-    }
-
-    String qName = null;
-    String qValueStr = null;
-    short qValue = 0;
-
-    int index = info.getMissingLabelIndex();
-    if (index != -1) {
-      LabelInfo label = Natives.asList(info.allLabels().values()).get(index);
-      JsArrayString values = info.permittedValues(label.name());
-      String s = values.get(values.length() - 1);
-      short v = LabelInfo.parseValue(s);
-      if (v > 0 && s.equals(label.maxValue())) {
-        qName = label.name();
-        qValueStr = s;
-        qValue = v;
-      }
-    }
-
-    if (qName != null) {
-      changeId = info.legacyId();
-      project = info.projectNameKey();
-      revision = commit;
-      input = ReviewInput.create();
-      input.drafts(DraftHandling.PUBLISH_ALL_REVISIONS);
-      input.label(qName, qValue);
-      replyAction = action;
-      setText(qName + qValueStr);
-      setVisible(true);
-    } else {
-      setVisible(false);
-    }
-  }
-
-  @Override
-  public void setText(String text) {
-    setHTML(new SafeHtmlBuilder().openDiv().append(text).closeDiv());
-  }
-
-  @Override
-  public void onClick(ClickEvent event) {
-    if (replyAction != null && replyAction.isVisible()) {
-      replyAction.quickApprove(input);
-    } else {
-      ChangeApi.revision(project.get(), changeId.get(), revision)
-          .view("review")
-          .post(
-              input,
-              new GerritCallback<ReviewInput>() {
-                @Override
-                public void onSuccess(ReviewInput result) {
-                  Gerrit.display(PageLinks.toChange(project, changeId));
-                }
-              });
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RebaseAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RebaseAction.java
deleted file mode 100644
index 0e3e835..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RebaseAction.java
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.ui.RebaseDialog;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.PopupPanel;
-
-class RebaseAction {
-  static void call(
-      final Button b,
-      final Project.NameKey project,
-      final String branch,
-      final Change.Id id,
-      final String revision,
-      final boolean enabled) {
-    b.setEnabled(false);
-
-    new RebaseDialog(project, branch, id, enabled) {
-      @Override
-      public void onSend() {
-        ChangeApi.rebase(
-            project.get(),
-            id.get(),
-            revision,
-            getBase(),
-            new GerritCallback<ChangeInfo>() {
-              @Override
-              public void onSuccess(ChangeInfo result) {
-                sent = true;
-                hide();
-                Gerrit.display(PageLinks.toChange(project, id));
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {
-                enableButtons(true);
-                super.onFailure(caught);
-              }
-            });
-      }
-
-      @Override
-      public void onClose(CloseEvent<PopupPanel> event) {
-        super.onClose(event);
-        b.setEnabled(true);
-      }
-    }.center();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChanges.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChanges.java
deleted file mode 100644
index 96bbe61..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChanges.java
+++ /dev/null
@@ -1,455 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import static com.google.gerrit.common.PageLinks.op;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.changes.ChangeList;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.ChangeInfo.CommitInfo;
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.extensions.client.ListChangesOption;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.event.logical.shared.SelectionEvent;
-import com.google.gwt.event.logical.shared.SelectionHandler;
-import com.google.gwt.resources.client.ClientBundle;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.TabBar;
-import com.google.gwt.user.client.ui.TabPanel;
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.List;
-
-public class RelatedChanges extends TabPanel {
-  static final RelatedChangesResources R = GWT.create(RelatedChangesResources.class);
-
-  interface RelatedChangesResources extends ClientBundle {
-    @Source("related_changes.css")
-    RelatedChangesCss css();
-  }
-
-  interface RelatedChangesCss extends CssResource {
-    String activeRow();
-
-    String current();
-
-    String gitweb();
-
-    String indirect();
-
-    String notCurrent();
-
-    String pointer();
-
-    String row();
-
-    String subject();
-
-    String strikedSubject();
-
-    String submittable();
-
-    String tabPanel();
-  }
-
-  enum Tab {
-    RELATED_CHANGES(Resources.C.relatedChanges(), Resources.C.relatedChangesTooltip()) {
-      @Override
-      String getTitle(int count) {
-        return Resources.M.relatedChanges(count);
-      }
-
-      @Override
-      String getTitle(String count) {
-        return Resources.M.relatedChanges(count);
-      }
-    },
-
-    SUBMITTED_TOGETHER(Resources.C.submittedTogether(), Resources.C.submittedTogether()) {
-      @Override
-      String getTitle(int count) {
-        return Resources.M.submittedTogether(count);
-      }
-
-      @Override
-      String getTitle(String count) {
-        return Resources.M.submittedTogether(count);
-      }
-    },
-
-    SAME_TOPIC(Resources.C.sameTopic(), Resources.C.sameTopicTooltip()) {
-      @Override
-      String getTitle(int count) {
-        return Resources.M.sameTopic(count);
-      }
-
-      @Override
-      String getTitle(String count) {
-        return Resources.M.sameTopic(count);
-      }
-    },
-
-    CONFLICTING_CHANGES(Resources.C.conflictingChanges(), Resources.C.conflictingChangesTooltip()) {
-      @Override
-      String getTitle(int count) {
-        return Resources.M.conflictingChanges(count);
-      }
-
-      @Override
-      String getTitle(String count) {
-        return Resources.M.conflictingChanges(count);
-      }
-    },
-
-    CHERRY_PICKS(Resources.C.cherryPicks(), Resources.C.cherryPicksTooltip()) {
-      @Override
-      String getTitle(int count) {
-        return Resources.M.cherryPicks(count);
-      }
-
-      @Override
-      String getTitle(String count) {
-        return Resources.M.cherryPicks(count);
-      }
-    };
-
-    final String defaultTitle;
-    final String tooltip;
-
-    abstract String getTitle(int count);
-
-    abstract String getTitle(String count);
-
-    Tab(String defaultTitle, String tooltip) {
-      this.defaultTitle = defaultTitle;
-      this.tooltip = tooltip;
-    }
-  }
-
-  private static Tab savedTab;
-
-  private final List<RelatedChangesTab> tabs;
-  private int maxHeightWithHeader;
-  private int selectedTab;
-  private int outstandingCallbacks;
-
-  RelatedChanges() {
-    tabs = new ArrayList<>(Tab.values().length);
-    selectedTab = -1;
-
-    setVisible(false);
-    addStyleName(R.css().tabPanel());
-    initTabBar();
-  }
-
-  private void initTabBar() {
-    TabBar tabBar = getTabBar();
-    tabBar.addSelectionHandler(
-        new SelectionHandler<Integer>() {
-          @Override
-          public void onSelection(SelectionEvent<Integer> event) {
-            if (selectedTab >= 0) {
-              tabs.get(selectedTab).registerKeys(false);
-            }
-            selectedTab = event.getSelectedItem();
-            tabs.get(selectedTab).registerKeys(true);
-          }
-        });
-
-    for (Tab tabInfo : Tab.values()) {
-      RelatedChangesTab panel = new RelatedChangesTab(tabInfo);
-      add(panel, tabInfo.defaultTitle);
-      tabs.add(panel);
-
-      TabBar.Tab tab = tabBar.getTab(tabInfo.ordinal());
-      tab.setWordWrap(false);
-      ((Composite) tab).setTitle(tabInfo.tooltip);
-
-      setTabEnabled(tabInfo, false);
-    }
-    getTab(Tab.RELATED_CHANGES).setShowIndirectAncestors(true);
-    getTab(Tab.CHERRY_PICKS).setShowBranches(true);
-    getTab(Tab.SAME_TOPIC).setShowBranches(true);
-    getTab(Tab.SAME_TOPIC).setShowProjects(true);
-    getTab(Tab.SAME_TOPIC).setShowSubmittable(true);
-    getTab(Tab.SUBMITTED_TOGETHER).setShowBranches(true);
-    getTab(Tab.SUBMITTED_TOGETHER).setShowProjects(true);
-    getTab(Tab.SUBMITTED_TOGETHER).setShowSubmittable(true);
-  }
-
-  void set(ChangeInfo info, String revision) {
-    if (info.status().isOpen()) {
-      setForOpenChange(info, revision);
-    }
-
-    ChangeApi.revision(info.project(), info.legacyId().get(), revision)
-        .view("related")
-        .get(
-            new TabCallback<RelatedInfo>(Tab.RELATED_CHANGES, info.project(), revision) {
-              @Override
-              public JsArray<ChangeAndCommit> convert(RelatedInfo result) {
-                return result.changes();
-              }
-            });
-
-    StringBuilder cherryPicksQuery = new StringBuilder();
-    cherryPicksQuery.append(op("project", info.project()));
-    cherryPicksQuery.append(" ").append(op("change", info.changeId()));
-    cherryPicksQuery.append(" ").append(op("-change", info.legacyId().get()));
-    cherryPicksQuery.append(" -is:abandoned");
-    ChangeList.query(
-        cherryPicksQuery.toString(),
-        EnumSet.of(ListChangesOption.CURRENT_REVISION, ListChangesOption.CURRENT_COMMIT),
-        new TabChangeListCallback(Tab.CHERRY_PICKS, info.project(), revision));
-
-    if (info.currentRevision() != null && info.currentRevision().equals(revision)) {
-      ChangeApi.change(info.project(), info.legacyId().get())
-          .view("submitted_together")
-          .addParameter("o", "CURRENT_COMMIT")
-          .get(new TabChangeListCallback(Tab.SUBMITTED_TOGETHER, info.project(), revision));
-    }
-
-    if (!Gerrit.info().change().isSubmitWholeTopicEnabled()
-        && info.topic() != null
-        && !"".equals(info.topic())) {
-      StringBuilder topicQuery = new StringBuilder();
-      topicQuery.append("status:open");
-      topicQuery.append(" ").append(op("topic", info.topic()));
-      ChangeList.query(
-          topicQuery.toString(),
-          EnumSet.of(
-              ListChangesOption.CURRENT_REVISION,
-              ListChangesOption.CURRENT_COMMIT,
-              ListChangesOption.DETAILED_LABELS,
-              ListChangesOption.LABELS),
-          new TabChangeListCallback(Tab.SAME_TOPIC, info.project(), revision));
-    }
-  }
-
-  private void setForOpenChange(ChangeInfo info, String revision) {
-    if (info.mergeable()) {
-      StringBuilder conflictsQuery = new StringBuilder();
-      conflictsQuery.append("status:open");
-      conflictsQuery.append(" is:mergeable");
-      conflictsQuery.append(" ").append(op("conflicts", info.legacyId().get()));
-      ChangeList.query(
-          conflictsQuery.toString(),
-          EnumSet.of(ListChangesOption.CURRENT_REVISION, ListChangesOption.CURRENT_COMMIT),
-          new TabChangeListCallback(Tab.CONFLICTING_CHANGES, info.project(), revision));
-    }
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    R.css().ensureInjected();
-  }
-
-  static void setSavedTab(Tab subject) {
-    savedTab = subject;
-  }
-
-  private RelatedChangesTab getTab(Tab tabInfo) {
-    return tabs.get(tabInfo.ordinal());
-  }
-
-  private void setTabTitle(Tab tabInfo, String title) {
-    getTabBar().setTabText(tabInfo.ordinal(), title);
-  }
-
-  private void setTabEnabled(Tab tabInfo, boolean enabled) {
-    getTabBar().setTabEnabled(tabInfo.ordinal(), enabled);
-  }
-
-  void setMaxHeight(int height) {
-    maxHeightWithHeader = height;
-    if (isVisible()) {
-      applyMaxHeight();
-    }
-  }
-
-  private void applyMaxHeight() {
-    int header = getTabBar().getOffsetHeight() + 2 /* padding */;
-    for (int i = 0; i < getTabBar().getTabCount(); i++) {
-      tabs.get(i).setMaxHeight(maxHeightWithHeader - header);
-    }
-  }
-
-  private abstract class TabCallback<T> implements AsyncCallback<T> {
-    private final Tab tabInfo;
-    private final String project;
-    private final String revision;
-
-    TabCallback(Tab tabInfo, String project, String revision) {
-      this.tabInfo = tabInfo;
-      this.project = project;
-      this.revision = revision;
-      outstandingCallbacks++;
-    }
-
-    protected abstract JsArray<ChangeAndCommit> convert(T result);
-
-    @Override
-    public void onSuccess(T result) {
-      if (isAttached()) {
-        JsArray<ChangeAndCommit> changes = convert(result);
-        if (changes.length() > 0) {
-          setTabTitle(tabInfo, tabInfo.getTitle(changes.length()));
-          getTab(tabInfo).setChanges(project, revision, changes);
-        }
-        onDone(changes.length() > 0);
-      }
-    }
-
-    @Override
-    public void onFailure(Throwable err) {
-      if (isAttached()) {
-        setTabTitle(tabInfo, tabInfo.getTitle(Resources.C.notAvailable()));
-        getTab(tabInfo).setError(err.getMessage());
-        onDone(true);
-      }
-    }
-
-    private void onDone(boolean enabled) {
-      setTabEnabled(tabInfo, enabled);
-      outstandingCallbacks--;
-      if (outstandingCallbacks == 0 || (enabled && tabInfo == Tab.RELATED_CHANGES)) {
-        outstandingCallbacks = 0; // Only execute this block once
-        for (int i = 0; i < getTabBar().getTabCount(); i++) {
-          if (getTabBar().isTabEnabled(i)) {
-            selectTab(i);
-            setVisible(true);
-            applyMaxHeight();
-            break;
-          }
-        }
-      }
-
-      if (tabInfo == savedTab && enabled) {
-        selectTab(savedTab.ordinal());
-      }
-    }
-  }
-
-  private class TabChangeListCallback extends TabCallback<ChangeList> {
-    TabChangeListCallback(Tab tabInfo, String project, String revision) {
-      super(tabInfo, project, revision);
-    }
-
-    @Override
-    protected JsArray<ChangeAndCommit> convert(ChangeList l) {
-      JsArray<ChangeAndCommit> arr = JavaScriptObject.createArray().cast();
-      for (ChangeInfo i : Natives.asList(l)) {
-        if (i.currentRevision() != null && i.revisions().containsKey(i.currentRevision())) {
-          RevisionInfo currentRevision = i.revision(i.currentRevision());
-          ChangeAndCommit c = ChangeAndCommit.create();
-          c.setId(i.id());
-          c.setCommit(currentRevision.commit());
-          c.setChangeNumber(i.legacyId().get());
-          c.setRevisionNumber(currentRevision._number());
-          c.setBranch(i.branch());
-          c.setProject(i.project());
-          c.setSubmittable(i.submittable() && i.mergeable());
-          c.setStatus(i.status().asChangeStatus().toString());
-          arr.push(c);
-        }
-      }
-      return arr;
-    }
-  }
-
-  public static class RelatedInfo extends JavaScriptObject {
-    public final native JsArray<ChangeAndCommit> changes() /*-{ return this.changes }-*/;
-
-    protected RelatedInfo() {}
-  }
-
-  public static class ChangeAndCommit extends JavaScriptObject {
-    static ChangeAndCommit create() {
-      return (ChangeAndCommit) createObject();
-    }
-
-    public final native String id() /*-{ return this.change_id }-*/;
-
-    public final native CommitInfo commit() /*-{ return this.commit }-*/;
-
-    final native String branch() /*-{ return this.branch }-*/;
-
-    final native String project() /*-{ return this.project }-*/;
-
-    final native boolean submittable() /*-{ return this._submittable ? true : false; }-*/;
-
-    final Change.Status status() {
-      String s = statusRaw();
-      return s != null ? Change.Status.valueOf(s) : null;
-    }
-
-    private native String statusRaw() /*-{ return this.status; }-*/;
-
-    final native void setId(String i) /*-{ if(i)this.change_id=i; }-*/;
-
-    final native void setCommit(CommitInfo c) /*-{ if(c)this.commit=c; }-*/;
-
-    final native void setBranch(String b) /*-{ if(b)this.branch=b; }-*/;
-
-    final native void setProject(String b) /*-{ if(b)this.project=b; }-*/;
-
-    public final Change.Id legacyId() {
-      return hasChangeNumber() ? new Change.Id(_changeNumber()) : null;
-    }
-
-    public final PatchSet.Id patchSetId() {
-      return hasChangeNumber() && hasRevisionNumber()
-          ? new PatchSet.Id(legacyId(), _revisionNumber())
-          : null;
-    }
-
-    public final native boolean hasChangeNumber()
-        /*-{ return this.hasOwnProperty('_change_number') }-*/ ;
-
-    final native boolean hasRevisionNumber()
-        /*-{ return this.hasOwnProperty('_revision_number') }-*/ ;
-
-    final native boolean hasCurrentRevisionNumber()
-        /*-{ return this.hasOwnProperty('_current_revision_number') }-*/ ;
-
-    final native int _changeNumber() /*-{ return this._change_number }-*/;
-
-    final native int _revisionNumber() /*-{ return this._revision_number }-*/;
-
-    final native int _currentRevisionNumber() /*-{ return this._current_revision_number }-*/;
-
-    final native void setChangeNumber(int n) /*-{ this._change_number=n; }-*/;
-
-    final native void setRevisionNumber(int n) /*-{ this._revision_number=n; }-*/;
-
-    final native void setCurrentRevisionNumber(int n) /*-{ this._current_revision_number=n; }-*/;
-
-    final native void setSubmittable(boolean s) /*-{ this._submittable=s; }-*/;
-
-    final native void setStatus(String s) /*-{ if(s)this.status=s; }-*/;
-
-    protected ChangeAndCommit() {}
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChangesTab.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChangesTab.java
deleted file mode 100644
index aa049ca..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChangesTab.java
+++ /dev/null
@@ -1,593 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.change.RelatedChanges.ChangeAndCommit;
-import com.google.gerrit.client.changes.Util;
-import com.google.gerrit.client.info.ChangeInfo.CommitInfo;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.RepeatingCommand;
-import com.google.gwt.dom.client.AnchorElement;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.NativeEvent;
-import com.google.gwt.dom.client.Node;
-import com.google.gwt.dom.client.NodeList;
-import com.google.gwt.dom.client.Style;
-import com.google.gwt.dom.client.Style.Visibility;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.DoubleClickEvent;
-import com.google.gwt.event.dom.client.DoubleClickHandler;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.ScrollEvent;
-import com.google.gwt.event.dom.client.ScrollHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.safehtml.shared.SafeHtml;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.AbstractImagePrototype;
-import com.google.gwt.user.client.ui.InlineLabel;
-import com.google.gwt.user.client.ui.IsWidget;
-import com.google.gwt.user.client.ui.ScrollPanel;
-import com.google.gwt.user.client.ui.SimplePanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.user.client.ui.impl.HyperlinkImpl;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-import com.google.gwtexpui.globalkey.client.KeyCommand;
-import com.google.gwtexpui.globalkey.client.KeyCommandSet;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-class RelatedChangesTab implements IsWidget {
-  private static final String OPEN = init(DOM.createUniqueId().replace('-', '_'));
-  private static final HyperlinkImpl LINK = GWT.create(HyperlinkImpl.class);
-  private static final SafeHtml POINTER_HTML =
-      AbstractImagePrototype.create(Gerrit.RESOURCES.arrowRight()).getSafeHtml();
-
-  private static native String init(String o) /*-{
-    $wnd[o] = $entry(@com.google.gerrit.client.change.RelatedChangesTab::onOpen(
-      Lcom/google/gwt/dom/client/NativeEvent;Lcom/google/gwt/dom/client/Element;));
-    return o + '(event,this)';
-  }-*/;
-
-  private static boolean onOpen(NativeEvent evt, Element e) {
-    if (LINK.handleAsClick(evt.<Event>cast())) {
-      Gerrit.display(e.getAttribute("href").substring(1));
-      evt.preventDefault();
-      return false;
-    }
-    return true;
-  }
-
-  private final SimplePanel panel;
-  private final RelatedChanges.Tab subject;
-
-  private boolean showBranches;
-  private boolean showProjects;
-  private boolean showSubmittable;
-  private boolean showIndirectAncestors;
-  private boolean registerKeys;
-  private int maxHeight;
-
-  private String project;
-  private NavigationList view;
-
-  RelatedChangesTab(RelatedChanges.Tab subject) {
-    panel = new SimplePanel();
-    this.subject = subject;
-  }
-
-  @Override
-  public Widget asWidget() {
-    return panel;
-  }
-
-  void setShowBranches(boolean showBranches) {
-    this.showBranches = showBranches;
-  }
-
-  void setShowProjects(boolean showProjects) {
-    this.showProjects = showProjects;
-  }
-
-  void setShowSubmittable(boolean submittable) {
-    this.showSubmittable = submittable;
-  }
-
-  void setShowIndirectAncestors(boolean showIndirectAncestors) {
-    this.showIndirectAncestors = showIndirectAncestors;
-  }
-
-  void setMaxHeight(int height) {
-    maxHeight = height;
-    if (view != null) {
-      view.setHeight(height + "px");
-      view.ensureRowMeasurements();
-      view.movePointerTo(view.selectedRow, true);
-    }
-  }
-
-  void registerKeys(boolean on) {
-    registerKeys = on;
-    if (view != null) {
-      view.setRegisterKeys(on);
-    }
-  }
-
-  void setError(String message) {
-    panel.setWidget(new InlineLabel(message));
-    view = null;
-    project = null;
-  }
-
-  void setChanges(String project, String revision, JsArray<ChangeAndCommit> changes) {
-    if (0 == changes.length()) {
-      setError(Resources.C.noChanges());
-      return;
-    }
-
-    this.project = project;
-    view = new NavigationList();
-    panel.setWidget(view);
-
-    DisplayCommand display = new DisplayCommand(revision, changes, view);
-    if (display.execute()) {
-      Scheduler.get().scheduleIncremental(display);
-    }
-  }
-
-  private final class DisplayCommand implements RepeatingCommand {
-    private final String revision;
-    private final JsArray<ChangeAndCommit> changes;
-    private final List<SafeHtml> rows;
-    private final Set<String> connected;
-    private final NavigationList navList;
-
-    private double start;
-    private int row;
-    private int connectedPos;
-    private int selected;
-
-    private DisplayCommand(
-        String revision, JsArray<ChangeAndCommit> changes, NavigationList navList) {
-      this.revision = revision;
-      this.changes = changes;
-      this.navList = navList;
-      rows = new ArrayList<>(changes.length());
-      connectedPos = changes.length() - 1;
-      connected =
-          showIndirectAncestors ? new HashSet<>(Math.max(changes.length() * 4 / 3, 16)) : null;
-    }
-
-    private boolean computeConnected() {
-      // Since TOPO sorted, when can walk the list in reverse and find all
-      // the connections.
-      if (!connected.contains(revision)) {
-        while (connectedPos >= 0) {
-          CommitInfo c = changes.get(connectedPos).commit();
-          connected.add(c.commit());
-          if (longRunning(--connectedPos)) {
-            return true;
-          }
-          if (c.commit().equals(revision)) {
-            break;
-          }
-        }
-      }
-      while (connectedPos >= 0) {
-        CommitInfo c = changes.get(connectedPos).commit();
-        for (int j = 0; j < c.parents().length(); j++) {
-          if (connected.contains(c.parents().get(j).commit())) {
-            connected.add(c.commit());
-            break;
-          }
-        }
-        if (longRunning(--connectedPos)) {
-          return true;
-        }
-      }
-      return false;
-    }
-
-    @Override
-    public boolean execute() {
-      if (navList != view || !panel.isAttached()) {
-        // If the user navigated away, we aren't in the DOM anymore.
-        // Don't continue to render.
-        return false;
-      }
-
-      start = System.currentTimeMillis();
-
-      if (connected != null && computeConnected()) {
-        return true;
-      }
-
-      while (row < changes.length()) {
-        ChangeAndCommit info = changes.get(row);
-        String commit = info.commit().commit();
-        rows.add(new RowSafeHtml(info, connected != null && !connected.contains(commit)));
-        if (revision.equals(commit)) {
-          selected = row;
-        }
-        if (longRunning(++row)) {
-          return true;
-        }
-      }
-
-      navList.rows = rows;
-      navList.ensureRowMeasurements();
-      navList.movePointerTo(selected, true);
-      return false;
-    }
-
-    private boolean longRunning(int i) {
-      return (i % 10) == 0 && System.currentTimeMillis() - start > 50;
-    }
-  }
-
-  @SuppressWarnings("serial")
-  private class RowSafeHtml implements SafeHtml {
-    private String html;
-    private ChangeAndCommit info;
-    private final boolean notConnected;
-
-    RowSafeHtml(ChangeAndCommit info, boolean notConnected) {
-      this.info = info;
-      this.notConnected = notConnected;
-    }
-
-    @Override
-    public String asString() {
-      if (html == null) {
-        SafeHtmlBuilder sb = new SafeHtmlBuilder();
-        renderRow(sb);
-        html = sb.asString();
-        info = null;
-      }
-      return html;
-    }
-
-    private void renderRow(SafeHtmlBuilder sb) {
-      sb.openDiv().setStyleName(RelatedChanges.R.css().row());
-
-      sb.openSpan().setStyleName(RelatedChanges.R.css().pointer());
-      sb.append(POINTER_HTML);
-      sb.closeSpan();
-
-      if (info.status() == Change.Status.ABANDONED) {
-        sb.openSpan().setStyleName(RelatedChanges.R.css().strikedSubject());
-      } else {
-        sb.openSpan().setStyleName(RelatedChanges.R.css().subject());
-      }
-      sb.setAttribute("data-branch", info.branch());
-      sb.setAttribute("data-project", info.project());
-      String url = url();
-      if (url != null) {
-        sb.openAnchor().setAttribute("href", url);
-        if (url.startsWith("#")) {
-          sb.setAttribute("onclick", OPEN);
-        }
-        sb.setAttribute("title", info.commit().subject());
-        if (showProjects) {
-          sb.append(info.project()).append(": ");
-        }
-        if (showBranches) {
-          sb.append(info.branch()).append(": ");
-        }
-        sb.append(info.commit().subject());
-        sb.closeAnchor();
-      } else {
-        sb.append(info.commit().subject());
-      }
-      sb.closeSpan();
-
-      sb.openSpan();
-      if (info.status() != null && !info.status().isOpen()) {
-        sb.setStyleName(RelatedChanges.R.css().gitweb());
-        sb.setAttribute("title", Util.toLongString(info.status()));
-        sb.append('\u25CF'); // Unicode 'BLACK CIRCLE'
-      } else if (notConnected) {
-        sb.setStyleName(RelatedChanges.R.css().indirect());
-        sb.setAttribute("title", Resources.C.indirectAncestor());
-        sb.append('~');
-      } else if (info.hasCurrentRevisionNumber()
-          && info.hasRevisionNumber()
-          && info._currentRevisionNumber() != info._revisionNumber()) {
-        sb.setStyleName(RelatedChanges.R.css().notCurrent());
-        sb.setAttribute("title", Util.C.notCurrent());
-        sb.append('\u25CF'); // Unicode 'BLACK CIRCLE'
-      } else if (showSubmittable && info.submittable()) {
-        sb.setStyleName(RelatedChanges.R.css().submittable());
-        sb.setAttribute("title", Util.C.submittable());
-        sb.append('\u2713'); // Unicode 'CHECK MARK'
-      } else {
-        sb.setStyleName(RelatedChanges.R.css().current());
-      }
-      sb.closeSpan();
-
-      sb.closeDiv();
-    }
-
-    private String url() {
-      if (info.hasChangeNumber() && info.hasRevisionNumber()) {
-        return "#" + PageLinks.toChange(new Project.NameKey(info.project()), info.patchSetId());
-      }
-      return null;
-    }
-  }
-
-  private class NavigationList extends ScrollPanel
-      implements ClickHandler, DoubleClickHandler, ScrollHandler {
-    private final KeyCommandSet keysNavigation;
-    private final Element body;
-    private final Element surrogate;
-    private final Node fragment = createDocumentFragment();
-
-    List<SafeHtml> rows;
-    private HandlerRegistration regNavigation;
-    private int selectedRow;
-    private int startRow;
-    private int rowHeight;
-    private int rowWidth;
-
-    NavigationList() {
-      addDomHandler(this, ClickEvent.getType());
-      addDomHandler(this, DoubleClickEvent.getType());
-      addScrollHandler(this);
-
-      keysNavigation = new KeyCommandSet(Resources.C.relatedChanges());
-      keysNavigation.add(
-          new KeyCommand(0, 'K', Resources.C.previousChange()) {
-            @Override
-            public void onKeyPress(KeyPressEvent event) {
-              movePointerTo(selectedRow - 1, true);
-            }
-          },
-          new KeyCommand(0, 'J', Resources.C.nextChange()) {
-            @Override
-            public void onKeyPress(KeyPressEvent event) {
-              movePointerTo(selectedRow + 1, true);
-            }
-          });
-      keysNavigation.add(
-          new KeyCommand(0, 'O', Resources.C.openChange()) {
-            @Override
-            public void onKeyPress(KeyPressEvent event) {
-              onOpenRow(getRow(selectedRow));
-            }
-          });
-
-      if (maxHeight > 0) {
-        setHeight(maxHeight + "px");
-      }
-
-      body = DOM.createDiv();
-      body.getStyle().setPosition(Style.Position.RELATIVE);
-      body.getStyle().setVisibility(Visibility.HIDDEN);
-      getContainerElement().appendChild(body);
-
-      surrogate = DOM.createDiv();
-      surrogate.getStyle().setVisibility(Visibility.HIDDEN);
-    }
-
-    private boolean ensureRowMeasurements() {
-      if (rowHeight == 0 && rows != null) {
-        surrogate.setInnerSafeHtml(rows.get(0));
-        getContainerElement().appendChild(surrogate);
-        rowHeight = surrogate.getOffsetHeight();
-        rowWidth = surrogate.getOffsetWidth();
-        getContainerElement().removeChild(surrogate);
-        getContainerElement().getStyle().setHeight(rowHeight * rows.size(), Style.Unit.PX);
-        return true;
-      }
-      return false;
-    }
-
-    public void movePointerTo(int row, boolean scroll) {
-      if (rows != null && 0 <= row && row < rows.size()) {
-        renderSelected(selectedRow, false);
-        selectedRow = row;
-
-        if (scroll && rowHeight != 0) {
-          // Position the selected row in the middle.
-          setVerticalScrollPosition(Math.max(rowHeight * selectedRow - maxHeight / 2, 0));
-          render();
-        }
-        renderSelected(selectedRow, true);
-      }
-    }
-
-    private void renderSelected(int row, boolean selected) {
-      Element e = getRow(row);
-      if (e != null) {
-        if (selected) {
-          e.addClassName(RelatedChanges.R.css().activeRow());
-        } else {
-          e.removeClassName(RelatedChanges.R.css().activeRow());
-        }
-      }
-    }
-
-    private void render() {
-      if (rows == null || rowHeight == 0) {
-        return;
-      }
-
-      int currStart = startRow;
-      int currEnd = startRow + body.getChildCount();
-
-      int vpos = getVerticalScrollPosition();
-      int start = Math.max(vpos / rowHeight - 5, 0);
-      int end = Math.min((vpos + maxHeight) / rowHeight + 5, rows.size());
-      if (currStart <= start && end <= currEnd) {
-        return; // All of the required nodes are already in the DOM.
-      }
-
-      if (end <= currStart) {
-        renderRange(start, end, true, true);
-      } else if (start < currStart) {
-        renderRange(start, currStart, false, true);
-      } else if (start >= currEnd) {
-        renderRange(start, end, true, false);
-      } else if (end > currEnd) {
-        renderRange(currEnd, end, false, false);
-      }
-
-      renderSelected(selectedRow, true);
-
-      if (currEnd == 0) {
-        // Account for the scroll bars
-        int width = body.getOffsetWidth();
-        if (rowWidth > width) {
-          int w = 2 * rowWidth - width;
-          setWidth(w + "px");
-        }
-        body.getStyle().clearVisibility();
-      }
-    }
-
-    private void renderRange(int start, int end, boolean removeAll, boolean insertFirst) {
-      SafeHtmlBuilder sb = new SafeHtmlBuilder();
-      for (int i = start; i < end; i++) {
-        sb.append(rows.get(i));
-      }
-
-      if (removeAll) {
-        body.setInnerSafeHtml(sb);
-      } else {
-        surrogate.setInnerSafeHtml(sb);
-        for (int cnt = surrogate.getChildCount(); cnt > 0; cnt--) {
-          fragment.appendChild(surrogate.getFirstChild());
-        }
-        if (insertFirst) {
-          body.insertFirst(fragment);
-        } else {
-          body.appendChild(fragment);
-        }
-      }
-
-      if (insertFirst || removeAll) {
-        startRow = start;
-        body.getStyle().setTop(start * rowHeight, Style.Unit.PX);
-      }
-    }
-
-    @Override
-    public void onClick(ClickEvent event) {
-      Element row = getRow(event.getNativeEvent().getEventTarget().<Element>cast());
-      if (row != null) {
-        movePointerTo(startRow + DOM.getChildIndex(body, row), false);
-        event.stopPropagation();
-      }
-      saveSelectedTab();
-    }
-
-    @Override
-    public void onDoubleClick(DoubleClickEvent event) {
-      Element row = getRow(event.getNativeEvent().getEventTarget().<Element>cast());
-      if (row != null) {
-        movePointerTo(startRow + DOM.getChildIndex(body, row), false);
-        onOpenRow(row);
-        event.stopPropagation();
-      }
-    }
-
-    @Override
-    public void onScroll(ScrollEvent event) {
-      render();
-    }
-
-    private Element getRow(Element e) {
-      for (Element prev = e; e != null; prev = e) {
-        if ((e = DOM.getParent(e)) == body) {
-          return prev;
-        }
-      }
-      return null;
-    }
-
-    private Element getRow(int row) {
-      if (startRow <= row && row < startRow + body.getChildCount()) {
-        return body.getChild(row - startRow).cast();
-      }
-      return null;
-    }
-
-    private void onOpenRow(Element row) {
-      // Find the first HREF of the anchor of the select row (if any)
-      if (row != null) {
-        NodeList<Element> nodes = row.getElementsByTagName(AnchorElement.TAG);
-        for (int i = 0; i < nodes.getLength(); i++) {
-          String url = nodes.getItem(i).getAttribute("href");
-          if (!url.isEmpty()) {
-            if (url.startsWith("#")) {
-              Gerrit.display(url.substring(1));
-            } else {
-              Window.Location.assign(url);
-            }
-            break;
-          }
-        }
-      }
-
-      saveSelectedTab();
-    }
-
-    private void saveSelectedTab() {
-      RelatedChanges.setSavedTab(subject);
-    }
-
-    @Override
-    protected void onLoad() {
-      super.onLoad();
-      setRegisterKeys(registerKeys);
-    }
-
-    @Override
-    protected void onUnload() {
-      setRegisterKeys(false);
-      super.onUnload();
-    }
-
-    public void setRegisterKeys(boolean on) {
-      if (on && isAttached()) {
-        if (regNavigation == null) {
-          regNavigation = GlobalKey.add(this, keysNavigation);
-        }
-        if (view.ensureRowMeasurements()) {
-          view.movePointerTo(view.selectedRow, true);
-        }
-      } else if (regNavigation != null) {
-        regNavigation.removeHandler();
-        regNavigation = null;
-      }
-    }
-  }
-
-  private static native Node createDocumentFragment() /*-{
-    return $doc.createDocumentFragment();
-  }-*/;
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RenameFileAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RenameFileAction.java
deleted file mode 100644
index 1e7063a..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RenameFileAction.java
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-
-class RenameFileAction {
-  private final Project.NameKey project;
-  private final Change.Id changeId;
-  private final RevisionInfo revision;
-  private final ChangeScreen.Style style;
-  private final Widget renameButton;
-
-  private RenameFileBox renameBox;
-  private PopupPanel popup;
-
-  RenameFileAction(
-      Project.NameKey project,
-      Change.Id changeId,
-      RevisionInfo revision,
-      ChangeScreen.Style style,
-      Widget renameButton) {
-    this.project = project;
-    this.changeId = changeId;
-    this.revision = revision;
-    this.style = style;
-    this.renameButton = renameButton;
-  }
-
-  void onRename() {
-    if (popup != null) {
-      popup.hide();
-      return;
-    }
-
-    if (renameBox == null) {
-      renameBox = new RenameFileBox(project, changeId, revision);
-    }
-    renameBox.clearPath();
-
-    final PopupPanel p = new PopupPanel(true);
-    p.setStyleName(style.replyBox());
-    p.addAutoHidePartner(renameButton.getElement());
-    p.addCloseHandler(
-        new CloseHandler<PopupPanel>() {
-          @Override
-          public void onClose(CloseEvent<PopupPanel> event) {
-            if (popup == p) {
-              popup = null;
-            }
-          }
-        });
-    p.add(renameBox);
-    p.showRelativeTo(renameButton);
-    GlobalKey.dialog(p);
-    renameBox.setFocus(true);
-    popup = p;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RenameFileBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RenameFileBox.java
deleted file mode 100644
index f288dbe..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RenameFileBox.java
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.VoidResult;
-import com.google.gerrit.client.changes.ChangeEditApi;
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.client.ui.RemoteSuggestBox;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.globalkey.client.NpTextBox;
-
-class RenameFileBox extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, RenameFileBox> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  private final Project.NameKey project;
-  private final Change.Id changeId;
-
-  @UiField Button rename;
-  @UiField Button cancel;
-
-  @UiField(provided = true)
-  RemoteSuggestBox path;
-
-  @UiField NpTextBox newPath;
-
-  RenameFileBox(Project.NameKey project, Change.Id changeId, RevisionInfo revision) {
-    this.project = project;
-    this.changeId = changeId;
-
-    path = new RemoteSuggestBox(new PathSuggestOracle(project, changeId, revision));
-    path.addCloseHandler(
-        new CloseHandler<RemoteSuggestBox>() {
-          @Override
-          public void onClose(CloseEvent<RemoteSuggestBox> event) {
-            hide();
-          }
-        });
-
-    initWidget(uiBinder.createAndBindUi(this));
-  }
-
-  void setFocus(boolean focus) {
-    path.setFocus(focus);
-  }
-
-  void clearPath() {
-    path.setText("");
-  }
-
-  @UiHandler("rename")
-  void onRename(@SuppressWarnings("unused") ClickEvent e) {
-    rename(path.getText(), newPath.getText());
-  }
-
-  private void rename(String path, String newPath) {
-    hide();
-    ChangeEditApi.rename(
-        project.get(),
-        changeId.get(),
-        path,
-        newPath,
-        new AsyncCallback<VoidResult>() {
-          @Override
-          public void onSuccess(VoidResult result) {
-            Gerrit.display(PageLinks.toChangeInEditMode(project, changeId));
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {}
-        });
-  }
-
-  @UiHandler("cancel")
-  void onCancel(@SuppressWarnings("unused") ClickEvent e) {
-    hide();
-  }
-
-  private void hide() {
-    for (Widget w = getParent(); w != null; w = w.getParent()) {
-      if (w instanceof PopupPanel) {
-        ((PopupPanel) w).hide();
-        break;
-      }
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RenameFileBox.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RenameFileBox.ui.xml
deleted file mode 100644
index 17e8797..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RenameFileBox.ui.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:c='urn:import:com.google.gwtexpui.globalkey.client'
-    xmlns:u='urn:import:com.google.gerrit.client.ui'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-  <ui:with field='res' type='com.google.gerrit.client.change.Resources'/>
-  <ui:style gss='false'>
-    .cancel { float: right; }
-  </ui:style>
-  <g:HTMLPanel>
-    <div class='{res.style.section}'>
-      <ui:msg>Old: <u:RemoteSuggestBox ui:field='path' visibleLength='86'/></ui:msg>
-    </div>
-    <div class='{res.style.section}'>
-      <ui:msg>New: <c:NpTextBox ui:field='newPath' visibleLength='86'/></ui:msg>
-    </div>
-    <div class='{res.style.section}'>
-      <g:Button ui:field='rename'
-          title='Rename file in the repository'
-          styleName='{res.style.button}'>
-        <ui:attribute name='title'/>
-        <div><ui:msg>Rename</ui:msg></div>
-      </g:Button>
-      <g:Button ui:field='cancel'
-          styleName='{res.style.button}'
-          addStyleNames='{style.cancel}'>
-          <div>Cancel</div>
-      </g:Button>
-    </div>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyAction.java
deleted file mode 100644
index ff09ff5..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyAction.java
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.changes.ReviewInput;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.ChangeInfo.LabelInfo;
-import com.google.gerrit.client.info.ChangeInfo.MessageInfo;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.ui.CommentLinkProcessor;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-
-class ReplyAction {
-  private final PatchSet.Id psId;
-  private final Project.NameKey project;
-  private final String revision;
-  private final boolean hasDraftComments;
-  private final ChangeScreen.Style style;
-  private final CommentLinkProcessor clp;
-  private final Widget replyButton;
-  private final Widget quickApproveButton;
-
-  private NativeMap<LabelInfo> allLabels;
-  private NativeMap<JsArrayString> permittedLabels;
-
-  private ReplyBox replyBox;
-  private PopupPanel popup;
-
-  ReplyAction(
-      ChangeInfo info,
-      String revision,
-      boolean hasDraftComments,
-      ChangeScreen.Style style,
-      CommentLinkProcessor clp,
-      Widget replyButton,
-      Widget quickApproveButton) {
-    this.psId = new PatchSet.Id(info.legacyId(), info.revisions().get(revision)._number());
-    this.project = info.projectNameKey();
-    this.revision = revision;
-    this.hasDraftComments = hasDraftComments;
-    this.style = style;
-    this.clp = clp;
-    this.replyButton = replyButton;
-    this.quickApproveButton = quickApproveButton;
-
-    boolean current = revision.equals(info.currentRevision());
-    allLabels = info.allLabels();
-    permittedLabels =
-        current && info.hasPermittedLabels()
-            ? info.permittedLabels()
-            : NativeMap.<JsArrayString>create();
-  }
-
-  boolean isVisible() {
-    return popup != null;
-  }
-
-  void quickApprove(ReviewInput input) {
-    replyBox.quickApprove(input);
-  }
-
-  void hide() {
-    if (popup != null) {
-      popup.hide();
-    }
-    return;
-  }
-
-  void onReply(MessageInfo msg) {
-    if (popup != null) {
-      popup.hide();
-      return;
-    }
-
-    if (replyBox == null) {
-      replyBox = new ReplyBox(clp, project, psId, revision, allLabels, permittedLabels);
-      allLabels = null;
-      permittedLabels = null;
-    }
-    if (msg != null) {
-      replyBox.replyTo(msg);
-    }
-
-    final PopupPanel p = new PopupPanel(true, false);
-    p.setStyleName(style.replyBox());
-    p.addAutoHidePartner(replyButton.getElement());
-    p.addAutoHidePartner(quickApproveButton.getElement());
-    p.addCloseHandler(
-        new CloseHandler<PopupPanel>() {
-          @Override
-          public void onClose(CloseEvent<PopupPanel> event) {
-            if (popup == p) {
-              popup = null;
-              if (hasDraftComments || replyBox.hasMessage()) {
-                replyButton.setStyleName(style.highlight());
-              }
-            }
-          }
-        });
-    p.add(replyBox);
-    Window.scrollTo(0, 0);
-    replyButton.removeStyleName(style.highlight());
-    p.showRelativeTo(replyButton);
-    GlobalKey.dialog(p);
-    popup = p;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.java
deleted file mode 100644
index 8a1a2d5..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.java
+++ /dev/null
@@ -1,544 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import static com.google.gwt.event.dom.client.KeyCodes.KEY_ENTER;
-import static com.google.gwt.event.dom.client.KeyCodes.KEY_MAC_ENTER;
-import static java.util.stream.Collectors.collectingAndThen;
-import static java.util.stream.Collectors.toList;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.changes.CommentInfo;
-import com.google.gerrit.client.changes.ReviewInput;
-import com.google.gerrit.client.changes.ReviewInput.DraftHandling;
-import com.google.gerrit.client.changes.Util;
-import com.google.gerrit.client.info.ChangeInfo.ApprovalInfo;
-import com.google.gerrit.client.info.ChangeInfo.LabelInfo;
-import com.google.gerrit.client.info.ChangeInfo.MessageInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.client.ui.CommentLinkProcessor;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.common.data.LabelValue;
-import com.google.gerrit.reviewdb.client.Patch;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.RepeatingCommand;
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.KeyDownEvent;
-import com.google.gwt.event.dom.client.KeyDownHandler;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.event.dom.client.MouseOutEvent;
-import com.google.gwt.event.dom.client.MouseOutHandler;
-import com.google.gwt.event.dom.client.MouseOverEvent;
-import com.google.gwt.event.dom.client.MouseOverHandler;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.logical.shared.ValueChangeHandler;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.RadioButton;
-import com.google.gwt.user.client.ui.ScrollPanel;
-import com.google.gwt.user.client.ui.TextArea;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwt.user.client.ui.Widget;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
-
-public class ReplyBox extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, ReplyBox> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  interface Styles extends CssResource {
-    String label_name();
-
-    String label_value();
-
-    String label_help();
-  }
-
-  private final CommentLinkProcessor clp;
-  private final Project.NameKey project;
-  private final PatchSet.Id psId;
-  private final String revision;
-  private ReviewInput in = ReviewInput.create();
-  private int labelHelpColumn;
-  private LocalComments lc;
-
-  @UiField Styles style;
-  @UiField TextArea message;
-  @UiField Element labelsParent;
-  @UiField Grid labelsTable;
-  @UiField Button post;
-  @UiField Button cancel;
-  @UiField ScrollPanel commentsPanel;
-  @UiField FlowPanel comments;
-
-  ReplyBox(
-      CommentLinkProcessor clp,
-      Project.NameKey project,
-      PatchSet.Id psId,
-      String revision,
-      NativeMap<LabelInfo> all,
-      NativeMap<JsArrayString> permitted) {
-    this.clp = clp;
-    this.project = project;
-    this.psId = psId;
-    this.revision = revision;
-    this.lc = new LocalComments(project, psId.getParentKey());
-    initWidget(uiBinder.createAndBindUi(this));
-
-    List<String> names =
-        permitted
-            .keySet()
-            .stream()
-            .sorted()
-            .collect(collectingAndThen(toList(), Collections::unmodifiableList));
-    if (names.isEmpty()) {
-      UIObject.setVisible(labelsParent, false);
-    } else {
-      renderLabels(names, all, permitted);
-    }
-
-    addDomHandler(
-        new KeyDownHandler() {
-          @Override
-          public void onKeyDown(KeyDownEvent e) {
-            e.stopPropagation();
-            if ((e.getNativeKeyCode() == KEY_ENTER || e.getNativeKeyCode() == KEY_MAC_ENTER)
-                && (e.isControlKeyDown() || e.isMetaKeyDown())) {
-              e.preventDefault();
-              if (post.isEnabled()) {
-                onPost(null);
-              }
-            }
-          }
-        },
-        KeyDownEvent.getType());
-    addDomHandler(
-        new KeyPressHandler() {
-          @Override
-          public void onKeyPress(KeyPressEvent e) {
-            e.stopPropagation();
-          }
-        },
-        KeyPressEvent.getType());
-  }
-
-  @Override
-  protected void onLoad() {
-    commentsPanel.setVisible(false);
-    post.setEnabled(false);
-    if (lc.hasReplyComment()) {
-      message.setText(lc.getReplyComment());
-      lc.removeReplyComment();
-    }
-    ChangeApi.drafts(project.get(), psId.getParentKey().get())
-        .get(
-            new AsyncCallback<NativeMap<JsArray<CommentInfo>>>() {
-              @Override
-              public void onSuccess(NativeMap<JsArray<CommentInfo>> result) {
-                displayComments(result);
-                post.setEnabled(true);
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {
-                post.setEnabled(true);
-              }
-            });
-
-    Scheduler.get()
-        .scheduleDeferred(
-            new ScheduledCommand() {
-              @Override
-              public void execute() {
-                message.setFocus(true);
-              }
-            });
-    Scheduler.get()
-        .scheduleFixedDelay(
-            new RepeatingCommand() {
-              @Override
-              public boolean execute() {
-                String t = message.getText();
-                if (t != null) {
-                  message.setCursorPos(t.length());
-                }
-                return false;
-              }
-            },
-            0);
-  }
-
-  @UiHandler("post")
-  void onPost(@SuppressWarnings("unused") ClickEvent e) {
-    postReview();
-  }
-
-  void quickApprove(ReviewInput quickApproveInput) {
-    in.mergeLabels(quickApproveInput);
-    postReview();
-  }
-
-  boolean hasMessage() {
-    return !message.getText().trim().isEmpty();
-  }
-
-  private void postReview() {
-    in.message(message.getText().trim());
-    // Don't send any comments in the request; just publish everything, even if
-    // e.g. a draft was modified in another tab since we last looked it up.
-    in.drafts(DraftHandling.PUBLISH_ALL_REVISIONS);
-    in.prePost();
-    ChangeApi.revision(project.get(), psId.getParentKey().get(), revision)
-        .view("review")
-        .post(
-            in,
-            new GerritCallback<ReviewInput>() {
-              @Override
-              public void onSuccess(ReviewInput result) {
-                Gerrit.display(PageLinks.toChange(project, psId));
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {
-                if (RestApi.isNotSignedIn(caught)) {
-                  lc.setReplyComment(message.getText());
-                }
-                super.onFailure(caught);
-              }
-            });
-    hide();
-  }
-
-  @UiHandler("cancel")
-  void onCancel(@SuppressWarnings("unused") ClickEvent e) {
-    message.setText("");
-    hide();
-  }
-
-  void replyTo(MessageInfo msg) {
-    if (msg.message() != null) {
-      String t = message.getText();
-      String m = quote(removePatchSetHeaderLine(msg.message()));
-      if (t == null || t.isEmpty()) {
-        t = m;
-      } else if (t.endsWith("\n\n")) {
-        t += m;
-      } else if (t.endsWith("\n")) {
-        t += "\n" + m;
-      } else {
-        t += "\n\n" + m;
-      }
-      message.setText(t);
-    }
-  }
-
-  private static String removePatchSetHeaderLine(String msg) {
-    msg = msg.trim();
-    if (msg.startsWith("Patch Set ")) {
-      int i = msg.indexOf('\n');
-      if (i > 0) {
-        msg = msg.substring(i + 1).trim();
-      }
-    }
-    return msg;
-  }
-
-  public static String quote(String msg) {
-    msg = msg.trim();
-    StringBuilder quotedMsg = new StringBuilder();
-    for (String line : msg.split("\\n")) {
-      line = line.trim();
-      while (line.length() > 67) {
-        int i = line.lastIndexOf(' ', 67);
-        if (i < 50) {
-          i = line.indexOf(' ', 67);
-        }
-        if (i > 0) {
-          quotedMsg.append(" > ").append(line.substring(0, i)).append("\n");
-          line = line.substring(i + 1);
-        } else {
-          break;
-        }
-      }
-      quotedMsg.append(" > ").append(line).append("\n");
-    }
-    quotedMsg.append("\n");
-    return quotedMsg.toString();
-  }
-
-  private void hide() {
-    for (Widget w = getParent(); w != null; w = w.getParent()) {
-      if (w instanceof PopupPanel) {
-        ((PopupPanel) w).hide();
-        break;
-      }
-    }
-  }
-
-  private void renderLabels(
-      List<String> names, NativeMap<LabelInfo> all, NativeMap<JsArrayString> permitted) {
-    TreeSet<Short> values = new TreeSet<>();
-    List<LabelAndValues> labels = new ArrayList<>(permitted.size());
-    for (String id : names) {
-      JsArrayString p = permitted.get(id);
-      if (p != null) {
-        if (!all.containsKey(id)) {
-          continue;
-        }
-        Set<Short> a = new TreeSet<>();
-        for (int i = 0; i < p.length(); i++) {
-          a.add(LabelInfo.parseValue(p.get(i)));
-        }
-        labels.add(new LabelAndValues(all.get(id), a));
-        values.addAll(a);
-      }
-    }
-    List<Short> columns = new ArrayList<>(values);
-
-    labelsTable.resize(1 + labels.size(), 2 + values.size());
-    for (int c = 0; c < columns.size(); c++) {
-      labelsTable.setText(0, 1 + c, LabelValue.formatValue(columns.get(c)));
-      labelsTable.getCellFormatter().setStyleName(0, 1 + c, style.label_value());
-    }
-
-    List<LabelAndValues> checkboxes = new ArrayList<>(labels.size());
-    int row = 1;
-    for (LabelAndValues lv : labels) {
-      if (isCheckBox(lv.info.valueSet())) {
-        checkboxes.add(lv);
-      } else {
-        renderRadio(row++, columns, lv);
-      }
-    }
-    for (LabelAndValues lv : checkboxes) {
-      renderCheckBox(row++, lv);
-    }
-  }
-
-  private Short normalizeDefaultValue(Short defaultValue, Set<Short> permittedValues) {
-    Short pmin = Collections.min(permittedValues);
-    Short pmax = Collections.max(permittedValues);
-    Short dv = defaultValue;
-    if (dv > pmax) {
-      dv = pmax;
-    } else if (dv < pmin) {
-      dv = pmin;
-    }
-    return dv;
-  }
-
-  private void renderRadio(int row, List<Short> columns, LabelAndValues lv) {
-    String id = lv.info.name();
-    Short dv = normalizeDefaultValue(lv.info.defaultValue(), lv.permitted);
-
-    labelHelpColumn = 1 + columns.size();
-    labelsTable.setText(row, 0, id);
-
-    CellFormatter fmt = labelsTable.getCellFormatter();
-    fmt.setStyleName(row, 0, style.label_name());
-    fmt.setStyleName(row, labelHelpColumn, style.label_help());
-
-    ApprovalInfo self =
-        Gerrit.isSignedIn() ? lv.info.forUser(Gerrit.getUserAccount()._accountId()) : null;
-
-    final LabelRadioGroup group = new LabelRadioGroup(row, id, lv.permitted.size());
-    for (int i = 0; i < columns.size(); i++) {
-      Short v = columns.get(i);
-      if (lv.permitted.contains(v)) {
-        String text = lv.info.valueText(LabelValue.formatValue(v));
-        LabelRadioButton b = new LabelRadioButton(group, text, v);
-        if ((self != null && v == self.value()) || (self == null && v.equals(dv))) {
-          b.setValue(true);
-          group.select(b);
-          in.label(group.label, v);
-          labelsTable.setText(row, labelHelpColumn, b.text);
-        }
-        group.buttons.add(b);
-        labelsTable.setWidget(row, 1 + i, b);
-      }
-    }
-  }
-
-  private void renderCheckBox(int row, LabelAndValues lv) {
-    ApprovalInfo self =
-        Gerrit.isSignedIn() ? lv.info.forUser(Gerrit.getUserAccount()._accountId()) : null;
-
-    final String id = lv.info.name();
-    final CheckBox b = new CheckBox();
-    b.setText(id);
-    b.setEnabled(lv.permitted.contains((short) 1));
-    if (self != null && self.value() == 1) {
-      b.setValue(true);
-    }
-    b.addValueChangeHandler(
-        new ValueChangeHandler<Boolean>() {
-          @Override
-          public void onValueChange(ValueChangeEvent<Boolean> event) {
-            in.label(id, event.getValue() ? (short) 1 : (short) 0);
-          }
-        });
-    b.setStyleName(style.label_name());
-    labelsTable.setWidget(row, 0, b);
-
-    CellFormatter fmt = labelsTable.getCellFormatter();
-    fmt.setStyleName(row, labelHelpColumn, style.label_help());
-    labelsTable.setText(row, labelHelpColumn, lv.info.valueText("+1"));
-  }
-
-  private static boolean isCheckBox(Set<Short> values) {
-    return values.size() == 2 && values.contains((short) 0) && values.contains((short) 1);
-  }
-
-  private void displayComments(NativeMap<JsArray<CommentInfo>> m) {
-    comments.clear();
-
-    JsArray<CommentInfo> l = m.get(Patch.COMMIT_MSG);
-    if (l != null) {
-      comments.add(
-          new FileComments(
-              clp, project, psId, Util.C.commitMessage(), copyPath(Patch.COMMIT_MSG, l)));
-    }
-    l = m.get(Patch.MERGE_LIST);
-    if (l != null) {
-      comments.add(
-          new FileComments(
-              clp, project, psId, Util.C.commitMessage(), copyPath(Patch.MERGE_LIST, l)));
-    }
-
-    List<String> paths =
-        m.keySet()
-            .stream()
-            .sorted()
-            .collect(collectingAndThen(toList(), Collections::unmodifiableList));
-
-    for (String path : paths) {
-      if (!Patch.isMagic(path)) {
-        comments.add(new FileComments(clp, project, psId, path, copyPath(path, m.get(path))));
-      }
-    }
-
-    commentsPanel.setVisible(comments.getWidgetCount() > 0);
-  }
-
-  private static List<CommentInfo> copyPath(String path, JsArray<CommentInfo> l) {
-    for (int i = 0; i < l.length(); i++) {
-      l.get(i).path(path);
-    }
-    return Natives.asList(l);
-  }
-
-  private static class LabelAndValues {
-    final LabelInfo info;
-    final Set<Short> permitted;
-
-    LabelAndValues(LabelInfo info, Set<Short> permitted) {
-      this.info = info;
-      this.permitted = permitted;
-    }
-  }
-
-  private class LabelRadioGroup {
-    final int row;
-    final String label;
-    final List<LabelRadioButton> buttons;
-    LabelRadioButton selected;
-
-    LabelRadioGroup(int row, String label, int cnt) {
-      this.row = row;
-      this.label = label;
-      this.buttons = new ArrayList<>(cnt);
-    }
-
-    void select(LabelRadioButton b) {
-      selected = b;
-      labelsTable.setText(row, labelHelpColumn, b.text);
-    }
-  }
-
-  private class LabelRadioButton extends RadioButton
-      implements ValueChangeHandler<Boolean>, ClickHandler, MouseOverHandler, MouseOutHandler {
-    private final LabelRadioGroup group;
-    private final String text;
-    private final short value;
-
-    LabelRadioButton(LabelRadioGroup group, String text, short value) {
-      super(group.label);
-      this.group = group;
-      this.text = text;
-      this.value = value;
-      addValueChangeHandler(this);
-      addClickHandler(this);
-      addMouseOverHandler(this);
-      addMouseOutHandler(this);
-    }
-
-    @Override
-    public void onValueChange(ValueChangeEvent<Boolean> event) {
-      if (event.getValue()) {
-        select();
-      }
-    }
-
-    @Override
-    public void onClick(ClickEvent event) {
-      select();
-    }
-
-    void select() {
-      group.select(this);
-      in.label(group.label, value);
-    }
-
-    @Override
-    public void onMouseOver(MouseOverEvent event) {
-      labelsTable.setText(group.row, labelHelpColumn, text);
-    }
-
-    @Override
-    public void onMouseOut(MouseOutEvent event) {
-      LabelRadioButton b = group.selected;
-      String s = b != null ? b.text : "";
-      labelsTable.setText(group.row, labelHelpColumn, s);
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.ui.xml
deleted file mode 100644
index 6903b91..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.ui.xml
+++ /dev/null
@@ -1,85 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-  <ui:with field='res' type='com.google.gerrit.client.change.Resources'/>
-  <ui:style gss='false' type='com.google.gerrit.client.change.ReplyBox.Styles'>
-    .replyBox {
-    }
-    .label_name {
-      font-weight: bold;
-      text-align: left;
-      white-space: nowrap;
-    }
-    .label_name input { margin-left: 0; }
-    .label_help {
-      padding-left: 5px;
-      white-space: nowrap;
-    }
-    .label_value {
-      text-align: center;
-    }
-    .cancel {
-      position: absolute;
-      bottom: 5px;
-      right: 5px;
-      background-color: #eee;
-      background-image: -webkit-linear-gradient(top, #eee, #eee);
-    }
-    .cancel div { color: #444; }
-    .comments {
-      max-height: 275px;
-      width: 526px;
-    }
-    .comments p {
-      margin: 5px 0 5px 0;
-    }
-  </ui:style>
-  <g:HTMLPanel styleName='{style.replyBox}'>
-    <div class='{res.style.section}'>
-      <g:TextArea
-         visibleLines='5'
-         characterWidth='70'
-         ui:field='message'/>
-    </div>
-    <div class='{res.style.section}' ui:field='labelsParent'>
-      <g:Grid ui:field='labelsTable'/>
-    </div>
-    <g:ScrollPanel ui:field='commentsPanel'
-        styleName='{style.comments}'
-        addStyleNames='{res.style.section}'>
-      <g:FlowPanel ui:field='comments'/>
-    </g:ScrollPanel>
-    <div class='{res.style.section}' style='position: relative'>
-      <g:Button ui:field='post'
-          title='Post reply (Shortcut: Ctrl-Enter)'
-          styleName='{res.style.button}'>
-        <ui:attribute name='title'/>
-        <div><ui:msg>Post</ui:msg></div>
-      </g:Button>
-
-      <g:Button ui:field='cancel'
-          title='Close reply form (Shortcut: Esc)'
-          styleName='{res.style.button}'
-          addStyleNames='{style.cancel}'>
-        <ui:attribute name='title'/>
-        <div><ui:msg>Cancel</ui:msg></div>
-      </g:Button>
-    </div>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Resources.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Resources.java
deleted file mode 100644
index cfc4e23..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Resources.java
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.resources.client.ClientBundle;
-import com.google.gwt.resources.client.CssResource;
-
-public interface Resources extends ClientBundle {
-  Resources I = GWT.create(Resources.class);
-  ChangeConstants C = GWT.create(ChangeConstants.class);
-  ChangeMessages M = GWT.create(ChangeMessages.class);
-
-  @Source("common.css")
-  Style style();
-
-  public interface Style extends CssResource {
-    String button();
-
-    String popup();
-
-    String popupContent();
-
-    String section();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RestoreAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RestoreAction.java
deleted file mode 100644
index aa3a9ef..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RestoreAction.java
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.user.client.ui.Button;
-
-class RestoreAction extends ActionMessageBox {
-  private final Project.NameKey project;
-  private final Change.Id id;
-
-  RestoreAction(Button b, Project.NameKey project, Change.Id id) {
-    super(b);
-    this.project = project;
-    this.id = id;
-  }
-
-  @Override
-  void send(String message) {
-    ChangeApi.restore(
-        project.get(),
-        id.get(),
-        message,
-        new GerritCallback<ChangeInfo>() {
-          @Override
-          public void onSuccess(ChangeInfo result) {
-            Gerrit.display(PageLinks.toChange(project, id));
-            hide();
-          }
-        });
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RevertAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RevertAction.java
deleted file mode 100644
index 3fba125..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RevertAction.java
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.changes.Util;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.ui.TextAreaActionDialog;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.PopupPanel;
-
-class RevertAction {
-
-  static void call(
-      final Button b,
-      Change.Id id,
-      Project.NameKey project,
-      String revision,
-      String commitSubject) {
-    // TODO Replace ActionDialog with a nicer looking display.
-    b.setEnabled(false);
-    new TextAreaActionDialog(Util.C.revertChangeTitle(), Util.C.headingRevertMessage()) {
-      {
-        sendButton.setText(Util.C.buttonRevertChangeSend());
-        message.setText(Util.M.revertChangeDefaultMessage(commitSubject, revision));
-      }
-
-      @Override
-      public void onSend() {
-        ChangeApi.revert(
-            project.get(),
-            id.get(),
-            getMessageText(),
-            new GerritCallback<ChangeInfo>() {
-              @Override
-              public void onSuccess(ChangeInfo result) {
-                sent = true;
-                hide();
-                Gerrit.display(PageLinks.toChange(result.projectNameKey(), result.legacyId()));
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {
-                enableButtons(true);
-                super.onFailure(caught);
-              }
-            });
-      }
-
-      @Override
-      public void onClose(CloseEvent<PopupPanel> event) {
-        super.onClose(event);
-        b.setEnabled(true);
-      }
-    }.center();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReviewerSuggestOracle.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReviewerSuggestOracle.java
deleted file mode 100644
index 4e464df..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReviewerSuggestOracle.java
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.admin.AdminConstants;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.info.GroupBaseInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.AccountSuggestOracle;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwtexpui.safehtml.client.HighlightSuggestOracle;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/** REST API based suggestion Oracle for reviewers. */
-public class ReviewerSuggestOracle extends HighlightSuggestOracle {
-  private Project.NameKey project;
-  private Change.Id changeId;
-
-  @Override
-  protected void onRequestSuggestions(Request req, Callback cb) {
-    ChangeApi.suggestReviewers(project.get(), changeId.get(), req.getQuery(), req.getLimit(), false)
-        .get(
-            new GerritCallback<JsArray<SuggestReviewerInfo>>() {
-              @Override
-              public void onSuccess(JsArray<SuggestReviewerInfo> result) {
-                List<RestReviewerSuggestion> r = new ArrayList<>(result.length());
-                for (SuggestReviewerInfo reviewer : Natives.asList(result)) {
-                  r.add(new RestReviewerSuggestion(reviewer, req.getQuery()));
-                }
-                cb.onSuggestionsReady(req, new Response(r));
-              }
-
-              @Override
-              public void onFailure(Throwable err) {
-                List<Suggestion> r = Collections.emptyList();
-                cb.onSuggestionsReady(req, new Response(r));
-              }
-            });
-  }
-
-  @Override
-  public void requestDefaultSuggestions(Request req, Callback cb) {
-    requestSuggestions(req, cb);
-  }
-
-  public void setChange(Project.NameKey project, Change.Id changeId) {
-    this.project = project;
-    this.changeId = changeId;
-  }
-
-  public static class RestReviewerSuggestion implements Suggestion {
-    private final String displayString;
-    private final String replacementString;
-
-    RestReviewerSuggestion(SuggestReviewerInfo reviewer, String query) {
-      if (reviewer.account() != null) {
-        this.replacementString =
-            AccountSuggestOracle.AccountSuggestion.format(reviewer.account(), query);
-        this.displayString = replacementString;
-      } else {
-        this.replacementString = reviewer.group().name();
-        this.displayString =
-            replacementString + " (" + AdminConstants.I.suggestedGroupLabel() + ")";
-      }
-    }
-
-    @Override
-    public String getDisplayString() {
-      return displayString;
-    }
-
-    @Override
-    public String getReplacementString() {
-      return replacementString;
-    }
-  }
-
-  public static class SuggestReviewerInfo extends JavaScriptObject {
-    public final native AccountInfo account() /*-{ return this.account; }-*/;
-
-    public final native GroupBaseInfo group() /*-{ return this.group; }-*/;
-
-    protected SuggestReviewerInfo() {}
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Reviewers.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Reviewers.java
deleted file mode 100644
index 859af19..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Reviewers.java
+++ /dev/null
@@ -1,328 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.ConfirmationCallback;
-import com.google.gerrit.client.ConfirmationDialog;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.NotSignedInDialog;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.changes.Util;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.ChangeInfo.ApprovalInfo;
-import com.google.gerrit.client.info.ChangeInfo.LabelInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.NativeString;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.RemoteSuggestBox;
-import com.google.gerrit.extensions.client.ReviewerState;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.event.logical.shared.SelectionEvent;
-import com.google.gwt.event.logical.shared.SelectionHandler;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.rpc.StatusCodeException;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwtexpui.safehtml.client.SafeHtml;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/** Add reviewers. */
-public class Reviewers extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, Reviewers> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  @UiField Element reviewersText;
-  @UiField Image addReviewerIcon;
-  @UiField Button addMe;
-  @UiField Element form;
-  @UiField Element error;
-
-  @UiField(provided = true)
-  RemoteSuggestBox suggestBox;
-
-  private ChangeScreen.Style style;
-  private Element ccText;
-
-  private ReviewerSuggestOracle reviewerSuggestOracle;
-  private Change.Id changeId;
-  private Project.NameKey project;
-
-  Reviewers() {
-    reviewerSuggestOracle = new ReviewerSuggestOracle();
-    suggestBox = new RemoteSuggestBox(reviewerSuggestOracle);
-    suggestBox.enableDefaultSuggestions();
-    suggestBox.setVisibleLength(55);
-    suggestBox.setHintText(Util.C.approvalTableAddReviewerHint());
-    suggestBox.addCloseHandler(
-        new CloseHandler<RemoteSuggestBox>() {
-          @Override
-          public void onClose(CloseEvent<RemoteSuggestBox> event) {
-            Reviewers.this.onCancel(null);
-          }
-        });
-    suggestBox.addSelectionHandler(
-        new SelectionHandler<String>() {
-          @Override
-          public void onSelection(SelectionEvent<String> event) {
-            addReviewer(event.getSelectedItem(), false);
-          }
-        });
-
-    initWidget(uiBinder.createAndBindUi(this));
-    addReviewerIcon.addDomHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            onOpenForm();
-          }
-        },
-        ClickEvent.getType());
-  }
-
-  void init(ChangeScreen.Style style, Element ccText) {
-    this.style = style;
-    this.ccText = ccText;
-  }
-
-  void set(ChangeInfo info) {
-    this.changeId = info.legacyId();
-    this.project = info.projectNameKey();
-    display(info);
-    reviewerSuggestOracle.setChange(project, changeId);
-    addReviewerIcon.setVisible(Gerrit.isSignedIn());
-  }
-
-  void onOpenForm() {
-    UIObject.setVisible(form, true);
-    UIObject.setVisible(error, false);
-    addReviewerIcon.setVisible(false);
-    suggestBox.setServeSuggestionsOnOracle(true);
-    suggestBox.setFocus(true);
-  }
-
-  @UiHandler("add")
-  void onAdd(@SuppressWarnings("unused") ClickEvent e) {
-    addReviewer(suggestBox.getText(), false);
-  }
-
-  @UiHandler("addMe")
-  void onAddMe(@SuppressWarnings("unused") ClickEvent e) {
-    String accountId = String.valueOf(Gerrit.getUserAccount()._accountId());
-    addReviewer(accountId, false);
-  }
-
-  @UiHandler("cancel")
-  void onCancel(@SuppressWarnings("unused") ClickEvent e) {
-    addReviewerIcon.setVisible(true);
-    UIObject.setVisible(form, false);
-    suggestBox.setFocus(false);
-    suggestBox.setText("");
-    suggestBox.setServeSuggestionsOnOracle(false);
-  }
-
-  private void addReviewer(String reviewer, boolean confirmed) {
-    if (reviewer.isEmpty()) {
-      return;
-    }
-
-    ChangeApi.reviewers(project.get(), changeId.get())
-        .post(
-            PostInput.create(reviewer, confirmed),
-            new GerritCallback<PostResult>() {
-              @Override
-              public void onSuccess(PostResult result) {
-                if (result.confirm()) {
-                  askForConfirmation(result.error());
-                } else if (result.error() != null) {
-                  UIObject.setVisible(error, true);
-                  error.setInnerText(result.error());
-                } else {
-                  UIObject.setVisible(error, false);
-                  error.setInnerText("");
-                  suggestBox.setText("");
-
-                  if (result.reviewers() != null && result.reviewers().length() > 0) {
-                    updateReviewerList();
-                  }
-                }
-              }
-
-              private void askForConfirmation(String text) {
-                new ConfirmationDialog(
-                        Util.C.approvalTableAddManyReviewersConfirmationDialogTitle(),
-                        new SafeHtmlBuilder().append(text),
-                        new ConfirmationCallback() {
-                          @Override
-                          public void onOk() {
-                            addReviewer(reviewer, true);
-                          }
-                        })
-                    .center();
-              }
-
-              @Override
-              public void onFailure(Throwable err) {
-                if (isSigninFailure(err)) {
-                  new NotSignedInDialog().center();
-                } else {
-                  UIObject.setVisible(error, true);
-                  error.setInnerText(
-                      err instanceof StatusCodeException
-                          ? ((StatusCodeException) err).getEncodedResponse()
-                          : err.getMessage());
-                }
-              }
-            });
-  }
-
-  void updateReviewerList() {
-    ChangeApi.detail(
-        project.get(),
-        changeId.get(),
-        new GerritCallback<ChangeInfo>() {
-          @Override
-          public void onSuccess(ChangeInfo result) {
-            display(result);
-          }
-        });
-  }
-
-  private void display(ChangeInfo info) {
-    Map<ReviewerState, List<AccountInfo>> reviewers = info.reviewers();
-    Map<Integer, AccountInfo> r = byAccount(reviewers, ReviewerState.REVIEWER);
-    Map<Integer, AccountInfo> cc = byAccount(reviewers, ReviewerState.CC);
-    for (Integer i : r.keySet()) {
-      cc.remove(i);
-    }
-    cc.remove(info.owner()._accountId());
-    Set<Integer> removable = info.removableReviewerIds();
-    Map<Integer, VotableInfo> votable = votable(info);
-
-    SafeHtml rHtml = Labels.formatUserList(style, r.values(), removable, null, votable);
-    SafeHtml ccHtml = Labels.formatUserList(style, cc.values(), removable, null, votable);
-
-    reviewersText.setInnerSafeHtml(rHtml);
-    ccText.setInnerSafeHtml(ccHtml);
-    if (Gerrit.isSignedIn()) {
-      int currentUser = Gerrit.getUserAccount()._accountId();
-      boolean showAddMeButton =
-          info.owner()._accountId() != currentUser
-              && !cc.containsKey(currentUser)
-              && !r.containsKey(currentUser);
-      addMe.setVisible(showAddMeButton);
-    }
-  }
-
-  private static Map<Integer, AccountInfo> byAccount(
-      Map<ReviewerState, List<AccountInfo>> reviewers, ReviewerState state) {
-    List<AccountInfo> accounts = reviewers.get(state);
-    if (accounts == null) {
-      return Collections.emptyMap();
-    }
-    Map<Integer, AccountInfo> result = new HashMap<>();
-    for (AccountInfo a : accounts) {
-      result.put(a._accountId(), a);
-    }
-    return result;
-  }
-
-  private static Map<Integer, VotableInfo> votable(ChangeInfo change) {
-    Map<Integer, VotableInfo> d = new HashMap<>();
-    for (String name : change.labels()) {
-      LabelInfo label = change.label(name);
-      Short labelMaxValue =
-          label.valueSet().isEmpty() ? null : LabelInfo.parseValue(label.maxValue());
-      if (label.all() != null) {
-        for (ApprovalInfo ai : Natives.asList(label.all())) {
-          int id = ai._accountId();
-          VotableInfo ad = d.get(id);
-          if (ad == null) {
-            ad = new VotableInfo();
-            d.put(id, ad);
-          }
-          if (labelMaxValue != null
-              && ai.permittedVotingRange() != null
-              && ai.permittedVotingRange().max() == labelMaxValue) {
-            ad.votable(name + " (" + label.maxValue() + ") ");
-          } else if (ai.hasValue()) {
-            ad.votable(name);
-          }
-        }
-      }
-    }
-    return d;
-  }
-
-  public static class PostInput extends JavaScriptObject {
-    public static PostInput create(String reviewer, boolean confirmed) {
-      PostInput input = createObject().cast();
-      input.init(reviewer, confirmed);
-      return input;
-    }
-
-    private native void init(String reviewer, boolean confirmed) /*-{
-      this.reviewer = reviewer;
-      if (confirmed) {
-        this.confirmed = true;
-      }
-    }-*/;
-
-    protected PostInput() {}
-  }
-
-  public static class ReviewerInfo extends AccountInfo {
-    final Set<String> approvals() {
-      return Natives.keys(_approvals());
-    }
-
-    final native String approval(String l) /*-{ return this.approvals[l]; }-*/;
-
-    private native NativeMap<NativeString> _approvals() /*-{ return this.approvals; }-*/;
-
-    protected ReviewerInfo() {}
-  }
-
-  public static class PostResult extends JavaScriptObject {
-    public final native JsArray<ReviewerInfo> reviewers() /*-{ return this.reviewers; }-*/;
-
-    public final native boolean confirm() /*-{ return this.confirm || false; }-*/;
-
-    public final native String error() /*-{ return this.error; }-*/;
-
-    protected PostResult() {}
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Reviewers.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Reviewers.ui.xml
deleted file mode 100644
index cf506e5..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Reviewers.ui.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:c='urn:import:com.google.gwtexpui.globalkey.client'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'
-    xmlns:u='urn:import:com.google.gerrit.client.ui'>
-  <ui:with field='ico' type='com.google.gerrit.client.GerritResources'/>
-  <ui:with field='res' type='com.google.gerrit.client.change.Resources'/>
-  <ui:style gss='false'>
-    .suggestBox {
-      margin-bottom: 2px;
-    }
-
-    .error {
-      color: #D33D3D;
-      font-weight: bold;
-    }
-
-    .addReviewer,
-    .cancel {
-      cursor: pointer;
-      float: right;
-    }
-  </ui:style>
-  <g:HTMLPanel>
-    <div>
-      <span ui:field='reviewersText'/>
-      <g:Image ui:field='addReviewerIcon'
-          resource='{ico.addUser}'
-          styleName='{style.addReviewer}'
-          title='Add Reviewer'/>
-    </div>
-    <div ui:field='form' style='display: none' aria-hidden='true'>
-      <u:RemoteSuggestBox ui:field='suggestBox' styleName='{style.suggestBox}'/>
-      <div ui:field='error'
-           class='{style.error}'
-           style='display: none' aria-hidden='true'/>
-      <div>
-        <g:Button ui:field='add' styleName='{res.style.button}'>
-          <div>Add</div>
-        </g:Button>
-        <g:Button ui:field='addMe'
-            styleName='{res.style.button}' visible='false'>
-          <div>Add Me</div>
-        </g:Button>
-        <g:Button ui:field='cancel'
-            styleName='{res.style.button}'
-            addStyleNames='{style.cancel}'>
-          <div>Cancel</div>
-        </g:Button>
-      </div>
-    </div>
-   </g:HTMLPanel>
-  </ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RightSidePopdownAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RightSidePopdownAction.java
deleted file mode 100644
index 1383c5d..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RightSidePopdownAction.java
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gwt.dom.client.Document;
-import com.google.gwt.dom.client.Style;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-
-abstract class RightSidePopdownAction {
-  private final ChangeScreen.Style style;
-  private final Widget button;
-  private final UIObject relativeTo;
-  private PopupPanel popup;
-
-  RightSidePopdownAction(ChangeScreen.Style style, UIObject relativeTo, Widget button) {
-    this.style = style;
-    this.relativeTo = relativeTo;
-    this.button = button;
-  }
-
-  abstract Widget getWidget();
-
-  void show() {
-    if (popup != null) {
-      button.removeStyleName(style.selected());
-      popup.hide();
-      return;
-    }
-
-    final PopupPanel p =
-        new PopupPanel(true) {
-          @Override
-          public void setPopupPosition(int left, int top) {
-            top -= Document.get().getBodyOffsetTop();
-
-            int w = Window.getScrollLeft() + Window.getClientWidth();
-            int r = relativeTo.getAbsoluteLeft() + relativeTo.getOffsetWidth();
-            int right = w - r;
-            Style style = getElement().getStyle();
-            style.clearProperty("left");
-            style.setPropertyPx("right", right);
-            style.setPropertyPx("top", top);
-          }
-        };
-    p.setStyleName(style.replyBox());
-    p.addAutoHidePartner(button.getElement());
-    p.addCloseHandler(
-        new CloseHandler<PopupPanel>() {
-          @Override
-          public void onClose(CloseEvent<PopupPanel> event) {
-            if (popup == p) {
-              button.removeStyleName(style.selected());
-              popup = null;
-            }
-          }
-        });
-    p.add(getWidget());
-    p.showRelativeTo(relativeTo);
-    GlobalKey.dialog(p);
-    button.addStyleName(style.selected());
-    popup = p;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/StarIcon.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/StarIcon.java
deleted file mode 100644
index b7bf8de..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/StarIcon.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.ToggleButton;
-
-class StarIcon extends ToggleButton {
-  StarIcon() {
-    super(new Image(Gerrit.RESOURCES.starOpen()), new Image(Gerrit.RESOURCES.starFilled()));
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/SubmitAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/SubmitAction.java
deleted file mode 100644
index 4446e65..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/SubmitAction.java
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.api.ChangeGlue;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.changes.SubmitInfo;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Change;
-
-class SubmitAction {
-  static void call(ChangeInfo changeInfo, RevisionInfo revisionInfo) {
-    if (ChangeGlue.onSubmitChange(changeInfo, revisionInfo)) {
-      final Change.Id changeId = changeInfo.legacyId();
-      ChangeApi.submit(
-          changeInfo.project(),
-          changeId.get(),
-          revisionInfo.name(),
-          new GerritCallback<SubmitInfo>() {
-            @Override
-            public void onSuccess(SubmitInfo result) {
-              redisplay();
-            }
-
-            @Override
-            public void onFailure(Throwable err) {
-              if (SubmitFailureDialog.isConflict(err)) {
-                new SubmitFailureDialog(err.getMessage()).center();
-              } else {
-                super.onFailure(err);
-              }
-              redisplay();
-            }
-
-            private void redisplay() {
-              Gerrit.display(PageLinks.toChange(changeInfo.projectNameKey(), changeId));
-            }
-          });
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/SubmitFailureDialog.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/SubmitFailureDialog.java
deleted file mode 100644
index 77bf217..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/SubmitFailureDialog.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.ErrorDialog;
-import com.google.gerrit.client.changes.Util;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-import com.google.gwtjsonrpc.client.RemoteJsonException;
-
-class SubmitFailureDialog extends ErrorDialog {
-  static boolean isConflict(Throwable err) {
-    return err instanceof RemoteJsonException && 409 == ((RemoteJsonException) err).getCode();
-  }
-
-  SubmitFailureDialog(String msg) {
-    super(new SafeHtmlBuilder().append(msg.trim()).wikify());
-    setText(Util.C.submitFailed());
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Topic.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Topic.java
deleted file mode 100644
index f5c921b..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Topic.java
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.ui.InlineHyperlink;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyDownEvent;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwtexpui.globalkey.client.NpTextBox;
-
-/** Displays (and edits) the change topic string. */
-class Topic extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, Topic> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  private PatchSet.Id psId;
-  private Project.NameKey project;
-  private boolean canEdit;
-
-  @UiField Element show;
-  @UiField InlineHyperlink text;
-  @UiField Image editIcon;
-
-  @UiField Element form;
-  @UiField NpTextBox input;
-  @UiField Button save;
-  @UiField Button cancel;
-
-  Topic() {
-    initWidget(uiBinder.createAndBindUi(this));
-    editIcon.addDomHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            onEdit();
-          }
-        },
-        ClickEvent.getType());
-  }
-
-  void set(ChangeInfo info, String revision) {
-    canEdit = info.hasActions() && info.actions().containsKey("topic");
-
-    psId = new PatchSet.Id(info.legacyId(), info.revisions().get(revision)._number());
-    project = info.projectNameKey();
-
-    initTopicLink(info);
-    editIcon.setVisible(canEdit);
-    if (!canEdit) {
-      show.setTitle(null);
-    }
-  }
-
-  private void initTopicLink(ChangeInfo info) {
-    if (info.topic() != null && !info.topic().isEmpty()) {
-      String topic = info.topic();
-      text.setText(topic);
-      text.setTargetHistoryToken(PageLinks.topicQuery(info.status(), topic));
-    }
-  }
-
-  boolean canEdit() {
-    return canEdit;
-  }
-
-  void onEdit() {
-    if (canEdit) {
-      UIObject.setVisible(show, false);
-      UIObject.setVisible(form, true);
-
-      input.setText(text.getText());
-      input.setFocus(true);
-      input.selectAll();
-    }
-  }
-
-  @UiHandler("cancel")
-  void onCancel(@SuppressWarnings("unused") ClickEvent e) {
-    input.setFocus(false);
-    UIObject.setVisible(form, false);
-    UIObject.setVisible(show, true);
-  }
-
-  @UiHandler("input")
-  void onKeyDownInput(KeyDownEvent e) {
-    if (e.getNativeKeyCode() == KeyCodes.KEY_ESCAPE) {
-      onCancel(null);
-    } else if (e.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
-      e.stopPropagation();
-      e.preventDefault();
-      onSave(null);
-    }
-  }
-
-  @UiHandler("save")
-  void onSave(@SuppressWarnings("unused") ClickEvent e) {
-    ChangeApi.topic(
-        project.get(),
-        psId.getParentKey().get(),
-        input.getValue().trim(),
-        new GerritCallback<String>() {
-          @Override
-          public void onSuccess(String result) {
-            Gerrit.display(PageLinks.toChange(project, psId));
-          }
-        });
-    onCancel(null);
-  }
-
-  @UiHandler("save")
-  void onSaveKeyPress(KeyPressEvent e) {
-    if (e.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
-      e.stopPropagation();
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Topic.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Topic.ui.xml
deleted file mode 100644
index c2a6fbd..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Topic.ui.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:c='urn:import:com.google.gwtexpui.globalkey.client'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'
-    xmlns:x='urn:import:com.google.gerrit.client.ui'>
-  <ui:with field='ico' type='com.google.gerrit.client.GerritResources'/>
-  <ui:with field='res' type='com.google.gerrit.client.change.Resources'/>
-  <ui:style gss='false'>
-    .edit { cursor: pointer; }
-    .edit, .cancel { float: right; }
-  </ui:style>
-  <g:HTMLPanel>
-    <div ui:field='show'>
-      <x:InlineHyperlink ui:field='text'
-          title='Search for changes on this topic'/>
-      <g:Image ui:field='editIcon'
-          resource='{ico.edit}'
-          styleName='{style.edit}'
-          title='Edit topic (Shortcut: t)'/>
-    </div>
-
-    <div ui:field='form' style='display: none' aria-hidden='true'>
-      <div>
-        <c:NpTextBox ui:field='input' visibleLength='55'/>
-      </div>
-      <div>
-        <g:Button ui:field='save' styleName='{res.style.button}'>
-          <div>Update</div>
-        </g:Button>
-        <g:Button ui:field='cancel'
-            styleName='{res.style.button}'
-            addStyleNames='{style.cancel}'>
-          <div>Cancel</div>
-        </g:Button>
-      </div>
-    </div>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/UpdateAvailableBar.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/UpdateAvailableBar.java
deleted file mode 100644
index 520dc69..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/UpdateAvailableBar.java
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.info.ChangeInfo.MessageInfo;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import java.sql.Timestamp;
-import java.util.HashSet;
-import java.util.List;
-
-/** Displays the "New Message From ..." panel in bottom right on updates. */
-abstract class UpdateAvailableBar extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, UpdateAvailableBar> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  private Timestamp updated;
-
-  @UiField Element author;
-  @UiField Anchor show;
-  @UiField Anchor ignore;
-
-  UpdateAvailableBar() {
-    initWidget(uiBinder.createAndBindUi(this));
-  }
-
-  void set(List<MessageInfo> newMessages, Timestamp newTime) {
-    HashSet<Integer> seen = new HashSet<>();
-    StringBuilder r = new StringBuilder();
-    for (MessageInfo m : newMessages) {
-      int a = m.author() != null ? m.author()._accountId() : 0;
-      if (seen.add(a)) {
-        if (r.length() > 0) {
-          r.append(", ");
-        }
-        r.append(Message.authorName(m));
-      }
-    }
-    author.setInnerText(r.toString());
-    updated = newTime;
-  }
-
-  @UiHandler("show")
-  void onShow(@SuppressWarnings("unused") ClickEvent e) {
-    onShow();
-  }
-
-  @UiHandler("ignore")
-  void onIgnore(@SuppressWarnings("unused") ClickEvent e) {
-    onIgnore(updated);
-    removeFromParent();
-  }
-
-  abstract void onShow();
-
-  abstract void onIgnore(Timestamp newTime);
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/UpdateAvailableBar.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/UpdateAvailableBar.ui.xml
deleted file mode 100644
index 1d5592b..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/UpdateAvailableBar.ui.xml
+++ /dev/null
@@ -1,65 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:c='urn:import:com.google.gwtexpui.globalkey.client'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-  <ui:style gss='false'>
-    .popup {
-      position: fixed;
-      bottom: 0;
-      right: 0;
-      z-index: 10;
-      padding: 5px;
-    }
-    .bar {
-      background-color: #fff1a8;
-      border: 1px solid #ccc;
-      padding: 5px 10px;
-      font-size: 80%;
-      color: #222;
-      white-space: nowrap;
-      width: auto;
-      height: auto;
-    }
-    a.action {
-      color: #222;
-      text-decoration: underline;
-      display: inline-block;
-      margin-left: 0.5em;
-    }
-  </ui:style>
-  <g:HTMLPanel styleName='{style.popup}'>
-    <div class='{style.bar}'>
-      <ui:msg>Update from <span ui:field='author'/></ui:msg>
-      <g:Anchor ui:field='show'
-          styleName='{style.action}'
-          href='javascript:;'
-          title='Refresh screen and display updates'>
-        <ui:attribute name='title'/>
-        <ui:msg>Show</ui:msg>
-      </g:Anchor>
-      <g:Anchor ui:field='ignore'
-          styleName='{style.action}'
-          href='javascript:;'
-          title='Ignore this update'>
-        <ui:attribute name='title'/>
-        <ui:msg>Ignore</ui:msg>
-      </g:Anchor>
-    </div>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/UpdateCheckTimer.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/UpdateCheckTimer.java
deleted file mode 100644
index 4a5af0551..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/UpdateCheckTimer.java
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.ui.UserActivityMonitor;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.logical.shared.ValueChangeHandler;
-import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-class UpdateCheckTimer extends Timer implements ValueChangeHandler<Boolean> {
-  private static final int MAX_PERIOD = 3 * 60 * 1000;
-  private static final int IDLE_PERIOD = 2 * 3600 * 1000;
-  private static final int POLL_PERIOD = Gerrit.info().change().updateDelay() * 1000;
-
-  private final ChangeScreen screen;
-  private int delay;
-  private boolean running;
-
-  UpdateCheckTimer(ChangeScreen screen) {
-    this.screen = screen;
-    this.delay = POLL_PERIOD;
-  }
-
-  void schedule() {
-    scheduleRepeating(delay);
-  }
-
-  @Override
-  public void run() {
-    if (!screen.isAttached()) {
-      // screen should have cancelled this timer.
-      cancel();
-      return;
-    } else if (running) {
-      return;
-    }
-
-    running = true;
-    screen.loadChangeInfo(
-        false,
-        new AsyncCallback<ChangeInfo>() {
-          @Override
-          public void onSuccess(ChangeInfo info) {
-            running = false;
-            screen.showUpdates(info);
-
-            int d = UserActivityMonitor.isActive() ? POLL_PERIOD : IDLE_PERIOD;
-            if (d != delay) {
-              delay = d;
-              schedule();
-            }
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            // On failures increase the delay time and try again,
-            // but place an upper bound on the delay.
-            running = false;
-            delay =
-                (int)
-                    Math.max(
-                        delay * (1.5 + Math.random()),
-                        UserActivityMonitor.isActive() ? MAX_PERIOD : IDLE_PERIOD + MAX_PERIOD);
-            schedule();
-          }
-        });
-  }
-
-  @Override
-  public void onValueChange(ValueChangeEvent<Boolean> event) {
-    if (event.getValue()) {
-      delay = POLL_PERIOD;
-      run();
-    } else {
-      delay = IDLE_PERIOD;
-    }
-    schedule();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/VotableInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/VotableInfo.java
deleted file mode 100644
index 33d8d12..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/VotableInfo.java
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import java.util.HashSet;
-import java.util.Set;
-
-class VotableInfo {
-  private Set<String> votable;
-
-  void votable(String label) {
-    if (votable == null) {
-      votable = new HashSet<>();
-    }
-    votable.add(label);
-  }
-
-  Set<String> votableLabels() {
-    Set<String> s = new HashSet<>();
-    if (votable != null) {
-      s.addAll(votable);
-    }
-    return s;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/common.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/common.css
deleted file mode 100644
index bb7cb27..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/common.css
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@eval trimColor com.google.gerrit.client.Gerrit.getTheme().trimColor;
-
-.popup {
-  background-color: trimColor;
-  min-width: 300px;
-  min-height: 90px;
-}
-
-.popupContent {
-  padding: 5px;
-}
-
-.button,
-.popup button,
-.popup input[type='button'] {
-  margin: 0 3px 0 0;
-  border-color: rgba(0, 0, 0, 0.15) !important;
-  text-align: center;
-  font-size: 11px;
-  font-weight: bold;
-  border: 2px solid;
-  cursor: pointer;
-  color: #fff;
-  background-color: #4d90fe;
-  background-image: -webkit-linear-gradient(top, #4d90fe, #4d90fe);
-  -webkit-border-radius: 2px;
-  -webkit-box-sizing: content-box;
-}
-
-.button:disabled,
-.popup button:disabled,
-.popup input[type='button']:disabled {
-  background-color: #999;
-  background-image: -webkit-linear-gradient(top, #999, #999);
-}
-
-.button div, .popup button div {
-  width: 54px;
-  white-space: nowrap;
-  color: #fff;
-  height: 14px;
-  line-height: 14px;
-}
-
-.section {
-  padding: 5px 5px;
-  border-bottom: 1px solid #b8b8b8;
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/file_table.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/file_table.css
deleted file mode 100644
index 6f514df..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/file_table.css
+++ /dev/null
@@ -1,115 +0,0 @@
-/* Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-.pointer, .reviewed, .restoreDelete {
-  padding: 0px;
-  vertical-align: top;
-}
-.pointer {
-  width: 12px;
-}
-.reviewed {
-  height: 19px;
-  width: 20px;
-}
-
-.table th {
-  vertical-align: top;
-  text-align: left;
-}
-.table tr {
-  vertical-align: top;
-}
-.table tr:hover {
-  background: rgba(209, 245, 248, 0.32);
-}
-.table tr.nohover:hover {
-  background: transparent;
-}
-
-.status {
-  padding-right: 4px;
-  color: #888;
-}
-
-.pathColumn {
-  white-space: nowrap;
-  min-width: 600px;
-}
-.pathColumn a {
-  color: #000;
-  cursor: pointer;
-}
-.commonPrefix {
-  color: #888;
-}
-.renameCopySource {
-  color: #888;
-  font-size: smaller;
-}
-
-.draftColumn,
-.newColumn,
-.commentColumn {
-  white-space: nowrap;
-}
-.draftColumn {
-  color: #d44;
-  font-weight: bold;
-}
-.newColumn {
-  font-weight: bold;
-}
-
-.deltaColumn1 {
-  white-space: nowrap;
-  text-align: right !important;
-}
-
-.deltaColumn2 {
-  padding-left: 5px;
-  white-space: nowrap;
-  text-align: right;
-}
-
-.inserted {
-  height: 10px;
-  display: inline-block;
-  background-color: #4d4;
-}
-
-.deleted {
-  height: 10px;
-  display: inline-block;
-  background-color: #d44;
-}
-
-.restoreDelete div {
-  white-space: nowrap;
-}
-
-.restoreDelete button {
-  cursor: pointer;
-  padding: 0;
-  margin: 0 0 0 5px;
-  border: 0;
-  background-color: transparent;
-  white-space: nowrap;
-}
-
-.error {
-  color: #D33D3D;
-  font-weight: bold;
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/moreLess.png b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/moreLess.png
deleted file mode 100644
index 298514f..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/moreLess.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/related_changes.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/related_changes.css
deleted file mode 100644
index 5e0e402..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/related_changes.css
+++ /dev/null
@@ -1,98 +0,0 @@
-/* Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@external .gwt-TabBarItem;
-@external .gwt-TabBarItem-disabled;
-@external .gwt-TabBarItem-selected;
-@external .gwt-TabBarRest;
-@external .gwt-TabPanelBottom;
-@eval selectionColor com.google.gerrit.client.Gerrit.getTheme().selectionColor;
-
-.row {
-  white-space: nowrap;
-}
-
-.activeRow {
-  background-color: selectionColor !important;
-}
-
-.activeRow .pointer {
-  visibility: visible;
-}
-
-.pointer {
-  display: inline-block;
-  vertical-align: top;
-  visibility: hidden;
-}
-
-.subject, .strikedSubject {
-  display: inline-block;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  width: 355px;
-}
-.strikedSubject {
-  text-decoration: line-through;
-}
-
-.tabPanel .gwt-TabBarItem,
-.tabPanel .gwt-TabBarItem-selected,
-.tabPanel .gwt-TabBarRest {
-  background: none repeat scroll 0 0 #FFF !important;
-}
-
-.tabPanel .gwt-TabPanelBottom {
-  padding: 2px 0 0 0;
-}
-
-.tabPanel .gwt-TabBarItem-selected {
-  border-bottom-color: #000 !important;
-  color: #000 !important;
-}
-
-.tabPanel .gwt-TabBarItem-disabled {
-  display: none;
-}
-
-.current,
-.gitweb,
-.indirect,
-.notCurrent,
-.submittable {
-  display: inline-block;
-  text-align: center;
-  vertical-align: top;
-  width: 12px;
-}
-
-.gitweb {
-  color: #000;
-}
-
-.indirect {
-  color: #090;      /* green */
-  font-weight: bold;
-}
-
-.notCurrent {
-  color: #FFA62F;   /* orange */
-}
-
-.submittable {
-  color: #090;      /* green */
-  font-weight: bold;
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AccountDashboardScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AccountDashboardScreen.java
deleted file mode 100644
index 7ec1102..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AccountDashboardScreen.java
+++ /dev/null
@@ -1,212 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-import static java.util.Comparator.comparing;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.NotFoundScreen;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gerrit.client.ui.InlineHyperlink;
-import com.google.gerrit.client.ui.Screen;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.extensions.client.ListChangesOption;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwtexpui.globalkey.client.KeyCommand;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.EnumSet;
-import java.util.Set;
-
-public class AccountDashboardScreen extends Screen implements ChangeListScreen {
-  // If changing default options, also update in
-  // ChangeIT#defaultSearchDoesNotTouchDatabase().
-  private static final Set<ListChangesOption> MY_DASHBOARD_OPTIONS;
-
-  static {
-    EnumSet<ListChangesOption> options = EnumSet.copyOf(ChangeTable.OPTIONS);
-    options.add(ListChangesOption.REVIEWED);
-    MY_DASHBOARD_OPTIONS = Collections.unmodifiableSet(options);
-  }
-
-  private final Integer ownerId;
-  private final boolean mine;
-  private ChangeTable table;
-  private ChangeTable.Section workInProgress;
-  private ChangeTable.Section outgoing;
-  private ChangeTable.Section incoming;
-  private ChangeTable.Section closed;
-
-  public AccountDashboardScreen(Integer accountId) {
-    ownerId = accountId;
-    mine = Gerrit.isSignedIn() && ownerId == Gerrit.getUserAccount()._accountId();
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    table =
-        new ChangeTable() {
-          {
-            keysNavigation.add(
-                new KeyCommand(0, 'R', Util.C.keyReloadSearch()) {
-                  @Override
-                  public void onKeyPress(KeyPressEvent event) {
-                    Gerrit.display(getToken());
-                  }
-                });
-          }
-        };
-    table.addStyleName(Gerrit.RESOURCES.css().accountDashboard());
-
-    workInProgress = new ChangeTable.Section();
-    outgoing = new ChangeTable.Section();
-    incoming = new ChangeTable.Section();
-    closed = new ChangeTable.Section();
-
-    String who = mine ? "self" : ownerId.toString();
-    workInProgress.setTitleWidget(
-        new InlineHyperlink(
-            Util.C.workInProgress(), PageLinks.toChangeQuery(queryWorkInProgress(who))));
-    outgoing.setTitleWidget(
-        new InlineHyperlink(Util.C.outgoingReviews(), PageLinks.toChangeQuery(queryOutgoing(who))));
-    incoming.setTitleWidget(
-        new InlineHyperlink(Util.C.incomingReviews(), PageLinks.toChangeQuery(queryIncoming(who))));
-    incoming.setHighlightUnreviewed(mine);
-    closed.setTitleWidget(
-        new InlineHyperlink(Util.C.recentlyClosed(), PageLinks.toChangeQuery(queryClosed(who))));
-
-    table.addSection(workInProgress);
-    table.addSection(outgoing);
-    table.addSection(incoming);
-    table.addSection(closed);
-    add(table);
-    table.setSavePointerId("owner:" + ownerId);
-  }
-
-  private static String queryWorkInProgress(String who) {
-    return "is:open is:wip owner:" + who;
-  }
-
-  private static String queryOutgoing(String who) {
-    return "is:open -is:wip owner:" + who;
-  }
-
-  private static String queryIncoming(String who) {
-    return "is:open ((reviewer:"
-        + who
-        + " -owner:"
-        + who
-        + " -is:ignored) OR assignee:"
-        + who
-        + ")";
-  }
-
-  private static String queryClosed(String who) {
-    return "is:closed (owner:" + who + " OR reviewer:" + who + " OR assignee:" + who + ")";
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-
-    String who = mine ? "self" : ownerId.toString();
-    ChangeList.queryMultiple(
-        new ScreenLoadCallback<JsArray<ChangeList>>(this) {
-          @Override
-          protected void preDisplay(JsArray<ChangeList> result) {
-            display(result);
-          }
-        },
-        mine ? MY_DASHBOARD_OPTIONS : DashboardTable.OPTIONS,
-        queryWorkInProgress(who),
-        queryOutgoing(who),
-        queryIncoming(who),
-        queryClosed(who) + " -age:4w limit:10");
-  }
-
-  @Override
-  public void registerKeys() {
-    super.registerKeys();
-    table.setRegisterKeys(true);
-  }
-
-  private void display(JsArray<ChangeList> result) {
-    if (!mine && !hasChanges(result)) {
-      // When no results are returned and the data is not for the
-      // current user, the target user is presumed to not exist.
-      Gerrit.display(getToken(), new NotFoundScreen());
-      return;
-    }
-
-    ChangeList wip = result.get(0);
-    ChangeList out = result.get(1);
-    ChangeList in = result.get(2);
-    ChangeList done = result.get(3);
-
-    if (mine) {
-      setWindowTitle(Util.C.myDashboardTitle());
-      setPageTitle(Util.C.myDashboardTitle());
-    } else {
-      // The server doesn't tell us who the dashboard is for. Try to guess
-      // by looking at a change started by the owner and extract the name.
-      String name = guessName(out);
-      if (name == null) {
-        name = guessName(done);
-      }
-      if (name != null) {
-        setWindowTitle(name);
-        setPageTitle(Util.M.accountDashboardTitle(name));
-      } else {
-        setWindowTitle(Util.C.unknownDashboardTitle());
-        setWindowTitle(Util.C.unknownDashboardTitle());
-      }
-    }
-
-    Natives.asList(out).sort(outComparator());
-
-    table.updateColumnsForLabels(wip, out, in, done);
-    workInProgress.display(wip);
-    outgoing.display(out);
-    incoming.display(in);
-    closed.display(done);
-    table.finishDisplay();
-  }
-
-  private Comparator<ChangeInfo> outComparator() {
-    return comparing(ChangeInfo::created).thenComparing(ChangeInfo::_number);
-  }
-
-  private boolean hasChanges(JsArray<ChangeList> result) {
-    for (ChangeList list : Natives.asList(result)) {
-      if (list.length() != 0) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  private static String guessName(ChangeList list) {
-    for (ChangeInfo change : Natives.asList(list)) {
-      if (change.owner() != null && change.owner().name() != null) {
-        return change.owner().name();
-      }
-    }
-    return null;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeApi.java
deleted file mode 100644
index 02be8c7..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeApi.java
+++ /dev/null
@@ -1,401 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.ChangeInfo.CommitInfo;
-import com.google.gerrit.client.info.ChangeInfo.EditInfo;
-import com.google.gerrit.client.info.ChangeInfo.IncludedInInfo;
-import com.google.gerrit.client.rpc.CallbackGroup.Callback;
-import com.google.gerrit.client.rpc.NativeString;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-/** A collection of static methods which work on the Gerrit REST API for specific changes. */
-public class ChangeApi {
-  /** Abandon the change, ending its review. */
-  public static void abandon(
-      @Nullable String project, int id, String msg, AsyncCallback<ChangeInfo> cb) {
-    MessageInput input = MessageInput.create();
-    input.message(emptyToNull(msg));
-    call(project, id, "abandon").post(input, cb);
-  }
-
-  /** Create a new work-in-progress change. */
-  public static void createChange(
-      String project,
-      String branch,
-      String topic,
-      String subject,
-      String base,
-      AsyncCallback<ChangeInfo> cb) {
-    CreateChangeInput input = CreateChangeInput.create();
-    input.project(emptyToNull(project));
-    input.branch(emptyToNull(branch));
-    input.topic(emptyToNull(topic));
-    input.subject(emptyToNull(subject));
-    input.baseChange(emptyToNull(base));
-    input.workInProgress(true);
-
-    new RestApi("/changes/").post(input, cb);
-  }
-
-  /** Restore a previously abandoned change to be open again. */
-  public static void restore(
-      @Nullable String project, int id, String msg, AsyncCallback<ChangeInfo> cb) {
-    MessageInput input = MessageInput.create();
-    input.message(emptyToNull(msg));
-    call(project, id, "restore").post(input, cb);
-  }
-
-  /** Create a new change that reverts the delta caused by this change. */
-  public static void revert(
-      @Nullable String project, int id, String msg, AsyncCallback<ChangeInfo> cb) {
-    MessageInput input = MessageInput.create();
-    input.message(emptyToNull(msg));
-    call(project, id, "revert").post(input, cb);
-  }
-
-  /** Update the topic of a change. */
-  public static void topic(
-      @Nullable String project, int id, String topic, AsyncCallback<String> cb) {
-    RestApi call = call(project, id, "topic");
-    topic = emptyToNull(topic);
-    if (topic != null) {
-      TopicInput input = TopicInput.create();
-      input.topic(topic);
-      call.put(input, NativeString.unwrap(cb));
-    } else {
-      call.delete(NativeString.unwrap(cb));
-    }
-  }
-
-  public static void detail(@Nullable String project, int id, AsyncCallback<ChangeInfo> cb) {
-    detail(project, id).get(cb);
-  }
-
-  public static RestApi detail(@Nullable String project, int id) {
-    return call(project, id, "detail");
-  }
-
-  public static RestApi blame(@Nullable String project, PatchSet.Id id, String path, boolean base) {
-    return revision(project, id).view("files").id(path).view("blame").addParameter("base", base);
-  }
-
-  public static RestApi actions(@Nullable String project, int id, String revision) {
-    if (revision == null || revision.equals("")) {
-      revision = "current";
-    }
-    return call(project, id, revision, "actions");
-  }
-
-  public static void deleteAssignee(
-      @Nullable String project, int id, AsyncCallback<AccountInfo> cb) {
-    change(project, id).view("assignee").delete(cb);
-  }
-
-  public static void setAssignee(
-      @Nullable String project, int id, String user, AsyncCallback<AccountInfo> cb) {
-    AssigneeInput input = AssigneeInput.create();
-    input.assignee(user);
-    change(project, id).view("assignee").put(input, cb);
-  }
-
-  public static void markPrivate(
-      @Nullable String project, int id, AsyncCallback<JavaScriptObject> cb) {
-    change(project, id).view("private").post(PrivateInput.create(), cb);
-  }
-
-  public static void unmarkPrivate(
-      @Nullable String project, int id, AsyncCallback<JavaScriptObject> cb) {
-    change(project, id).view("private.delete").post(PrivateInput.create(), cb);
-  }
-
-  public static RestApi comments(@Nullable String project, int id) {
-    return call(project, id, "comments");
-  }
-
-  public static RestApi drafts(@Nullable String project, int id) {
-    return call(project, id, "drafts");
-  }
-
-  public static void edit(@Nullable String project, int id, AsyncCallback<EditInfo> cb) {
-    edit(project, id).get(cb);
-  }
-
-  public static void editWithFiles(@Nullable String project, int id, AsyncCallback<EditInfo> cb) {
-    edit(project, id).addParameterTrue("list").get(cb);
-  }
-
-  public static RestApi edit(@Nullable String project, int id) {
-    return change(project, id).view("edit");
-  }
-
-  public static RestApi editWithCommands(@Nullable String project, int id) {
-    return edit(project, id).addParameterTrue("download-commands");
-  }
-
-  public static void includedIn(
-      @Nullable String project, int id, AsyncCallback<IncludedInInfo> cb) {
-    call(project, id, "in").get(cb);
-  }
-
-  public static RestApi revision(@Nullable String project, int id, String revision) {
-    return change(project, id).view("revisions").id(revision);
-  }
-
-  public static RestApi revision(@Nullable String project, PatchSet.Id id) {
-    int cn = id.getParentKey().get();
-    String revision = RevisionInfoCache.get(id);
-    if (revision != null) {
-      return revision(project, cn, revision);
-    }
-    return change(project, cn).view("revisions").id(id.get());
-  }
-
-  public static RestApi reviewers(@Nullable String project, int id) {
-    return change(project, id).view("reviewers");
-  }
-
-  public static RestApi suggestReviewers(
-      @Nullable String project, int id, String q, int n, boolean e) {
-    RestApi api =
-        change(project, id).view("suggest_reviewers").addParameter("n", n).addParameter("e", e);
-    if (q != null) {
-      api.addParameter("q", q);
-    }
-    return api;
-  }
-
-  public static RestApi vote(@Nullable String project, int id, int reviewer, String vote) {
-    return reviewer(project, id, reviewer).view("votes").id(vote);
-  }
-
-  public static RestApi reviewer(@Nullable String project, int id, int reviewer) {
-    return change(project, id).view("reviewers").id(reviewer);
-  }
-
-  public static RestApi reviewer(@Nullable String project, int id, String reviewer) {
-    return change(project, id).view("reviewers").id(reviewer);
-  }
-
-  public static RestApi hashtags(@Nullable String project, int changeId) {
-    return change(project, changeId).view("hashtags");
-  }
-
-  public static RestApi hashtag(@Nullable String project, int changeId, String hashtag) {
-    return change(project, changeId).view("hashtags").id(hashtag);
-  }
-
-  /** Submit a specific revision of a change. */
-  public static void cherrypick(
-      String project,
-      int id,
-      String commit,
-      String destination,
-      String message,
-      AsyncCallback<ChangeInfo> cb) {
-    CherryPickInput cherryPickInput = CherryPickInput.create();
-    cherryPickInput.setMessage(message);
-    cherryPickInput.setDestination(destination);
-    call(project, id, commit, "cherrypick").post(cherryPickInput, cb);
-  }
-
-  /** Move change to another branch. */
-  public static void move(
-      String project, int id, String destination, String message, AsyncCallback<ChangeInfo> cb) {
-    MoveInput moveInput = MoveInput.create();
-    moveInput.setMessage(message);
-    moveInput.setDestinationBranch(destination);
-    change(project, id).view("move").post(moveInput, cb);
-  }
-
-  /** Edit commit message for specific revision of a change. */
-  public static void message(
-      @Nullable String project,
-      int id,
-      String commit,
-      String message,
-      AsyncCallback<JavaScriptObject> cb) {
-    CherryPickInput input = CherryPickInput.create();
-    input.setMessage(message);
-    call(project, id, commit, "message").post(input, cb);
-  }
-
-  /** Submit a specific revision of a change. */
-  public static void submit(
-      @Nullable String project, int id, String commit, AsyncCallback<SubmitInfo> cb) {
-    JavaScriptObject in = JavaScriptObject.createObject();
-    call(project, id, commit, "submit").post(in, cb);
-  }
-
-  /** Delete a specific draft change. */
-  public static void deleteChange(
-      @Nullable String project, int id, AsyncCallback<JavaScriptObject> cb) {
-    change(project, id).delete(cb);
-  }
-
-  /** Delete change edit. */
-  public static void deleteEdit(
-      @Nullable String project, int id, AsyncCallback<JavaScriptObject> cb) {
-    edit(project, id).delete(cb);
-  }
-
-  /** Publish change edit. */
-  public static void publishEdit(
-      @Nullable String project, int id, AsyncCallback<JavaScriptObject> cb) {
-    JavaScriptObject in = JavaScriptObject.createObject();
-    change(project, id).view("edit:publish").post(in, cb);
-  }
-
-  /** Rebase change edit on latest patch set. */
-  public static void rebaseEdit(
-      @Nullable String project, int id, AsyncCallback<JavaScriptObject> cb) {
-    JavaScriptObject in = JavaScriptObject.createObject();
-    change(project, id).view("edit:rebase").post(in, cb);
-  }
-
-  /** Rebase a revision onto the branch tip or another change. */
-  public static void rebase(
-      @Nullable String project, int id, String commit, String base, AsyncCallback<ChangeInfo> cb) {
-    RebaseInput rebaseInput = RebaseInput.create();
-    rebaseInput.setBase(base);
-    call(project, id, commit, "rebase").post(rebaseInput, cb);
-  }
-
-  private static class MessageInput extends JavaScriptObject {
-    final native void message(String m) /*-{ if(m)this.message=m; }-*/;
-
-    static MessageInput create() {
-      return (MessageInput) createObject();
-    }
-
-    protected MessageInput() {}
-  }
-
-  private static class AssigneeInput extends JavaScriptObject {
-    final native void assignee(String a) /*-{ if(a)this.assignee=a; }-*/;
-
-    static AssigneeInput create() {
-      return (AssigneeInput) createObject();
-    }
-
-    protected AssigneeInput() {}
-  }
-
-  private static class TopicInput extends JavaScriptObject {
-    final native void topic(String t) /*-{ if(t)this.topic=t; }-*/;
-
-    static TopicInput create() {
-      return (TopicInput) createObject();
-    }
-
-    protected TopicInput() {}
-  }
-
-  private static class CreateChangeInput extends JavaScriptObject {
-    static CreateChangeInput create() {
-      return (CreateChangeInput) createObject();
-    }
-
-    public final native void branch(String b) /*-{ if(b)this.branch=b; }-*/;
-
-    public final native void topic(String t) /*-{ if(t)this.topic=t; }-*/;
-
-    public final native void project(String p) /*-{ if(p)this.project=p; }-*/;
-
-    public final native void subject(String s) /*-{ if(s)this.subject=s; }-*/;
-
-    public final native void status(String s) /*-{ if(s)this.status=s; }-*/;
-
-    public final native void baseChange(String b) /*-{ if(b)this.base_change=b; }-*/;
-
-    public final native void workInProgress(Boolean b) /*-{ if(b)this.work_in_progress=b; }-*/;
-
-    protected CreateChangeInput() {}
-  }
-
-  private static class CherryPickInput extends JavaScriptObject {
-    static CherryPickInput create() {
-      return (CherryPickInput) createObject();
-    }
-
-    final native void setDestination(String d) /*-{ this.destination = d; }-*/;
-
-    final native void setMessage(String m) /*-{ this.message = m; }-*/;
-
-    protected CherryPickInput() {}
-  }
-
-  private static class MoveInput extends JavaScriptObject {
-    static MoveInput create() {
-      return (MoveInput) createObject();
-    }
-
-    final native void setDestinationBranch(String d) /*-{ this.destination_branch = d; }-*/;
-
-    final native void setMessage(String m) /*-{ this.message = m; }-*/;
-
-    protected MoveInput() {}
-  }
-
-  private static class PrivateInput extends JavaScriptObject {
-    static PrivateInput create() {
-      return (PrivateInput) createObject();
-    }
-
-    final native void setMessage(String m) /*-{ this.message = m; }-*/;
-
-    protected PrivateInput() {}
-  }
-
-  private static class RebaseInput extends JavaScriptObject {
-    final native void setBase(String b) /*-{ this.base = b; }-*/;
-
-    static RebaseInput create() {
-      return (RebaseInput) createObject();
-    }
-
-    protected RebaseInput() {}
-  }
-
-  private static RestApi call(@Nullable String project, int id, String action) {
-    return change(project, id).view(action);
-  }
-
-  private static RestApi call(@Nullable String project, int id, String commit, String action) {
-    return change(project, id).view("revisions").id(commit).view(action);
-  }
-
-  public static RestApi change(@Nullable String project, int id) {
-    if (project == null) {
-      return new RestApi("/changes/").id(String.valueOf(id));
-    }
-    return new RestApi("/changes/").id(project, id);
-  }
-
-  public static String emptyToNull(String str) {
-    return str == null || str.isEmpty() ? null : str;
-  }
-
-  public static void commitWithLinks(
-      @Nullable String project, int changeId, String revision, Callback<CommitInfo> callback) {
-    revision(project, changeId, revision).view("commit").addParameterTrue("links").get(callback);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
deleted file mode 100644
index aa6c4ec..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-import com.google.gwt.i18n.client.Constants;
-
-public interface ChangeConstants extends Constants {
-  String statusLongNew();
-
-  String statusLongMerged();
-
-  String statusLongAbandoned();
-
-  String statusLongDraft();
-
-  String submittable();
-
-  String readyToSubmit();
-
-  String mergeConflict();
-
-  String notCurrent();
-
-  String isPrivate();
-
-  String isWorkInProgress();
-
-  String changeEdit();
-
-  String myDashboardTitle();
-
-  String unknownDashboardTitle();
-
-  String workInProgress();
-
-  String incomingReviews();
-
-  String outgoingReviews();
-
-  String recentlyClosed();
-
-  String changeTableColumnSubject();
-
-  String changeTableColumnSize();
-
-  String changeTableColumnStatus();
-
-  String changeTableColumnOwner();
-
-  String changeTableColumnAssignee();
-
-  String changeTableColumnProject();
-
-  String changeTableColumnBranch();
-
-  String changeTableColumnLastUpdate();
-
-  String changeTableColumnID();
-
-  String changeTableNone();
-
-  String changeTableNotMergeable();
-
-  String changeItemHelp();
-
-  String changeTableStar();
-
-  String changeTablePagePrev();
-
-  String changeTablePageNext();
-
-  String upToChangeList();
-
-  String keyReloadChange();
-
-  String keyNextPatchSet();
-
-  String keyPreviousPatchSet();
-
-  String keyReloadSearch();
-
-  String keyPublishComments();
-
-  String keyEditTopic();
-
-  String keyAddReviewers();
-
-  String keyExpandAllMessages();
-
-  String keyCollapseAllMessages();
-
-  String patchTableColumnName();
-
-  String patchTableColumnComments();
-
-  String patchTableColumnSize();
-
-  String commitMessage();
-
-  String mergeList();
-
-  String patchTablePrev();
-
-  String patchTableNext();
-
-  String patchTableOpenDiff();
-
-  String approvalTableEditAssigneeHint();
-
-  String approvalTableAddReviewerHint();
-
-  String approvalTableAddManyReviewersConfirmationDialogTitle();
-
-  String changeInfoBlockUploaded();
-
-  String changeInfoBlockUpdated();
-
-  String messageNoAuthor();
-
-  String sideBySide();
-
-  String unifiedDiff();
-
-  String buttonRevertChangeSend();
-
-  String headingRevertMessage();
-
-  String revertChangeTitle();
-
-  String buttonCherryPickChangeSend();
-
-  String headingCherryPickBranch();
-
-  String cherryPickCommitMessage();
-
-  String cherryPickTitle();
-
-  String moveChangeSend();
-
-  String headingMoveBranch();
-
-  String moveChangeMessage();
-
-  String moveTitle();
-
-  String buttonRebaseChangeSend();
-
-  String rebaseConfirmMessage();
-
-  String rebaseNotPossibleMessage();
-
-  String rebasePlaceholderMessage();
-
-  String rebaseTitle();
-
-  String baseDiffItem();
-
-  String autoMerge();
-
-  String pagedChangeListPrev();
-
-  String pagedChangeListNext();
-
-  String submitFailed();
-
-  String votable();
-
-  String pushCertMissing();
-
-  String pushCertBad();
-
-  String pushCertOk();
-
-  String pushCertTrusted();
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
deleted file mode 100644
index 2d5a9f9..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
+++ /dev/null
@@ -1,103 +0,0 @@
-statusLongNew = Review in Progress
-statusLongMerged = Merged
-statusLongAbandoned = Abandoned
-statusLongDraft = Draft
-submittable = Submittable
-readyToSubmit = Ready to Submit
-mergeConflict = Merge Conflict
-notCurrent = Not Current
-changeEdit = Change Edit
-isPrivate = (Private)
-isWorkInProgress = (Work in Progress)
-
-myDashboardTitle = My Reviews
-unknownDashboardTitle = Code Review Dashboard
-workInProgress Work in progress
-incomingReviews = Incoming reviews
-outgoingReviews = Outgoing reviews
-recentlyClosed = Recently closed
-
-changeTableColumnSubject = Subject
-changeTableColumnSize = Size
-changeTableColumnStatus = Status
-changeTableColumnOwner = Owner
-changeTableColumnAssignee = Assignee
-changeTableColumnProject = Project
-changeTableColumnBranch = Branch
-changeTableColumnLastUpdate = Updated
-changeTableColumnID = ID
-changeTableNone = (None)
-changeTableNotMergeable = Merge Conflict
-
-changeItemHelp = change
-changeTableStar = Star (or unstar) change
-changeTablePagePrev = Previous page of changes
-changeTablePageNext = Next page of changes
-upToChangeList = Up to change list
-keyReloadChange = Reload change
-keyNextPatchSet = Next patch set
-keyPreviousPatchSet = Previous patch set
-keyReloadSearch = Reload change list
-keyPublishComments = Review and publish comments
-keyEditTopic = Edit change topic
-keyAddReviewers = Add reviewers
-keyExpandAllMessages = Expand all messages
-keyCollapseAllMessages = Collapse all messages
-
-patchTableColumnName = File Path
-patchTableColumnComments = Comments
-patchTableColumnSize = Size
-commitMessage = Commit Message
-mergeList = Merge List
-
-patchTablePrev = Previous file
-patchTableNext = Next file
-patchTableOpenDiff = Open diff
-
-approvalTableEditAssigneeHint = Name or Email
-
-approvalTableAddReviewerHint = Name or Email or Group
-approvalTableAddManyReviewersConfirmationDialogTitle = Adding Group Members as Reviewers
-
-changeInfoBlockUploaded = Uploaded
-changeInfoBlockUpdated = Updated
-
-messageNoAuthor = Gerrit Code Review
-
-sideBySide = Side by Side
-unifiedDiff = Unified Diff
-
-baseDiffItem = Base
-autoMerge = Auto Merge
-
-buttonRevertChangeSend = Revert Change
-headingRevertMessage = Revert Commit Message:
-revertChangeTitle = Code Review - Revert Merged Change
-
-buttonCherryPickChangeSend = Cherry Pick Change
-headingCherryPickBranch = Cherry Pick to Branch:
-cherryPickCommitMessage = Cherry Pick Commit Message:
-cherryPickTitle = Code Review - Cherry Pick Change to Another Branch
-
-headingMoveBranch = Move Change to Branch:
-moveChangeSend = Move Change
-moveChangeMessage = Move Change Message:
-moveTitle = Code Review - Move Change to Another Branch
-
-buttonRebaseChangeSend = Rebase
-rebaseConfirmMessage = Change parent revision
-rebaseNotPossibleMessage = Change is already up to date
-rebasePlaceholderMessage = (subject, change number, or leave empty)
-rebaseTitle = Code Review - Rebase Change
-
-pagedChangeListPrev = &#x21e6;Prev
-pagedChangeListNext = Next&#x21e8;
-
-submitFailed = Submit Failed
-
-votable = Votable:
-
-pushCertMissing = This patch set was created without a push certificate
-pushCertBad = Push certificate is invalid
-pushCertOk = Push certificate is valid, but key is not trusted
-pushCertTrusted = Push certificate is valid and key is trusted
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeEditApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeEditApi.java
deleted file mode 100644
index 71b54f7d..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeEditApi.java
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-import com.google.gerrit.client.VoidResult;
-import com.google.gerrit.client.editor.EditFileInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.HttpCallback;
-import com.google.gerrit.client.rpc.NativeString;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.reviewdb.client.Patch;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-/** REST API helpers to remotely edit a change. */
-public class ChangeEditApi {
-  /** Get file (or commit message) contents. */
-  public static void get(
-      @Nullable Project.NameKey project,
-      PatchSet.Id id,
-      String path,
-      boolean base,
-      HttpCallback<NativeString> cb) {
-    RestApi api;
-    if (id.get() != 0) {
-      // Read from a published revision, when change edit doesn't
-      // exist for the caller, or is not currently active.
-      api =
-          ChangeApi.revision(Project.NameKey.asStringOrNull(project), id)
-              .view("files")
-              .id(path)
-              .view("content");
-    } else if (Patch.COMMIT_MSG.equals(path)) {
-      api =
-          editMessage(Project.NameKey.asStringOrNull(project), id.getParentKey().get())
-              .addParameter("base", base);
-    } else {
-      api =
-          editFile(Project.NameKey.asStringOrNull(project), id.getParentKey().get(), path)
-              .addParameter("base", base);
-    }
-    api.get(cb);
-  }
-
-  /** Get file (or commit message) contents of the edit. */
-  public static void get(
-      @Nullable Project.NameKey project,
-      PatchSet.Id id,
-      String path,
-      HttpCallback<NativeString> cb) {
-    get(project, id, path, false, cb);
-  }
-
-  /** Get meta info for change edit. */
-  public static void getMeta(
-      @Nullable String project, PatchSet.Id id, String path, AsyncCallback<EditFileInfo> cb) {
-    if (id.get() != 0) {
-      throw new IllegalStateException("only supported for edits");
-    }
-    editFile(project, id.getParentKey().get(), path).view("meta").get(cb);
-  }
-
-  /** Put message into a change edit. */
-  public static void putMessage(
-      @Nullable String project, int id, String m, GerritCallback<VoidResult> cb) {
-    editMessage(project, id).put(m, cb);
-  }
-
-  /** Put contents into a file or commit message in a change edit. */
-  public static void put(
-      @Nullable String project,
-      int id,
-      String path,
-      String content,
-      GerritCallback<VoidResult> cb) {
-    if (Patch.COMMIT_MSG.equals(path)) {
-      putMessage(project, id, content, cb);
-    } else {
-      editFile(project, id, path).put(content, cb);
-    }
-  }
-
-  /** Delete a file in the pending edit. */
-  public static void delete(
-      @Nullable String project, int id, String path, AsyncCallback<VoidResult> cb) {
-    editFile(project, id, path).delete(cb);
-  }
-
-  /** Rename a file in the pending edit. */
-  public static void rename(
-      @Nullable String project, int id, String path, String newPath, AsyncCallback<VoidResult> cb) {
-    Input in = Input.create();
-    in.oldPath(path);
-    in.newPath(newPath);
-    ChangeApi.edit(project, id).post(in, cb);
-  }
-
-  /** Restore (undo delete/modify) a file in the pending edit. */
-  public static void restore(
-      @Nullable String project, int id, String path, AsyncCallback<VoidResult> cb) {
-    Input in = Input.create();
-    in.restorePath(path);
-    ChangeApi.edit(project, id).post(in, cb);
-  }
-
-  private static RestApi editMessage(@Nullable String project, int id) {
-    return ChangeApi.change(project, id).view("edit:message");
-  }
-
-  private static RestApi editFile(@Nullable String project, int id, String path) {
-    return ChangeApi.edit(project, id).id(path);
-  }
-
-  private static class Input extends JavaScriptObject {
-    static Input create() {
-      return createObject().cast();
-    }
-
-    final native void restorePath(String p) /*-{ this.restore_path=p }-*/;
-
-    final native void oldPath(String p) /*-{ this.old_path=p }-*/;
-
-    final native void newPath(String p) /*-{ this.new_path=p }-*/;
-
-    protected Input() {}
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeList.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeList.java
deleted file mode 100644
index 5d525b6..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeList.java
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.extensions.client.ListChangesOption;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtorm.client.KeyUtil;
-import java.util.Set;
-
-/** List of changes available from {@code /changes/}. */
-public class ChangeList extends JsArray<ChangeInfo> {
-  private static final String URI = "/changes/";
-
-  /** Run multiple queries in a single remote invocation. */
-  public static void queryMultiple(
-      final AsyncCallback<JsArray<ChangeList>> callback,
-      Set<ListChangesOption> options,
-      String... queries) {
-    if (queries.length == 0) {
-      return;
-    }
-    RestApi call = new RestApi(URI);
-    for (String q : queries) {
-      call.addParameterRaw("q", KeyUtil.encode(q));
-    }
-    addOptions(call, options);
-    if (queries.length == 1) {
-      // Server unwraps a single query, so wrap it back in an array for the
-      // callback.
-      call.get(
-          new AsyncCallback<ChangeList>() {
-            @Override
-            public void onSuccess(ChangeList result) {
-              JsArray<ChangeList> wrapped = JsArray.createArray(1).cast();
-              wrapped.set(0, result);
-              callback.onSuccess(wrapped);
-            }
-
-            @Override
-            public void onFailure(Throwable caught) {
-              callback.onFailure(caught);
-            }
-          });
-    } else {
-      call.get(callback);
-    }
-  }
-
-  public static void query(
-      String query, Set<ListChangesOption> options, AsyncCallback<ChangeList> callback) {
-    query(query, options, callback, 0, 0);
-  }
-
-  public static void query(
-      String query,
-      Set<ListChangesOption> options,
-      AsyncCallback<ChangeList> callback,
-      int start,
-      int limit) {
-    RestApi call = newQuery(query);
-    if (limit > 0) {
-      call.addParameter("n", limit);
-    }
-    addOptions(call, options);
-    if (start != 0) {
-      call.addParameter("S", start);
-    }
-    call.get(callback);
-  }
-
-  public static void addOptions(RestApi call, Set<ListChangesOption> s) {
-    call.addParameterRaw("O", Integer.toHexString(ListChangesOption.toBits(s)));
-  }
-
-  private static RestApi newQuery(String query) {
-    RestApi call = new RestApi(URI);
-    // The server default is ?q=status:open so don't repeat it.
-    if (!"status:open".equals(query) && !"is:open".equals(query)) {
-      call.addParameterRaw("q", KeyUtil.encode(query));
-    }
-    return call;
-  }
-
-  protected ChangeList() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeListScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeListScreen.java
deleted file mode 100644
index ed5a6f2..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeListScreen.java
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-public interface ChangeListScreen {}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeMessages.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeMessages.java
deleted file mode 100644
index c64fe91..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeMessages.java
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-import com.google.gwt.i18n.client.Messages;
-
-public interface ChangeMessages extends Messages {
-  String accountDashboardTitle(String fullName);
-
-  String revertChangeDefaultMessage(String commitMsg, String commitId);
-
-  String cherryPickedChangeDefaultMessage(String commitMsg, String commitId);
-
-  String changeScreenTitleId(String changeId);
-
-  String loadingPatchSet(int id);
-
-  String patchTableSize_Modify(int insertions, int deletions);
-
-  String patchTableSize_ModifyBinaryFiles(String bytesInserted, String bytesDeleted);
-
-  String patchTableSize_ModifyBinaryFilesWithPercentages(
-      String bytesInserted,
-      String percentageInserted,
-      String bytesDeleted,
-      String percentageDeleted);
-
-  String patchTableSize_LongModify(int insertions, int deletions);
-
-  String removeReviewer(String fullName);
-
-  String removeVote(String label);
-
-  String blockedOn(String labelName);
-
-  String needs(String labelName);
-
-  String changeQueryWindowTitle(String query);
-
-  String changeQueryPageTitle(String query);
-
-  String insertionsAndDeletions(int insertions, int deletions);
-
-  String diffBaseParent(int parentNum);
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeMessages.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeMessages.properties
deleted file mode 100644
index 2b68492..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeMessages.properties
+++ /dev/null
@@ -1,27 +0,0 @@
-# Changes to this file should also be made in
-# gerrit-server/src/main/resources/com/google/gerrit/server/change/ChangeMessages.properties
-accountDashboardTitle = Code Review Dashboard for {0}
-
-revertChangeDefaultMessage = Revert \"{0}\"\n\nThis reverts commit {1}.
-cherryPickedChangeDefaultMessage = {0}\n(cherry picked from commit {1})
-
-changeScreenTitleId = Change {0}
-loadingPatchSet = Loading Patch Set {0} ...
-
-patchTableSize_Modify = +{0}, -{1}
-patchTableSize_ModifyBinaryFiles = +{0}, -{1}
-patchTableSize_ModifyBinaryFilesWithPercentages = +{0} (+{1}), -{2} (-{3})
-patchTableSize_LongModify = {0} inserted, {1} deleted
-
-removeReviewer = Remove reviewer {0}
-removeVote = Remove vote {0}
-
-blockedOn = Blocked on {0} Label
-needs = Needs {0} Label
-
-changeQueryWindowTitle = {0}
-changeQueryPageTitle = Search for {0}
-
-insertionsAndDeletions = +{0}, -{1}
-
-diffBaseParent = Parent {0}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java
deleted file mode 100644
index 4fda78b..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java
+++ /dev/null
@@ -1,558 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-import static com.google.gerrit.client.FormatUtil.relativeFormat;
-import static com.google.gerrit.client.FormatUtil.shortFormat;
-import static java.util.stream.Collectors.toList;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.ChangeInfo.LabelInfo;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.AccountLinkPanel;
-import com.google.gerrit.client.ui.BranchLink;
-import com.google.gerrit.client.ui.ChangeLink;
-import com.google.gerrit.client.ui.NavigationTable;
-import com.google.gerrit.client.ui.NeedsSignInKeyCommand;
-import com.google.gerrit.client.ui.ProjectLink;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.ReviewCategoryStrategy;
-import com.google.gerrit.extensions.client.ListChangesOption;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HTMLTable.Cell;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.InlineLabel;
-import com.google.gwt.user.client.ui.SimplePanel;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwt.user.client.ui.Widget;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-
-public class ChangeTable extends NavigationTable<ChangeInfo> {
-  // If changing default options, also update in
-  // ChangeIT#defaultSearchDoesNotTouchDatabase().
-  static final Set<ListChangesOption> OPTIONS =
-      Collections.unmodifiableSet(
-          EnumSet.of(ListChangesOption.LABELS, ListChangesOption.DETAILED_ACCOUNTS));
-
-  private static final int C_STAR = 1;
-  private static final int C_ID = 2;
-  private static final int C_SUBJECT = 3;
-  private static final int C_STATUS = 4;
-  private static final int C_OWNER = 5;
-  private static final int C_ASSIGNEE = 6;
-  private static final int C_PROJECT = 7;
-  private static final int C_BRANCH = 8;
-  private static final int C_LAST_UPDATE = 9;
-  private static final int C_SIZE = 10;
-  private static final int BASE_COLUMNS = 11;
-
-  private final List<Section> sections;
-  private int columns;
-  private final boolean showAssignee;
-  private final boolean showLegacyId;
-  private List<String> labelNames;
-
-  public ChangeTable() {
-    super(Util.C.changeItemHelp());
-    columns = BASE_COLUMNS;
-    labelNames = Collections.emptyList();
-    showAssignee = Gerrit.info().change().showAssigneeInChangesTable();
-    showLegacyId = Gerrit.getUserPreferences().legacycidInChangeTable();
-
-    if (Gerrit.isSignedIn()) {
-      keysAction.add(new StarKeyCommand(0, 's', Util.C.changeTableStar()));
-    }
-
-    sections = new ArrayList<>();
-    table.setText(0, C_STAR, "");
-    table.setText(0, C_ID, Util.C.changeTableColumnID());
-    table.setText(0, C_SUBJECT, Util.C.changeTableColumnSubject());
-    table.setText(0, C_STATUS, Util.C.changeTableColumnStatus());
-    table.setText(0, C_OWNER, Util.C.changeTableColumnOwner());
-    table.setText(0, C_ASSIGNEE, Util.C.changeTableColumnAssignee());
-    table.setText(0, C_PROJECT, Util.C.changeTableColumnProject());
-    table.setText(0, C_BRANCH, Util.C.changeTableColumnBranch());
-    table.setText(0, C_LAST_UPDATE, Util.C.changeTableColumnLastUpdate());
-    table.setText(0, C_SIZE, Util.C.changeTableColumnSize());
-
-    final FlexCellFormatter fmt = table.getFlexCellFormatter();
-    fmt.addStyleName(0, C_STAR, Gerrit.RESOURCES.css().iconHeader());
-    for (int i = C_ID; i < columns; i++) {
-      fmt.addStyleName(0, i, Gerrit.RESOURCES.css().dataHeader());
-    }
-    if (!showLegacyId) {
-      fmt.addStyleName(0, C_ID, Gerrit.RESOURCES.css().dataHeaderHidden());
-    }
-    if (!showAssignee) {
-      fmt.addStyleName(0, C_ASSIGNEE, Gerrit.RESOURCES.css().dataHeaderHidden());
-    }
-
-    table.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            final Cell cell = table.getCellForEvent(event);
-            if (cell == null) {
-              return;
-            }
-            if (cell.getCellIndex() == C_STAR) {
-              // Don't do anything (handled by star itself).
-            } else if (cell.getCellIndex() == C_STATUS) {
-              // Don't do anything.
-            } else if (cell.getCellIndex() == C_OWNER) {
-              // Don't do anything.
-            } else if (getRowItem(cell.getRowIndex()) != null) {
-              movePointerTo(cell.getRowIndex());
-            }
-          }
-        });
-  }
-
-  @Override
-  protected Object getRowItemKey(ChangeInfo item) {
-    return item.legacyId();
-  }
-
-  @Override
-  protected void onOpenRow(int row) {
-    final ChangeInfo c = getRowItem(row);
-    Gerrit.display(PageLinks.toChange(c.projectNameKey(), c.legacyId()));
-  }
-
-  private void insertNoneRow(int row) {
-    insertRow(row);
-    table.setText(row, 0, Util.C.changeTableNone());
-    final FlexCellFormatter fmt = table.getFlexCellFormatter();
-    fmt.setColSpan(row, 0, columns);
-    fmt.setStyleName(row, 0, Gerrit.RESOURCES.css().emptySection());
-  }
-
-  private void insertChangeRow(int row) {
-    insertRow(row);
-    applyDataRowStyle(row);
-  }
-
-  @Override
-  protected void applyDataRowStyle(int row) {
-    super.applyDataRowStyle(row);
-    final CellFormatter fmt = table.getCellFormatter();
-    fmt.addStyleName(row, C_STAR, Gerrit.RESOURCES.css().iconCell());
-    for (int i = C_ID; i < columns; i++) {
-      fmt.addStyleName(row, i, Gerrit.RESOURCES.css().dataCell());
-    }
-    if (!showLegacyId) {
-      fmt.addStyleName(row, C_ID, Gerrit.RESOURCES.css().dataCellHidden());
-    }
-    fmt.addStyleName(row, C_SUBJECT, Gerrit.RESOURCES.css().cSUBJECT());
-    fmt.addStyleName(row, C_STATUS, Gerrit.RESOURCES.css().cSTATUS());
-    fmt.addStyleName(row, C_OWNER, Gerrit.RESOURCES.css().cOWNER());
-    fmt.addStyleName(
-        row,
-        C_ASSIGNEE,
-        showAssignee
-            ? Gerrit.RESOURCES.css().cASSIGNEE()
-            : Gerrit.RESOURCES.css().dataCellHidden());
-    fmt.addStyleName(row, C_LAST_UPDATE, Gerrit.RESOURCES.css().cLastUpdate());
-    fmt.addStyleName(row, C_SIZE, Gerrit.RESOURCES.css().cSIZE());
-
-    for (int i = C_SIZE + 1; i < columns; i++) {
-      fmt.addStyleName(row, i, Gerrit.RESOURCES.css().cAPPROVAL());
-    }
-  }
-
-  public void updateColumnsForLabels(ChangeList... lists) {
-    labelNames =
-        Arrays.stream(lists)
-            .flatMap(l -> Natives.asList(l).stream())
-            .flatMap(c -> c.labels().stream())
-            .distinct()
-            .sorted()
-            .collect(toList());
-
-    int baseColumns = BASE_COLUMNS;
-    if (baseColumns + labelNames.size() < columns) {
-      int n = columns - (baseColumns + labelNames.size());
-      for (int row = 0; row < table.getRowCount(); row++) {
-        table.removeCells(row, columns, n);
-      }
-    }
-    columns = baseColumns + labelNames.size();
-
-    FlexCellFormatter fmt = table.getFlexCellFormatter();
-    for (int i = 0; i < labelNames.size(); i++) {
-      String name = labelNames.get(i);
-      int col = baseColumns + i;
-
-      String abbrev = getAbbreviation(name, "-");
-      table.setText(0, col, abbrev);
-      table.getCellFormatter().getElement(0, col).setTitle(name);
-      fmt.addStyleName(0, col, Gerrit.RESOURCES.css().dataHeader());
-    }
-
-    for (Section s : sections) {
-      if (s.titleRow >= 0) {
-        fmt.setColSpan(s.titleRow, 0, columns);
-      }
-    }
-  }
-
-  private void populateChangeRow(int row, ChangeInfo c, boolean highlightUnreviewed) {
-    CellFormatter fmt = table.getCellFormatter();
-    if (Gerrit.isSignedIn()) {
-      table.setWidget(row, C_STAR, StarredChanges.createIcon(c.legacyId(), c.starred()));
-    }
-    table.setWidget(row, C_ID, new TableChangeLink(String.valueOf(c.legacyId()), c));
-
-    String subject = Util.cropSubject(c.subject());
-    table.setWidget(row, C_SUBJECT, new TableChangeLink(subject, c));
-
-    Change.Status status = c.status();
-    if (status != Change.Status.NEW) {
-      table.setText(
-          row,
-          C_STATUS,
-          Util.toLongString(status) + (c.isPrivate() ? (" " + Util.C.isPrivate()) : ""));
-    } else if (c.isWorkInProgress()) {
-      table.setText(
-          row,
-          C_STATUS,
-          Util.C.workInProgress() + (c.isPrivate() ? (" " + Util.C.isPrivate()) : ""));
-    } else if (!c.mergeable()) {
-      table.setText(
-          row,
-          C_STATUS,
-          Util.C.changeTableNotMergeable() + (c.isPrivate() ? (" " + Util.C.isPrivate()) : ""));
-    } else if (c.isPrivate()) {
-      table.setText(row, C_STATUS, Util.C.isPrivate());
-    }
-
-    if (c.owner() != null) {
-      table.setWidget(row, C_OWNER, AccountLinkPanel.withStatus(c.owner(), status));
-    } else {
-      table.setText(row, C_OWNER, "");
-    }
-
-    if (showAssignee) {
-      if (c.assignee() != null) {
-        table.setWidget(row, C_ASSIGNEE, AccountLinkPanel.forAssignee(c.assignee()));
-        if (Gerrit.getUserPreferences().highlightAssigneeInChangeTable()
-            && Objects.equals(c.assignee()._accountId(), Gerrit.getUserAccount()._accountId())) {
-          table.getRowFormatter().addStyleName(row, Gerrit.RESOURCES.css().cASSIGNEDTOME());
-        }
-      } else {
-        table.setText(row, C_ASSIGNEE, "");
-      }
-    }
-
-    table.setWidget(row, C_PROJECT, new ProjectLink(c.projectNameKey()));
-    table.setWidget(
-        row, C_BRANCH, new BranchLink(c.projectNameKey(), c.status(), c.branch(), c.topic()));
-    if (Gerrit.getUserPreferences().relativeDateInChangeTable()) {
-      table.setText(row, C_LAST_UPDATE, relativeFormat(c.updated()));
-    } else {
-      table.setText(row, C_LAST_UPDATE, shortFormat(c.updated()));
-    }
-
-    int col = C_SIZE;
-    if (!Gerrit.getUserPreferences().sizeBarInChangeTable()) {
-      table.setText(row, col, Util.M.insertionsAndDeletions(c.insertions(), c.deletions()));
-    } else {
-      table.setWidget(row, col, getSizeWidget(c));
-      fmt.getElement(row, col)
-          .setTitle(Util.M.insertionsAndDeletions(c.insertions(), c.deletions()));
-    }
-    col++;
-
-    for (int idx = 0; idx < labelNames.size(); idx++, col++) {
-      String name = labelNames.get(idx);
-
-      LabelInfo label = c.label(name);
-      if (label == null) {
-        fmt.getElement(row, col).setTitle(Gerrit.C.labelNotApplicable());
-        fmt.addStyleName(row, col, Gerrit.RESOURCES.css().labelNotApplicable());
-        continue;
-      }
-
-      String user;
-      String info;
-      ReviewCategoryStrategy reviewCategoryStrategy =
-          Gerrit.getUserPreferences().reviewCategoryStrategy();
-      if (label.rejected() != null) {
-        user = label.rejected().name();
-        info = getReviewCategoryDisplayInfo(reviewCategoryStrategy, label.rejected());
-        if (info != null) {
-          FlowPanel panel = new FlowPanel();
-          panel.add(new Image(Gerrit.RESOURCES.redNot()));
-          panel.add(new InlineLabel(info));
-          table.setWidget(row, col, panel);
-        } else {
-          table.setWidget(row, col, new Image(Gerrit.RESOURCES.redNot()));
-        }
-      } else if (label.approved() != null) {
-        user = label.approved().name();
-        info = getReviewCategoryDisplayInfo(reviewCategoryStrategy, label.approved());
-        if (info != null) {
-          FlowPanel panel = new FlowPanel();
-          panel.add(new Image(Gerrit.RESOURCES.greenCheck()));
-          panel.add(new InlineLabel(info));
-          table.setWidget(row, col, panel);
-        } else {
-          table.setWidget(row, col, new Image(Gerrit.RESOURCES.greenCheck()));
-        }
-      } else if (label.disliked() != null) {
-        user = label.disliked().name();
-        info = getReviewCategoryDisplayInfo(reviewCategoryStrategy, label.disliked());
-        String vstr = String.valueOf(label._value());
-        if (info != null) {
-          vstr = vstr + " " + info;
-        }
-        fmt.addStyleName(row, col, Gerrit.RESOURCES.css().negscore());
-        table.setText(row, col, vstr);
-      } else if (label.recommended() != null) {
-        user = label.recommended().name();
-        info = getReviewCategoryDisplayInfo(reviewCategoryStrategy, label.recommended());
-        String vstr = "+" + label._value();
-        if (info != null) {
-          vstr = vstr + " " + info;
-        }
-        fmt.addStyleName(row, col, Gerrit.RESOURCES.css().posscore());
-        table.setText(row, col, vstr);
-      } else {
-        table.clearCell(row, col);
-        continue;
-      }
-      fmt.addStyleName(row, col, Gerrit.RESOURCES.css().singleLine());
-
-      if (user != null) {
-        // Some web browsers ignore the embedded newline; some like it;
-        // so we include a space before the newline to accommodate both.
-        fmt.getElement(row, col).setTitle(name + " \nby " + user);
-      }
-    }
-
-    boolean needHighlight = false;
-    if (highlightUnreviewed && !c.reviewed()) {
-      needHighlight = true;
-    }
-    final Element tr = fmt.getElement(row, 0).getParentElement();
-    UIObject.setStyleName(tr, Gerrit.RESOURCES.css().needsReview(), needHighlight);
-
-    setRowItem(row, c);
-  }
-
-  private static String getReviewCategoryDisplayInfo(
-      ReviewCategoryStrategy reviewCategoryStrategy, AccountInfo accountInfo) {
-    switch (reviewCategoryStrategy) {
-      case NAME:
-        return accountInfo.name();
-      case EMAIL:
-        return accountInfo.email();
-      case USERNAME:
-        return accountInfo.username();
-      case ABBREV:
-        return getAbbreviation(accountInfo.name(), " ");
-      case NONE:
-      default:
-        return null;
-    }
-  }
-
-  private static String getAbbreviation(String name, String token) {
-    StringBuilder abbrev = new StringBuilder();
-    if (name != null) {
-      for (String t : name.split(token)) {
-        abbrev.append(t.substring(0, 1).toUpperCase());
-      }
-    }
-    return abbrev.toString();
-  }
-
-  private static Widget getSizeWidget(ChangeInfo c) {
-    int largeChangeSize = Gerrit.info().change().largeChange();
-    int changedLines = c.insertions() + c.deletions();
-    int p = 100;
-    if (changedLines < largeChangeSize) {
-      p = changedLines * 100 / largeChangeSize;
-    }
-
-    int width = Math.max(2, 70 * p / 100);
-    int red = p >= 50 ? 255 : (int) Math.round((p) * 5.12);
-    int green = p <= 50 ? 255 : (int) Math.round(256 - (p - 50) * 5.12);
-    String bg = "#" + toHex(red) + toHex(green) + "00";
-
-    SimplePanel panel = new SimplePanel();
-    panel.setStyleName(Gerrit.RESOURCES.css().changeSize());
-    panel.setWidth(width + "px");
-    panel.getElement().getStyle().setBackgroundColor(bg);
-    return panel;
-  }
-
-  private static String toHex(int i) {
-    String hex = Integer.toHexString(i);
-    return hex.length() == 1 ? "0" + hex : hex;
-  }
-
-  public void addSection(Section s) {
-    assert s.parent == null;
-
-    s.parent = this;
-    s.titleRow = table.getRowCount();
-    if (s.displayTitle()) {
-      final FlexCellFormatter fmt = table.getFlexCellFormatter();
-      fmt.setColSpan(s.titleRow, 0, columns);
-      fmt.addStyleName(s.titleRow, 0, Gerrit.RESOURCES.css().sectionHeader());
-    } else {
-      s.titleRow = -1;
-    }
-
-    s.dataBegin = table.getRowCount();
-    insertNoneRow(s.dataBegin);
-    sections.add(s);
-  }
-
-  private int insertRow(int beforeRow) {
-    for (Section s : sections) {
-      if (beforeRow <= s.titleRow) {
-        s.titleRow++;
-      }
-      if (beforeRow < s.dataBegin) {
-        s.dataBegin++;
-      }
-    }
-    return table.insertRow(beforeRow);
-  }
-
-  private void removeRow(int row) {
-    for (Section s : sections) {
-      if (row < s.titleRow) {
-        s.titleRow--;
-      }
-      if (row < s.dataBegin) {
-        s.dataBegin--;
-      }
-    }
-    table.removeRow(row);
-  }
-
-  public class StarKeyCommand extends NeedsSignInKeyCommand {
-    public StarKeyCommand(int mask, char key, String help) {
-      super(mask, key, help);
-    }
-
-    @Override
-    public void onKeyPress(KeyPressEvent event) {
-      int row = getCurrentRow();
-      ChangeInfo c = getRowItem(row);
-      if (c != null && Gerrit.isSignedIn()) {
-        ((StarredChanges.Icon) table.getWidget(row, C_STAR)).toggleStar();
-      }
-    }
-  }
-
-  private final class TableChangeLink extends ChangeLink {
-    private TableChangeLink(String text, ChangeInfo c) {
-      super(c.projectNameKey(), c.legacyId(), text);
-    }
-
-    @Override
-    public void go() {
-      movePointerTo(cid);
-      super.go();
-    }
-  }
-
-  public static class Section {
-    ChangeTable parent;
-    String titleText;
-    Widget titleWidget;
-    int titleRow = -1;
-    int dataBegin;
-    int rows;
-    private boolean highlightUnreviewed;
-
-    public void setHighlightUnreviewed(boolean value) {
-      this.highlightUnreviewed = value;
-    }
-
-    public void setTitleText(String text) {
-      titleText = text;
-      titleWidget = null;
-      if (titleRow >= 0) {
-        parent.table.setText(titleRow, 0, titleText);
-      }
-    }
-
-    public void setTitleWidget(Widget title) {
-      titleWidget = title;
-      titleText = null;
-      if (titleRow >= 0) {
-        parent.table.setWidget(titleRow, 0, title);
-      }
-    }
-
-    public boolean displayTitle() {
-      if (titleText != null) {
-        setTitleText(titleText);
-        return true;
-      } else if (titleWidget != null) {
-        setTitleWidget(titleWidget);
-        return true;
-      }
-      return false;
-    }
-
-    public void display(ChangeList changeList) {
-      final int sz = changeList != null ? changeList.length() : 0;
-      final boolean hadData = rows > 0;
-
-      if (hadData) {
-        while (sz < rows) {
-          parent.removeRow(dataBegin);
-          rows--;
-        }
-      } else {
-        parent.removeRow(dataBegin);
-      }
-
-      if (sz == 0) {
-        parent.insertNoneRow(dataBegin);
-        return;
-      }
-
-      while (rows < sz) {
-        parent.insertChangeRow(dataBegin + rows);
-        rows++;
-      }
-      for (int i = 0; i < sz; i++) {
-        parent.populateChangeRow(dataBegin + i, changeList.get(i), highlightUnreviewed);
-      }
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommentApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommentApi.java
deleted file mode 100644
index 987b382..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommentApi.java
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-public class CommentApi {
-
-  public static void comments(
-      @Nullable String project, PatchSet.Id id, AsyncCallback<NativeMap<JsArray<CommentInfo>>> cb) {
-    revision(project, id, "comments").get(cb);
-  }
-
-  public static void comment(
-      @Nullable String project, PatchSet.Id id, String commentId, AsyncCallback<CommentInfo> cb) {
-    revision(project, id, "comments").id(commentId).get(cb);
-  }
-
-  public static void drafts(
-      @Nullable String project, PatchSet.Id id, AsyncCallback<NativeMap<JsArray<CommentInfo>>> cb) {
-    revision(project, id, "drafts").get(cb);
-  }
-
-  public static void draft(
-      @Nullable String project, PatchSet.Id id, String draftId, AsyncCallback<CommentInfo> cb) {
-    revision(project, id, "drafts").id(draftId).get(cb);
-  }
-
-  public static void createDraft(
-      @Nullable String project,
-      PatchSet.Id id,
-      CommentInfo content,
-      AsyncCallback<CommentInfo> cb) {
-    revision(project, id, "drafts").put(content, cb);
-  }
-
-  public static void updateDraft(
-      @Nullable String project,
-      PatchSet.Id id,
-      String draftId,
-      CommentInfo content,
-      AsyncCallback<CommentInfo> cb) {
-    revision(project, id, "drafts").id(draftId).put(content, cb);
-  }
-
-  public static void deleteDraft(
-      @Nullable String project,
-      PatchSet.Id id,
-      String draftId,
-      AsyncCallback<JavaScriptObject> cb) {
-    revision(project, id, "drafts").id(draftId).delete(cb);
-  }
-
-  private static RestApi revision(@Nullable String project, PatchSet.Id id, String type) {
-    return ChangeApi.revision(project, id).view(type);
-  }
-
-  private CommentApi() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommentInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommentInfo.java
deleted file mode 100644
index a111860..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommentInfo.java
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-import com.google.gerrit.client.diff.CommentRange;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.extensions.client.Side;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwtjsonrpc.client.impl.ser.JavaSqlTimestamp_JsonSerializer;
-import java.sql.Timestamp;
-
-public class CommentInfo extends JavaScriptObject {
-  public static CommentInfo create(
-      String path, Side side, int line, CommentRange range, Boolean unresolved) {
-    return create(path, side, 0, line, range, unresolved);
-  }
-
-  public static CommentInfo create(
-      String path, Side side, int parent, int line, CommentRange range, boolean unresolved) {
-    CommentInfo n = createObject().cast();
-    n.path(path);
-    n.side(side);
-    n.parent(parent);
-    if (range != null) {
-      n.line(range.endLine());
-      n.range(range);
-    } else if (line > 0) {
-      n.line(line);
-    }
-    n.unresolved(unresolved);
-    return n;
-  }
-
-  public static CommentInfo createReply(CommentInfo r) {
-    CommentInfo n = createObject().cast();
-    n.path(r.path());
-    n.side(r.side());
-    n.parent(r.parent());
-    n.inReplyTo(r.id());
-    if (r.hasRange()) {
-      n.line(r.range().endLine());
-      n.range(r.range());
-    } else if (r.hasLine()) {
-      n.line(r.line());
-    }
-    n.unresolved(r.unresolved());
-    return n;
-  }
-
-  public static CommentInfo copy(CommentInfo s) {
-    CommentInfo n = createObject().cast();
-    n.path(s.path());
-    n.side(s.side());
-    n.parent(s.parent());
-    n.id(s.id());
-    n.inReplyTo(s.inReplyTo());
-    n.message(s.message());
-    if (s.hasRange()) {
-      n.line(s.range().endLine());
-      n.range(s.range());
-    } else if (s.hasLine()) {
-      n.line(s.line());
-    }
-    n.unresolved(s.unresolved());
-    return n;
-  }
-
-  public final native void path(String p) /*-{ this.path = p }-*/;
-
-  public final native void id(String i) /*-{ this.id = i }-*/;
-
-  public final native void line(int n) /*-{ this.line = n }-*/;
-
-  public final native void range(CommentRange r) /*-{ this.range = r }-*/;
-
-  public final native void inReplyTo(String i) /*-{ this.in_reply_to = i }-*/;
-
-  public final native void message(String m) /*-{ this.message = m }-*/;
-
-  public final native void unresolved(boolean b) /*-{ this.unresolved = b }-*/;
-
-  public final void side(Side side) {
-    sideRaw(side.toString());
-  }
-
-  private native void sideRaw(String s) /*-{ this.side = s }-*/;
-
-  public final native void parent(int n) /*-{ this.parent = n }-*/;
-
-  public final native boolean hasParent() /*-{ return this.hasOwnProperty('parent') }-*/;
-
-  public final native String path() /*-{ return this.path }-*/;
-
-  public final native String id() /*-{ return this.id }-*/;
-
-  public final native String inReplyTo() /*-{ return this.in_reply_to }-*/;
-
-  public final native int patchSet() /*-{ return this.patch_set }-*/;
-
-  public final native boolean unresolved() /*-{ return this.unresolved }-*/;
-
-  public final Side side() {
-    String s = sideRaw();
-    return s != null ? Side.valueOf(s) : Side.REVISION;
-  }
-
-  private native String sideRaw() /*-{ return this.side }-*/;
-
-  public final native int parent() /*-{ return this.parent }-*/;
-
-  public final Timestamp updated() {
-    Timestamp r = updatedTimestamp();
-    if (r == null) {
-      String s = updatedRaw();
-      if (s != null) {
-        r = JavaSqlTimestamp_JsonSerializer.parseTimestamp(s);
-        updatedTimestamp(r);
-      }
-    }
-    return r;
-  }
-
-  private native String updatedRaw() /*-{ return this.updated }-*/;
-
-  private native Timestamp updatedTimestamp() /*-{ return this._ts }-*/;
-
-  private native void updatedTimestamp(Timestamp t) /*-{ this._ts = t }-*/;
-
-  public final native AccountInfo author() /*-{ return this.author }-*/;
-
-  public final native int line() /*-{ return this.line || 0 }-*/;
-
-  public final native boolean hasLine() /*-{ return this.hasOwnProperty('line') }-*/;
-
-  public final native boolean hasRange() /*-{ return this.hasOwnProperty('range') }-*/;
-
-  public final native CommentRange range() /*-{ return this.range }-*/;
-
-  public final native String message() /*-{ return this.message }-*/;
-
-  protected CommentInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CustomDashboardScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CustomDashboardScreen.java
deleted file mode 100644
index 802e56c..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CustomDashboardScreen.java
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-import com.google.gerrit.client.ui.Screen;
-
-public class CustomDashboardScreen extends Screen implements ChangeListScreen {
-  private DashboardTable table;
-  private String params;
-
-  public CustomDashboardScreen(String params) {
-    this.params = params;
-  }
-
-  @Override
-  protected void onInitUI() {
-    table =
-        new DashboardTable(this, params) {
-          @Override
-          public void finishDisplay() {
-            super.finishDisplay();
-            display();
-          }
-        };
-
-    super.onInitUI();
-
-    String title = table.getTitle();
-    if (title != null) {
-      setWindowTitle(title);
-      setPageTitle(title);
-    }
-
-    add(table);
-  }
-
-  @Override
-  public void registerKeys() {
-    super.registerKeys();
-    table.setRegisterKeys(true);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DashboardTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DashboardTable.java
deleted file mode 100644
index aba4ee0..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DashboardTable.java
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.InlineHyperlink;
-import com.google.gerrit.client.ui.Screen;
-import com.google.gerrit.common.PageLinks;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.http.client.URL;
-import com.google.gwtexpui.globalkey.client.KeyCommand;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.ListIterator;
-
-public class DashboardTable extends ChangeTable {
-  private List<Section> sections;
-  private String title;
-  private List<String> titles;
-  private List<String> queries;
-
-  public DashboardTable(Screen screen, String params) {
-    titles = new ArrayList<>();
-    queries = new ArrayList<>();
-    String foreach = null;
-    for (String kvPair : params.split("[,;&]")) {
-      String[] kv = kvPair.split("=", 2);
-      if (kv.length != 2 || kv[0].isEmpty()) {
-        continue;
-      }
-
-      if ("title".equals(kv[0])) {
-        title = URL.decodeQueryString(kv[1]);
-      } else if ("foreach".equals(kv[0])) {
-        foreach = URL.decodeQueryString(kv[1]);
-      } else {
-        titles.add(URL.decodeQueryString(kv[0]));
-        queries.add(URL.decodeQueryString(kv[1]));
-      }
-    }
-
-    if (foreach != null) {
-      ListIterator<String> it = queries.listIterator();
-      while (it.hasNext()) {
-        it.set(it.next() + " " + foreach);
-      }
-    }
-
-    addStyleName(Gerrit.RESOURCES.css().accountDashboard());
-
-    sections = new ArrayList<>();
-    int i = 0;
-    for (String title : titles) {
-      Section s = new Section();
-      String query = removeLimitAndAge(queries.get(i++));
-      s.setTitleWidget(new InlineHyperlink(title, PageLinks.toChangeQuery(query)));
-      addSection(s);
-      sections.add(s);
-    }
-
-    keysNavigation.add(
-        new KeyCommand(0, 'R', Util.C.keyReloadSearch()) {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            Gerrit.display(screen.getToken());
-          }
-        });
-  }
-
-  private String removeLimitAndAge(String query) {
-    StringBuilder unlimitedQuery = new StringBuilder();
-    String[] operators = query.split(" ");
-    for (String o : operators) {
-      if (!o.startsWith("limit:") && !o.startsWith("age:") && !o.startsWith("-age:")) {
-        unlimitedQuery.append(o).append(" ");
-      }
-    }
-    return unlimitedQuery.toString().trim();
-  }
-
-  @Override
-  public String getTitle() {
-    return title;
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    ChangeList.queryMultiple(
-        new GerritCallback<JsArray<ChangeList>>() {
-          @Override
-          public void onSuccess(JsArray<ChangeList> result) {
-            List<ChangeList> cls = Natives.asList(result);
-            updateColumnsForLabels(cls.toArray(new ChangeList[cls.size()]));
-            for (int i = 0; i < cls.size(); i++) {
-              sections.get(i).display(cls.get(i));
-            }
-            finishDisplay();
-          }
-        },
-        OPTIONS,
-        queries.toArray(new String[queries.size()]));
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PagedSingleListScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PagedSingleListScreen.java
deleted file mode 100644
index 1695eb9..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PagedSingleListScreen.java
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gerrit.client.ui.Hyperlink;
-import com.google.gerrit.client.ui.Screen;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.user.client.History;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwtexpui.globalkey.client.KeyCommand;
-
-public abstract class PagedSingleListScreen extends Screen {
-  protected final int pageSize;
-  protected final int start;
-  private final String anchorPrefix;
-
-  protected ChangeList changes;
-  private ChangeTable table;
-  private ChangeTable.Section section;
-  private Hyperlink prev;
-  private Hyperlink next;
-
-  protected PagedSingleListScreen(String anchorToken, int start) {
-    anchorPrefix = anchorToken;
-    this.start = start;
-    pageSize = Gerrit.getUserPreferences().changesPerPage();
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    prev = new Hyperlink(Util.C.pagedChangeListPrev(), true, "");
-    prev.setVisible(false);
-
-    next = new Hyperlink(Util.C.pagedChangeListNext(), true, "");
-    next.setVisible(false);
-
-    table =
-        new ChangeTable() {
-          {
-            keysNavigation.add(
-                new DoLinkCommand(0, 'p', Util.C.changeTablePagePrev(), prev),
-                new DoLinkCommand(0, 'n', Util.C.changeTablePageNext(), next));
-
-            keysNavigation.add(
-                new DoLinkCommand(0, '[', Util.C.changeTablePagePrev(), prev),
-                new DoLinkCommand(0, ']', Util.C.changeTablePageNext(), next));
-
-            keysNavigation.add(
-                new KeyCommand(0, 'R', Util.C.keyReloadSearch()) {
-                  @Override
-                  public void onKeyPress(KeyPressEvent event) {
-                    Gerrit.display(getToken());
-                  }
-                });
-          }
-        };
-    section = new ChangeTable.Section();
-    table.addSection(section);
-    table.setSavePointerId(anchorPrefix);
-    add(table);
-
-    final HorizontalPanel buttons = new HorizontalPanel();
-    buttons.setStyleName(Gerrit.RESOURCES.css().changeTablePrevNextLinks());
-    buttons.add(prev);
-    buttons.add(next);
-    add(buttons);
-  }
-
-  @Override
-  public void registerKeys() {
-    super.registerKeys();
-    table.setRegisterKeys(true);
-  }
-
-  protected AsyncCallback<ChangeList> loadCallback() {
-    return new ScreenLoadCallback<ChangeList>(this) {
-      @Override
-      protected void preDisplay(ChangeList result) {
-        display(result);
-      }
-    };
-  }
-
-  protected void display(ChangeList result) {
-    changes = result;
-    if (changes.length() != 0) {
-      if (start > 0) {
-        int p = start - pageSize;
-        prev.setTargetHistoryToken(anchorPrefix + (p > 0 ? "," + p : ""));
-        prev.setVisible(true);
-      } else {
-        prev.setVisible(false);
-      }
-
-      int n = start + changes.length();
-      next.setTargetHistoryToken(anchorPrefix + "," + n);
-      next.setVisible(changes.get(changes.length() - 1)._more_changes());
-    }
-    table.updateColumnsForLabels(result);
-    section.display(result);
-    table.finishDisplay();
-  }
-
-  private static final class DoLinkCommand extends KeyCommand {
-    private final Hyperlink link;
-
-    private DoLinkCommand(int mask, char key, String help, Hyperlink l) {
-      super(mask, key, help);
-      link = l;
-    }
-
-    @Override
-    public void onKeyPress(KeyPressEvent event) {
-      if (link.isVisible()) {
-        History.newItem(link.getTargetHistoryToken());
-      }
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ProjectDashboardScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ProjectDashboardScreen.java
deleted file mode 100644
index f511308..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ProjectDashboardScreen.java
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.admin.ProjectScreen;
-import com.google.gerrit.client.ui.InlineHyperlink;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.user.client.ui.FlowPanel;
-
-public class ProjectDashboardScreen extends ProjectScreen implements ChangeListScreen {
-  private DashboardTable table;
-  private String params;
-
-  public ProjectDashboardScreen(Project.NameKey toShow, String params) {
-    super(toShow);
-    this.params = params;
-  }
-
-  @Override
-  protected void onInitUI() {
-    table =
-        new DashboardTable(this, params) {
-          @Override
-          public void finishDisplay() {
-            super.finishDisplay();
-            display();
-          }
-        };
-
-    super.onInitUI();
-
-    String title = table.getTitle();
-    if (title != null) {
-      FlowPanel fp = new FlowPanel();
-      fp.setStyleName(Gerrit.RESOURCES.css().screenHeader());
-      fp.add(new InlineHyperlink(title, PageLinks.toCustomDashboard(params)));
-      add(fp);
-    }
-
-    add(table);
-  }
-
-  @Override
-  public void registerKeys() {
-    super.registerKeys();
-    table.setRegisterKeys(true);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/QueryScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/QueryScreen.java
deleted file mode 100644
index 8d580a3..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/QueryScreen.java
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.RevId;
-import com.google.gwt.regexp.shared.RegExp;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtorm.client.KeyUtil;
-
-public class QueryScreen extends PagedSingleListScreen implements ChangeListScreen {
-  // Legacy numeric identifier.
-  private static final RegExp NUMERIC_ID = RegExp.compile("^[1-9][0-9]*$");
-  // Commit SHA1 hash
-  private static final RegExp COMMIT_SHA1 = RegExp.compile("^([0-9a-fA-F]{4," + RevId.LEN + "})$");
-  // Change-Id
-  private static final String ID_PATTERN = "[iI][0-9a-f]{4,}$";
-  private static final RegExp CHANGE_ID = RegExp.compile("^" + ID_PATTERN);
-  private static final RegExp CHANGE_ID_TRIPLET = RegExp.compile("^(.)+~(.)+~" + ID_PATTERN);
-
-  public static QueryScreen forQuery(String query) {
-    return forQuery(query, 0);
-  }
-
-  public static QueryScreen forQuery(String query, int start) {
-    return new QueryScreen(KeyUtil.encode(query), start);
-  }
-
-  private final String query;
-
-  public QueryScreen(String encQuery, int start) {
-    super(PageLinks.QUERY + encQuery, start);
-    query = KeyUtil.decode(encQuery);
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    setWindowTitle(Util.M.changeQueryWindowTitle(query));
-    setPageTitle(Util.M.changeQueryPageTitle(query));
-  }
-
-  @Override
-  protected AsyncCallback<ChangeList> loadCallback() {
-    return new GerritCallback<ChangeList>() {
-      @Override
-      public void onSuccess(ChangeList result) {
-        if (isAttached()) {
-          if (result.length() == 1 && isSingleQuery(query)) {
-            ChangeInfo c = result.get(0);
-            Change.Id id = c.legacyId();
-            Gerrit.display(PageLinks.toChange(c.projectNameKey(), id));
-          } else {
-            display(result);
-            QueryScreen.this.display();
-          }
-        }
-      }
-    };
-  }
-
-  @Override
-  public void onShowView() {
-    super.onShowView();
-    Gerrit.setQueryString(query);
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    ChangeList.query(query, ChangeTable.OPTIONS, loadCallback(), start, pageSize);
-  }
-
-  private static boolean isSingleQuery(String query) {
-    return NUMERIC_ID.test(query)
-        || CHANGE_ID.test(query)
-        || CHANGE_ID_TRIPLET.test(query)
-        || COMMIT_SHA1.test(query);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ReviewInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ReviewInfo.java
deleted file mode 100644
index 06d2484..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ReviewInfo.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class ReviewInfo extends JavaScriptObject {
-
-  public final native NativeMap<?> labels() /*-{ return this.labels }-*/;
-
-  protected ReviewInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ReviewInput.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ReviewInput.java
deleted file mode 100644
index f851d5e..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ReviewInput.java
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-
-public class ReviewInput extends JavaScriptObject {
-  public enum NotifyHandling {
-    NONE,
-    OWNER,
-    OWNER_REVIEWERS,
-    ALL
-  }
-
-  public enum DraftHandling {
-    DELETE,
-    PUBLISH,
-    KEEP,
-    PUBLISH_ALL_REVISIONS
-  }
-
-  public static ReviewInput create() {
-    ReviewInput r = createObject().cast();
-    r.init();
-    r.drafts(DraftHandling.PUBLISH);
-    return r;
-  }
-
-  public final native void message(String m) /*-{ if(m)this.message=m; }-*/;
-
-  public final native void label(String n, short v) /*-{ this.labels[n]=v; }-*/;
-
-  public final native void comments(NativeMap<JsArray<CommentInfo>> m) /*-{ this.comments=m }-*/;
-
-  public final void notify(NotifyHandling e) {
-    _notify(e.name());
-  }
-
-  private native void _notify(String n) /*-{ this.notify=n; }-*/;
-
-  public final void drafts(DraftHandling e) {
-    _drafts(e.name());
-  }
-
-  private native void _drafts(String n) /*-{ this.drafts=n; }-*/;
-
-  private native void init() /*-{
-    this.labels = {};
-  }-*/;
-
-  public final native void prePost() /*-{
-    var m=this.comments;
-    if (m) {
-      for (var p in m) {
-        var l=m[p];
-        for (var i=0;i<l.length;i++) {
-          var c=l[i];
-          delete c['path'];
-          delete c['updated'];
-        }
-      }
-    }
-  }-*/;
-
-  public final native void mergeLabels(ReviewInput o) /*-{
-    var l=o.labels;
-    if (l) {
-      for (var n in l)
-        this.labels[n]=l[n];
-    }
-  }-*/;
-
-  protected ReviewInput() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/RevisionInfoCache.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/RevisionInfoCache.java
deleted file mode 100644
index 0b83119..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/RevisionInfoCache.java
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-/** Cache of PatchSet.Id to revision SHA-1 strings. */
-public class RevisionInfoCache {
-  private static final int LIMIT = 10;
-  private static final RevisionInfoCache IMPL = new RevisionInfoCache();
-
-  public static void add(Change.Id change, RevisionInfo info) {
-    IMPL.psToCommit.put(new PatchSet.Id(change, info._number()), info.name());
-  }
-
-  static String get(PatchSet.Id id) {
-    return IMPL.psToCommit.get(id);
-  }
-
-  private final LinkedHashMap<PatchSet.Id, String> psToCommit;
-
-  @SuppressWarnings("serial")
-  private RevisionInfoCache() {
-    psToCommit =
-        new LinkedHashMap<PatchSet.Id, String>(LIMIT) {
-          @Override
-          protected boolean removeEldestEntry(Map.Entry<PatchSet.Id, String> e) {
-            return size() > LIMIT;
-          }
-        };
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/StarredChanges.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/StarredChanges.java
deleted file mode 100644
index b1028420..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/StarredChanges.java
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.account.AccountApi;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.resources.client.ImageResource;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwtexpui.globalkey.client.KeyCommand;
-import com.google.web.bindery.event.shared.Event;
-import com.google.web.bindery.event.shared.HandlerRegistration;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-/** Supports the star icon displayed on changes and tracking the status. */
-public class StarredChanges {
-  private static final Event.Type<ChangeStarHandler> TYPE = new Event.Type<>();
-
-  /** Handler that can receive notifications of a change's starred status. */
-  public interface ChangeStarHandler {
-    void onChangeStar(ChangeStarEvent event);
-  }
-
-  /** Event fired when a star changes status. The new status is reported. */
-  public static class ChangeStarEvent extends Event<ChangeStarHandler> {
-    private boolean starred;
-
-    public ChangeStarEvent(Change.Id source, boolean starred) {
-      setSource(source);
-      this.starred = starred;
-    }
-
-    public boolean isStarred() {
-      return starred;
-    }
-
-    @Override
-    public Type<ChangeStarHandler> getAssociatedType() {
-      return TYPE;
-    }
-
-    @Override
-    protected void dispatch(ChangeStarHandler handler) {
-      handler.onChangeStar(this);
-    }
-  }
-
-  /**
-   * Create a star icon for the given change, and current status. Returns null if the user is not
-   * signed in and cannot support starred changes.
-   */
-  public static Icon createIcon(Change.Id source, boolean starred) {
-    return Gerrit.isSignedIn() ? new Icon(source, starred) : null;
-  }
-
-  /** Make a key command that toggles the star for a change. */
-  public static KeyCommand newKeyCommand(Icon icon) {
-    return new KeyCommand(0, 's', Util.C.changeTableStar()) {
-      @Override
-      public void onKeyPress(KeyPressEvent event) {
-        icon.toggleStar();
-      }
-    };
-  }
-
-  /** Add a handler to listen for starred status to change. */
-  public static HandlerRegistration addHandler(Change.Id source, ChangeStarHandler handler) {
-    return Gerrit.EVENT_BUS.addHandlerToSource(TYPE, source, handler);
-  }
-
-  /**
-   * Broadcast the current starred value of a change to UI widgets. This does not RPC to the server
-   * and does not alter the starred status of a change.
-   */
-  public static void fireChangeStarEvent(Change.Id id, boolean starred) {
-    Gerrit.EVENT_BUS.fireEventFromSource(new ChangeStarEvent(id, starred), id);
-  }
-
-  /**
-   * Set the starred status of a change. This method broadcasts to all interested UI widgets and
-   * sends an RPC to the server to record the updated status.
-   */
-  public static void toggleStar(Change.Id changeId, boolean newValue) {
-    pending.put(changeId, newValue);
-    fireChangeStarEvent(changeId, newValue);
-    if (!busy) {
-      startRequest();
-    }
-  }
-
-  private static boolean busy;
-  private static final Map<Change.Id, Boolean> pending = new LinkedHashMap<>(4);
-
-  private static void startRequest() {
-    busy = true;
-
-    final Change.Id id = pending.keySet().iterator().next();
-    final boolean starred = pending.remove(id);
-    RestApi call = AccountApi.self().view("starred.changes").id(id.get());
-    AsyncCallback<JavaScriptObject> cb =
-        new AsyncCallback<JavaScriptObject>() {
-          @Override
-          public void onSuccess(JavaScriptObject none) {
-            if (pending.isEmpty()) {
-              busy = false;
-            } else {
-              startRequest();
-            }
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            if (!starred && RestApi.isStatus(caught, 404)) {
-              onSuccess(null);
-              return;
-            }
-
-            fireChangeStarEvent(id, !starred);
-            for (Map.Entry<Change.Id, Boolean> e : pending.entrySet()) {
-              fireChangeStarEvent(e.getKey(), !e.getValue());
-            }
-            pending.clear();
-            busy = false;
-          }
-        };
-    if (starred) {
-      call.put(cb);
-    } else {
-      call.delete(cb);
-    }
-  }
-
-  public static class Icon extends Image implements ChangeStarHandler, ClickHandler {
-    private final Change.Id changeId;
-    private boolean starred;
-    private HandlerRegistration handler;
-
-    Icon(Change.Id changeId, boolean starred) {
-      super(resource(starred));
-      this.changeId = changeId;
-      this.starred = starred;
-      addClickHandler(this);
-    }
-
-    /**
-     * Toggles the state of the star, as if the user clicked on the image. This will broadcast the
-     * new star status to all interested UI widgets, and RPC to the server to store the changed
-     * value.
-     */
-    public void toggleStar() {
-      StarredChanges.toggleStar(changeId, !starred);
-    }
-
-    @Override
-    protected void onLoad() {
-      handler = StarredChanges.addHandler(changeId, this);
-    }
-
-    @Override
-    protected void onUnload() {
-      handler.removeHandler();
-      handler = null;
-    }
-
-    @Override
-    public void onChangeStar(ChangeStarEvent event) {
-      setResource(resource(event.isStarred()));
-      starred = event.isStarred();
-    }
-
-    @Override
-    public void onClick(ClickEvent event) {
-      toggleStar();
-    }
-
-    private static ImageResource resource(boolean starred) {
-      return starred ? Gerrit.RESOURCES.starFilled() : Gerrit.RESOURCES.starOpen();
-    }
-  }
-
-  private StarredChanges() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/SubmitInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/SubmitInfo.java
deleted file mode 100644
index 9027c5b..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/SubmitInfo.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class SubmitInfo extends JavaScriptObject {
-  final Change.Status status() {
-    return Change.Status.valueOf(statusRaw());
-  }
-
-  private native String statusRaw() /*-{ return this.status; }-*/;
-
-  protected SubmitInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/Util.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/Util.java
deleted file mode 100644
index 8d949d1..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/Util.java
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gwt.core.client.GWT;
-
-public class Util {
-  public static final ChangeConstants C = GWT.create(ChangeConstants.class);
-  public static final ChangeMessages M = GWT.create(ChangeMessages.class);
-
-  private static final int SUBJECT_MAX_LENGTH = 80;
-  private static final String SUBJECT_CROP_APPENDIX = "...";
-  private static final int SUBJECT_CROP_RANGE = 10;
-
-  public static String toLongString(Change.Status status) {
-    if (status == null) {
-      return "";
-    }
-    switch (status) {
-      case NEW:
-        return C.statusLongNew();
-      case MERGED:
-        return C.statusLongMerged();
-      case ABANDONED:
-        return C.statusLongAbandoned();
-      default:
-        return status.name();
-    }
-  }
-
-  /**
-   * Crops the given change subject if needed so that it has at most {@link #SUBJECT_MAX_LENGTH}
-   * characters.
-   *
-   * <p>If the given subject is not longer than {@link #SUBJECT_MAX_LENGTH} characters it is
-   * returned unchanged.
-   *
-   * <p>If the length of the given subject exceeds {@link #SUBJECT_MAX_LENGTH} characters it is
-   * cropped. In this case {@link #SUBJECT_CROP_APPENDIX} is appended to the cropped subject, the
-   * cropped subject including the appendix has at most {@link #SUBJECT_MAX_LENGTH} characters.
-   *
-   * <p>If cropping is needed, the subject will be cropped after the last space character that is
-   * found within the last {@link #SUBJECT_CROP_RANGE} characters of the potentially visible
-   * characters. If no such space is found, the subject will be cropped so that the cropped subject
-   * including the appendix has exactly {@link #SUBJECT_MAX_LENGTH} characters.
-   *
-   * @return the subject, cropped if needed
-   */
-  @SuppressWarnings("deprecation")
-  public static String cropSubject(String subject) {
-    if (subject.length() > SUBJECT_MAX_LENGTH) {
-      final int maxLength = SUBJECT_MAX_LENGTH - SUBJECT_CROP_APPENDIX.length();
-      for (int cropPosition = maxLength;
-          cropPosition > maxLength - SUBJECT_CROP_RANGE;
-          cropPosition--) {
-        // Character.isWhitespace(char) can't be used because this method is not supported by GWT,
-        // see https://developers.google.com/web-toolkit/doc/1.6/RefJreEmulation#Package_java_lang
-        if (Character.isSpace(subject.charAt(cropPosition - 1))) {
-          return subject.substring(0, cropPosition) + SUBJECT_CROP_APPENDIX;
-        }
-      }
-      return subject.substring(0, maxLength) + SUBJECT_CROP_APPENDIX;
-    }
-    return subject;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/config/CapabilityInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/config/CapabilityInfo.java
deleted file mode 100644
index 1d7f4ab..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/config/CapabilityInfo.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.config;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class CapabilityInfo extends JavaScriptObject {
-  public final native String id() /*-{ return this.id; }-*/;
-
-  public final native String name() /*-{ return this.name; }-*/;
-
-  protected CapabilityInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/config/ConfigServerApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/config/ConfigServerApi.java
deleted file mode 100644
index e71929c..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/config/ConfigServerApi.java
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.config;
-
-import com.google.gerrit.client.VoidResult;
-import com.google.gerrit.client.info.GeneralPreferences;
-import com.google.gerrit.client.info.ServerInfo;
-import com.google.gerrit.client.info.TopMenuList;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-/** A collection of static methods which work on the Gerrit REST API for server configuration. */
-public class ConfigServerApi {
-  /** map of the server wide capabilities (core & plugins). */
-  public static void capabilities(AsyncCallback<NativeMap<CapabilityInfo>> cb) {
-    new RestApi("/config/server/capabilities/").get(cb);
-  }
-
-  public static void topMenus(AsyncCallback<TopMenuList> cb) {
-    new RestApi("/config/server/top-menus").get(cb);
-  }
-
-  public static void defaultPreferences(AsyncCallback<GeneralPreferences> cb) {
-    new RestApi("/config/server/preferences").get(cb);
-  }
-
-  public static void serverInfo(AsyncCallback<ServerInfo> cb) {
-    new RestApi("/config/server/info").get(cb);
-  }
-
-  public static void confirmEmail(String token, AsyncCallback<VoidResult> cb) {
-    EmailConfirmationInput input = EmailConfirmationInput.create();
-    input.setToken(token);
-    new RestApi("/config/server/email.confirm").put(input, cb);
-  }
-
-  private static class EmailConfirmationInput extends JavaScriptObject {
-    final native void setToken(String token) /*-{ this.token = token; }-*/;
-
-    static EmailConfirmationInput create() {
-      return createObject().cast();
-    }
-
-    protected EmailConfirmationInput() {}
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/DashboardConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/DashboardConstants.java
deleted file mode 100644
index ecb2938..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/DashboardConstants.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.dashboards;
-
-import com.google.gwt.i18n.client.Constants;
-
-public interface DashboardConstants extends Constants {
-  String dashboardName();
-
-  String dashboardTitle();
-
-  String dashboardDescription();
-
-  String dashboardInherited();
-
-  String dashboardItem();
-
-  String dashboardDefaultToolTip();
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/DashboardConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/DashboardConstants.properties
deleted file mode 100644
index ac4de7c..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/DashboardConstants.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-dashboardName = Dashboard Name
-dashboardTitle = Dashboard Title
-dashboardDescription = Dashboard Description
-dashboardInherited = Inherited From
-dashboardItem = dashboard
-dashboardDefaultToolTip = Project Default Dashboard
\ No newline at end of file
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/DashboardInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/DashboardInfo.java
deleted file mode 100644
index 5c6b51a..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/DashboardInfo.java
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.dashboards;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class DashboardInfo extends JavaScriptObject {
-  public final native String id() /*-{ return this.id; }-*/;
-
-  public final native String title() /*-{ return this.title; }-*/;
-
-  public final native String project() /*-{ return this.project; }-*/;
-
-  public final native String definingProject() /*-{ return this.defining_project; }-*/;
-
-  public final native String ref() /*-{ return this.ref; }-*/;
-
-  public final native String path() /*-{ return this.path; }-*/;
-
-  public final native String description() /*-{ return this.description; }-*/;
-
-  public final native String foreach() /*-{ return this.foreach; }-*/;
-
-  public final native String url() /*-{ return this.url; }-*/;
-
-  private final native boolean isDefaultLegacy() /*-{ return this['default'] ? true : false; }-*/;
-
-  private final native boolean isDefaultNew() /*-{ return this.is_default ? true : false; }-*/;
-
-  public final boolean isDefault() {
-    return isDefaultLegacy() || isDefaultNew();
-  }
-
-  protected DashboardInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/DashboardList.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/DashboardList.java
deleted file mode 100644
index 7ba3580..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/DashboardList.java
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.dashboards;
-
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.http.client.URL;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-/** Project dashboards from {@code /projects/<name>/dashboards/}. */
-public class DashboardList extends JsArray<DashboardInfo> {
-  public static void all(Project.NameKey project, AsyncCallback<JsArray<DashboardList>> callback) {
-    base(project).addParameterTrue("inherited").get(callback);
-  }
-
-  public static void getDefault(Project.NameKey project, AsyncCallback<DashboardInfo> callback) {
-    base(project).view("default").addParameterTrue("inherited").get(callback);
-  }
-
-  public static void get(
-      Project.NameKey project, String id, AsyncCallback<DashboardInfo> callback) {
-    base(project).idRaw(encodeDashboardId(id)).get(callback);
-  }
-
-  private static RestApi base(Project.NameKey project) {
-    return new RestApi("/projects/").id(project.get()).view("dashboards");
-  }
-
-  private static String encodeDashboardId(String id) {
-    int c = id.indexOf(':');
-    if (0 <= c) {
-      String ref = URL.encodeQueryString(id.substring(0, c));
-      String path = URL.encodeQueryString(id.substring(c + 1));
-      return ref + ':' + path;
-    }
-    return URL.encodeQueryString(id);
-  }
-
-  protected DashboardList() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/DashboardsTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/DashboardsTable.java
deleted file mode 100644
index dcb9c01..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/DashboardsTable.java
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.dashboards;
-
-import static java.util.Comparator.comparing;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.NavigationTable;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.user.client.History;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
-import com.google.gwt.user.client.ui.Image;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class DashboardsTable extends NavigationTable<DashboardInfo> {
-  Project.NameKey project;
-
-  public DashboardsTable(Project.NameKey project) {
-    super(Util.C.dashboardItem());
-    this.project = project;
-    initColumnHeaders();
-  }
-
-  protected void initColumnHeaders() {
-    final FlexCellFormatter fmt = table.getFlexCellFormatter();
-    fmt.setColSpan(0, 0, 2);
-    fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().dataHeader());
-    fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader());
-    fmt.addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader());
-    fmt.addStyleName(0, 4, Gerrit.RESOURCES.css().dataHeader());
-
-    table.setText(0, 1, Util.C.dashboardName());
-    table.setText(0, 2, Util.C.dashboardTitle());
-    table.setText(0, 3, Util.C.dashboardDescription());
-    table.setText(0, 4, Util.C.dashboardInherited());
-  }
-
-  public void display(DashboardList dashes) {
-    display(Natives.asList(dashes));
-  }
-
-  public void display(JsArray<DashboardList> in) {
-    Map<String, DashboardInfo> map = new HashMap<>();
-    for (DashboardList list : Natives.asList(in)) {
-      for (DashboardInfo d : Natives.asList(list)) {
-        if (!map.containsKey(d.id())) {
-          map.put(d.id(), d);
-        }
-      }
-    }
-    display(new ArrayList<>(map.values()));
-  }
-
-  public void display(List<DashboardInfo> list) {
-    while (1 < table.getRowCount()) {
-      table.removeRow(table.getRowCount() - 1);
-    }
-
-    list.sort(comparing(DashboardInfo::id));
-
-    String ref = null;
-    for (DashboardInfo d : list) {
-      if (!d.ref().equals(ref)) {
-        ref = d.ref();
-        insertTitleRow(table.getRowCount(), ref);
-      }
-      insert(table.getRowCount(), d);
-    }
-
-    finishDisplay();
-  }
-
-  protected void insertTitleRow(int row, String section) {
-    table.insertRow(row);
-
-    table.setText(row, 0, section);
-
-    final FlexCellFormatter fmt = table.getFlexCellFormatter();
-    fmt.setColSpan(row, 0, 6);
-    fmt.addStyleName(row, 0, Gerrit.RESOURCES.css().sectionHeader());
-  }
-
-  protected void insert(int row, DashboardInfo k) {
-    table.insertRow(row);
-
-    applyDataRowStyle(row);
-
-    final FlexCellFormatter fmt = table.getFlexCellFormatter();
-    fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().dataCell());
-    fmt.addStyleName(row, 2, Gerrit.RESOURCES.css().dataCell());
-    fmt.addStyleName(row, 3, Gerrit.RESOURCES.css().dataCell());
-    fmt.addStyleName(row, 4, Gerrit.RESOURCES.css().dataCell());
-    fmt.addStyleName(row, 5, Gerrit.RESOURCES.css().dataCell());
-
-    populate(row, k);
-  }
-
-  protected void populate(int row, DashboardInfo k) {
-    if (k.isDefault()) {
-      table.setWidget(row, 1, new Image(Gerrit.RESOURCES.greenCheck()));
-      final FlexCellFormatter fmt = table.getFlexCellFormatter();
-      fmt.getElement(row, 1).setTitle(Util.C.dashboardDefaultToolTip());
-    }
-    table.setWidget(
-        row,
-        2,
-        new Anchor(
-            k.path(),
-            "#" + PageLinks.toProjectDashboard(new Project.NameKey(k.project()), k.id())));
-    table.setText(row, 3, k.title() != null ? k.title() : k.path());
-    table.setText(row, 4, k.description());
-    if (k.definingProject() != null && !k.definingProject().equals(k.project())) {
-      table.setWidget(
-          row,
-          5,
-          new Anchor(
-              k.definingProject(),
-              "#" + PageLinks.toProjectDashboards(new Project.NameKey(k.definingProject()))));
-    }
-    setRowItem(row, k);
-  }
-
-  @Override
-  protected Object getRowItemKey(DashboardInfo item) {
-    return item.id();
-  }
-
-  @Override
-  protected void onOpenRow(int row) {
-    if (row > 0) {
-      movePointerTo(row);
-    }
-    History.newItem(getRowItem(row).url());
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/Util.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/Util.java
deleted file mode 100644
index b15bf73..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/dashboards/Util.java
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.dashboards;
-
-import com.google.gwt.core.client.GWT;
-
-public class Util {
-  public static final DashboardConstants C = GWT.create(DashboardConstants.class);
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/ChunkManager.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/ChunkManager.java
deleted file mode 100644
index 0091f53..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/ChunkManager.java
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import static com.google.gerrit.client.diff.DisplaySide.A;
-
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.dom.client.Element;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.List;
-import net.codemirror.lib.CodeMirror;
-import net.codemirror.lib.CodeMirror.LineClassWhere;
-import net.codemirror.lib.Pos;
-import net.codemirror.lib.TextMarker;
-
-/** Colors modified regions for {@link SideBySide} and {@link Unified}. */
-abstract class ChunkManager {
-  static final native void onClick(Element e, JavaScriptObject f) /*-{ e.onclick = f }-*/;
-
-  final Scrollbar scrollbar;
-  final LineMapper lineMapper;
-
-  private List<TextMarker> markers;
-  private List<Runnable> undo;
-
-  ChunkManager(Scrollbar scrollbar) {
-    this.scrollbar = scrollbar;
-    this.lineMapper = new LineMapper();
-  }
-
-  abstract DiffChunkInfo getFirst();
-
-  List<TextMarker> getMarkers() {
-    return markers;
-  }
-
-  void reset() {
-    lineMapper.reset();
-    for (TextMarker m : markers) {
-      m.clear();
-    }
-    for (Runnable r : undo) {
-      r.run();
-    }
-  }
-
-  abstract void render(DiffInfo diff);
-
-  void render() {
-    markers = new ArrayList<>();
-    undo = new ArrayList<>();
-  }
-
-  void colorLines(CodeMirror cm, String color, int line, int cnt) {
-    colorLines(cm, LineClassWhere.WRAP, color, line, line + cnt);
-  }
-
-  void colorLines(CodeMirror cm, LineClassWhere where, String className, int start, int end) {
-    if (start < end) {
-      for (int line = start; line < end; line++) {
-        cm.addLineClass(line, where, className);
-      }
-      undo.add(
-          () -> {
-            for (int line = start; line < end; line++) {
-              cm.removeLineClass(line, where, className);
-            }
-          });
-    }
-  }
-
-  abstract Runnable diffChunkNav(CodeMirror cm, Direction dir);
-
-  void diffChunkNavHelper(
-      List<? extends DiffChunkInfo> chunks, DiffScreen host, int res, Direction dir) {
-    if (res < 0) {
-      res = -res - (dir == Direction.PREV ? 1 : 2);
-    }
-    res = res + (dir == Direction.PREV ? -1 : 1);
-    if (res < 0 || chunks.size() <= res) {
-      return;
-    }
-
-    DiffChunkInfo lookUp = chunks.get(res);
-    // If edit, skip the deletion chunk and set focus on the insertion one.
-    if (lookUp.isEdit() && lookUp.getSide() == A) {
-      res = res + (dir == Direction.PREV ? -1 : 1);
-      if (res < 0 || chunks.size() <= res) {
-        return;
-      }
-    }
-
-    DiffChunkInfo target = chunks.get(res);
-    CodeMirror targetCm = host.getCmFromSide(target.getSide());
-    int cmLine = getCmLine(target.getStart(), target.getSide());
-    targetCm.setCursor(Pos.create(cmLine));
-    targetCm.focus();
-    targetCm.scrollToY(
-        targetCm.heightAtLine(cmLine, "local") - 0.5 * targetCm.scrollbarV().getClientHeight());
-  }
-
-  Comparator<DiffChunkInfo> getDiffChunkComparator() {
-    // Chunks are ordered by their starting line. If it's a deletion,
-    // use its corresponding line on the revision side for comparison.
-    // In the edit case, put the deletion chunk right before the
-    // insertion chunk. This placement guarantees well-ordering.
-    return new Comparator<DiffChunkInfo>() {
-      @Override
-      public int compare(DiffChunkInfo a, DiffChunkInfo b) {
-        if (a.getSide() == b.getSide()) {
-          return a.getStart() - b.getStart();
-        } else if (a.getSide() == A) {
-          int comp = lineMapper.lineOnOther(a.getSide(), a.getStart()).getLine() - b.getStart();
-          return comp == 0 ? -1 : comp;
-        } else {
-          int comp = a.getStart() - lineMapper.lineOnOther(b.getSide(), b.getStart()).getLine();
-          return comp == 0 ? 1 : comp;
-        }
-      }
-    };
-  }
-
-  abstract int getCmLine(int line, DisplaySide side);
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentBox.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentBox.css
deleted file mode 100644
index b4216eb..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentBox.css
+++ /dev/null
@@ -1,147 +0,0 @@
-/* Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@external .cm-s-midnight;
-@external .cm-s-night;
-@external .cm-s-twilight;
-@external .com-google-gerrit-client-diff-PublishedBox_BinderImpl_GenCss_style-name;
-@external .com-google-gerrit-client-diff-CommentBox-Style-message;
-@external .com-google-gerrit-client-diff-CommentBox-Style-date;
-@external .com-google-gerrit-client-diff-DiffTable_BinderImpl_GenCss_style-range;
-@external .com-google-gerrit-client-diff-DiffTable_BinderImpl_GenCss_style-rangeHighlight;
-@external .net-codemirror-lib-CodeMirror-Style-activeLine;
-@external .CodeMirror-linenumber;
-
-.cm-s-midnight .com-google-gerrit-client-diff-PublishedBox_BinderImpl_GenCss_style-name { color: black }
-.cm-s-midnight .com-google-gerrit-client-diff-CommentBox-Style-message { color: black }
-.cm-s-midnight .com-google-gerrit-client-diff-CommentBox-Style-date { color: black }
-.cm-s-midnight .com-google-gerrit-client-diff-DiffTable_BinderImpl_GenCss_style-range { color: #777 }
-.cm-s-midnight .com-google-gerrit-client-diff-DiffTable_BinderImpl_GenCss_style-rangeHighlight { color: #777 }
-.cm-s-midnight .net-codemirror-lib-CodeMirror-Style-activeLine .CodeMirror-linenumber { color: black }
-
-.cm-s-night .com-google-gerrit-client-diff-PublishedBox_BinderImpl_GenCss_style-name { color: black }
-.cm-s-night .com-google-gerrit-client-diff-CommentBox-Style-message { color: black }
-.cm-s-night .com-google-gerrit-client-diff-CommentBox-Style-date { color: black }
-.cm-s-night .com-google-gerrit-client-diff-DiffTable_BinderImpl_GenCss_style-range { color: #777 }
-.cm-s-night .com-google-gerrit-client-diff-DiffTable_BinderImpl_GenCss_style-rangeHighlight { color: #777 }
-.cm-s-night .net-codemirror-lib-CodeMirror-Style-activeLine .CodeMirror-linenumber { color: black }
-
-.cm-s-twilight .com-google-gerrit-client-diff-PublishedBox_BinderImpl_GenCss_style-name { color: black }
-.cm-s-twilight .com-google-gerrit-client-diff-CommentBox-Style-message { color: black }
-.cm-s-twilight .com-google-gerrit-client-diff-CommentBox-Style-date { color: black }
-.cm-s-twilight .com-google-gerrit-client-diff-DiffTable_BinderImpl_GenCss_style-range { color: #777 }
-.cm-s-twilight .com-google-gerrit-client-diff-DiffTable_BinderImpl_GenCss_style-rangeHighlight { color: #777 }
-.cm-s-twilight .net-codemirror-lib-CodeMirror-Style-activeLine .CodeMirror-linenumber { color: black }
-
-.commentWidgets {
-  max-width: 650px;
-
-  font-family: sans-serif;
-  background-color: #fcfa96;
-  border: 1px solid black;
-  -webkit-box-shadow: 3px 3px 3px #888888;
-  -moz-box-shadow: 3px 3px 3px #888888;
-  box-shadow: 3px 3px 3px #888888;
-
-  /* margin-bottom is fixed in CommentGroup.computeHeight() */
-  margin-bottom: 5px;
-  margin-right: 5px;
-
-  -webkit-touch-callout: initial;
-  -webkit-user-select: text;
-  -khtml-user-select: text;
-  -moz-user-select: text;
-  -ms-user-select: text;
-  user-select: text;
-}
-
-.commentBox {
-  position: relative;
-  min-height: 16px;
-}
-
-.header {
-  cursor: pointer;
-}
-
-.summary {
-  color: #777;
-  position: absolute;
-  top: 1px;
-  left: 120px;
-  width: 408px;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  padding-bottom: 0.1em;
-}
-
-.date {
-  white-space: nowrap;
-  position: absolute;
-  top: 2px;
-  right: 5px;
-}
-
-.contents {
-  margin-left: 28px;
-  padding-top: 2px;
-  position: relative;
-}
-.message {
-  overflow-x: auto;
-}
-.message p,
-.message ul,
-.message blockquote {
-  -webkit-margin-before: 0.2em;
-  -webkit-margin-after: 0.3em;
-}
-.message {
-  white-space: pre-wrap;
-}
-.commentBox button {
-  margin-right: 3px;
-  margin-bottom: 1px;
-  padding: 1px;
-  text-align: center;
-  font-size: 8px;
-  font-weight: bold;
-  border: 1px solid black;
-  cursor: pointer;
-  color: #fff;
-  background-color: #4d90fe;
-  background-image: -webkit-linear-gradient(top, #4d90fe, #4d90fe);
-  -webkit-border-radius: 2px;
-  -webkit-box-sizing: content-box;
-}
-.commentBox button div {
-  width: 25px;
-  white-space: nowrap;
-  color: #fff;
-}
-
-@sprite .goPrev {
-  gwt-image: "goPrev";
-  display: inline-block;
-}
-@sprite .goNext {
-  gwt-image: "goNext";
-  display: inline-block;
-}
-@sprite .goUp {
-  gwt-image: "goUp";
-  display: inline-block;
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentBox.java
deleted file mode 100644
index 6f9e694..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentBox.java
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gerrit.client.changes.CommentInfo;
-import com.google.gwt.event.dom.client.MouseOutEvent;
-import com.google.gwt.event.dom.client.MouseOutHandler;
-import com.google.gwt.event.dom.client.MouseOverEvent;
-import com.google.gwt.event.dom.client.MouseOverHandler;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.user.client.ui.Composite;
-import net.codemirror.lib.CodeMirror;
-import net.codemirror.lib.Configuration;
-import net.codemirror.lib.Pos;
-import net.codemirror.lib.TextMarker;
-import net.codemirror.lib.TextMarker.FromTo;
-
-/** An HtmlPanel for displaying a comment */
-abstract class CommentBox extends Composite {
-  static {
-    Resources.I.style().ensureInjected();
-  }
-
-  interface Style extends CssResource {
-    String commentWidgets();
-
-    String commentBox();
-
-    String contents();
-
-    String message();
-
-    String header();
-
-    String summary();
-
-    String date();
-
-    String goPrev();
-
-    String goNext();
-
-    String goUp();
-  }
-
-  private final CommentGroup group;
-  private ScrollbarAnnotation annotation;
-  private FromTo fromTo;
-  private TextMarker rangeMarker;
-  private TextMarker rangeHighlightMarker;
-
-  CommentBox(CommentGroup group, CommentRange range) {
-    this.group = group;
-    if (range != null) {
-      DiffScreen screen = group.getManager().host;
-      int startCmLine = screen.getCmLine(range.startLine() - 1, group.getSide());
-      int endCmLine = screen.getCmLine(range.endLine() - 1, group.getSide());
-      fromTo =
-          FromTo.create(
-              Pos.create(startCmLine, range.startCharacter()),
-              Pos.create(endCmLine, range.endCharacter()));
-      rangeMarker =
-          group
-              .getCm()
-              .markText(
-                  fromTo.from(),
-                  fromTo.to(),
-                  Configuration.create().set("className", Resources.I.diffTableStyle().range()));
-    }
-    addDomHandler(
-        new MouseOverHandler() {
-          @Override
-          public void onMouseOver(MouseOverEvent event) {
-            setRangeHighlight(true);
-          }
-        },
-        MouseOverEvent.getType());
-    addDomHandler(
-        new MouseOutHandler() {
-          @Override
-          public void onMouseOut(MouseOutEvent event) {
-            setRangeHighlight(isOpen());
-          }
-        },
-        MouseOutEvent.getType());
-  }
-
-  abstract CommentInfo getCommentInfo();
-
-  abstract boolean isOpen();
-
-  void setOpen(boolean open) {
-    group.resize();
-    setRangeHighlight(open);
-    getCm().focus();
-  }
-
-  CommentGroup getCommentGroup() {
-    return group;
-  }
-
-  CommentManager getCommentManager() {
-    return group.getCommentManager();
-  }
-
-  ScrollbarAnnotation getAnnotation() {
-    return annotation;
-  }
-
-  void setAnnotation(ScrollbarAnnotation mh) {
-    annotation = mh;
-  }
-
-  void setRangeHighlight(boolean highlight) {
-    if (fromTo != null) {
-      if (highlight && rangeHighlightMarker == null) {
-        rangeHighlightMarker =
-            group
-                .getCm()
-                .markText(
-                    fromTo.from(),
-                    fromTo.to(),
-                    Configuration.create()
-                        .set("className", Resources.I.diffTableStyle().rangeHighlight()));
-      } else if (!highlight && rangeHighlightMarker != null) {
-        rangeHighlightMarker.clear();
-        rangeHighlightMarker = null;
-      }
-    }
-  }
-
-  void clearRange() {
-    if (rangeMarker != null) {
-      rangeMarker.clear();
-      rangeMarker = null;
-    }
-  }
-
-  CodeMirror getCm() {
-    return group.getCm();
-  }
-
-  FromTo getFromTo() {
-    return fromTo;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentGroup.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentGroup.java
deleted file mode 100644
index 414e82e..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentGroup.java
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.SimplePanel;
-import net.codemirror.lib.CodeMirror;
-import net.codemirror.lib.Configuration;
-import net.codemirror.lib.LineWidget;
-import net.codemirror.lib.TextMarker.FromTo;
-
-/**
- * LineWidget attached to a CodeMirror container.
- *
- * <p>When a comment is placed on a line a CommentWidget is created.
- */
-abstract class CommentGroup extends Composite {
-
-  final DisplaySide side;
-  final int line;
-
-  private final CommentManager manager;
-  private final CodeMirror cm;
-  private final FlowPanel comments;
-  private LineWidget lineWidget;
-  private Timer resizeTimer;
-
-  CommentGroup(CommentManager manager, CodeMirror cm, DisplaySide side, int line) {
-    this.manager = manager;
-    this.cm = cm;
-    this.side = side;
-    this.line = line;
-
-    comments = new FlowPanel();
-    comments.setStyleName(Resources.I.style().commentWidgets());
-    comments.setVisible(false);
-    initWidget(new SimplePanel(comments));
-  }
-
-  CommentManager getCommentManager() {
-    return manager;
-  }
-
-  CodeMirror getCm() {
-    return cm;
-  }
-
-  int getLine() {
-    return line;
-  }
-
-  DisplaySide getSide() {
-    return side;
-  }
-
-  void add(PublishedBox box) {
-    comments.add(box);
-    comments.setVisible(true);
-  }
-
-  void add(DraftBox box) {
-    PublishedBox p = box.getReplyToBox();
-    if (p != null) {
-      for (int i = 0; i < getBoxCount(); i++) {
-        if (p == getCommentBox(i)) {
-          comments.insert(box, i + 1);
-          comments.setVisible(true);
-          resize();
-          return;
-        }
-      }
-    }
-    comments.add(box);
-    comments.setVisible(true);
-    resize();
-  }
-
-  CommentBox getCommentBox(int i) {
-    return (CommentBox) comments.getWidget(i);
-  }
-
-  int getBoxCount() {
-    return comments.getWidgetCount();
-  }
-
-  void openCloseLast() {
-    if (0 < getBoxCount()) {
-      CommentBox box = getCommentBox(getBoxCount() - 1);
-      box.setOpen(!box.isOpen());
-    }
-  }
-
-  void openCloseAll() {
-    boolean open = false;
-    for (int i = 0; i < getBoxCount(); i++) {
-      if (!getCommentBox(i).isOpen()) {
-        open = true;
-        break;
-      }
-    }
-    setOpenAll(open);
-  }
-
-  void setOpenAll(boolean open) {
-    for (int i = 0; i < getBoxCount(); i++) {
-      getCommentBox(i).setOpen(open);
-    }
-  }
-
-  void remove(DraftBox box) {
-    comments.remove(box);
-    comments.setVisible(0 < getBoxCount());
-  }
-
-  void detach() {
-    if (lineWidget != null) {
-      lineWidget.clear();
-      lineWidget = null;
-      updateSelection();
-    }
-    manager.clearLine(side, line, this);
-    removeFromParent();
-  }
-
-  void attach(DiffTable parent) {
-    parent.add(this);
-    lineWidget =
-        cm.addLineWidget(
-            Math.max(0, line - 1),
-            getElement(),
-            Configuration.create()
-                .set("coverGutter", true)
-                .set("noHScroll", true)
-                .set("above", line <= 0)
-                .set("insertAt", 0));
-  }
-
-  @Override
-  protected void onUnload() {
-    super.onUnload();
-    if (resizeTimer != null) {
-      resizeTimer.cancel();
-    }
-  }
-
-  void updateSelection() {
-    if (cm.somethingSelected()) {
-      FromTo r = cm.getSelectedRange();
-      if (r.to().line() >= line) {
-        cm.setSelection(r.from(), r.to());
-      }
-    }
-  }
-
-  boolean canComputeHeight() {
-    return !comments.isVisible() || comments.getOffsetHeight() > 0;
-  }
-
-  LineWidget getLineWidget() {
-    return lineWidget;
-  }
-
-  void setLineWidget(LineWidget widget) {
-    lineWidget = widget;
-  }
-
-  Timer getResizeTimer() {
-    return resizeTimer;
-  }
-
-  void setResizeTimer(Timer timer) {
-    resizeTimer = timer;
-  }
-
-  FlowPanel getComments() {
-    return comments;
-  }
-
-  CommentManager getManager() {
-    return manager;
-  }
-
-  abstract void init(DiffTable parent);
-
-  abstract void handleRedraw();
-
-  abstract void resize();
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentManager.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentManager.java
deleted file mode 100644
index ef1ec1e..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentManager.java
+++ /dev/null
@@ -1,451 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gerrit.client.DiffObject;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.CommentInfo;
-import com.google.gerrit.client.patches.SkippedLine;
-import com.google.gerrit.client.rpc.CallbackGroup;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.CommentLinkProcessor;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.extensions.client.Side;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JsArray;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import net.codemirror.lib.CodeMirror;
-import net.codemirror.lib.Pos;
-import net.codemirror.lib.TextMarker.FromTo;
-
-/** Tracks comment widgets for {@link DiffScreen}. */
-abstract class CommentManager {
-  @Nullable private final Project.NameKey project;
-  private final DiffObject base;
-  private final PatchSet.Id revision;
-  private final String path;
-  private final CommentLinkProcessor commentLinkProcessor;
-  final SortedMap<Integer, CommentGroup> sideA;
-  final SortedMap<Integer, CommentGroup> sideB;
-  private final Map<String, PublishedBox> published;
-  private final Set<DraftBox> unsavedDrafts;
-  final DiffScreen host;
-  private boolean attached;
-  private boolean expandAll;
-  private boolean open;
-
-  CommentManager(
-      DiffScreen host,
-      @Nullable Project.NameKey project,
-      DiffObject base,
-      PatchSet.Id revision,
-      String path,
-      CommentLinkProcessor clp,
-      boolean open) {
-    this.host = host;
-    this.project = project;
-    this.base = base;
-    this.revision = revision;
-    this.path = path;
-    this.commentLinkProcessor = clp;
-    this.open = open;
-
-    published = new HashMap<>();
-    unsavedDrafts = new HashSet<>();
-    sideA = new TreeMap<>();
-    sideB = new TreeMap<>();
-  }
-
-  void setAttached(boolean attached) {
-    this.attached = attached;
-  }
-
-  boolean isAttached() {
-    return attached;
-  }
-
-  void setExpandAll(boolean expandAll) {
-    this.expandAll = expandAll;
-  }
-
-  boolean isExpandAll() {
-    return expandAll;
-  }
-
-  boolean isOpen() {
-    return open;
-  }
-
-  String getPath() {
-    return path;
-  }
-
-  Map<String, PublishedBox> getPublished() {
-    return published;
-  }
-
-  CommentLinkProcessor getCommentLinkProcessor() {
-    return commentLinkProcessor;
-  }
-
-  void renderDrafts(DisplaySide forSide, JsArray<CommentInfo> in) {
-    for (CommentInfo info : Natives.asList(in)) {
-      DisplaySide side = displaySide(info, forSide);
-      if (side != null) {
-        addDraftBox(side, info);
-      }
-    }
-  }
-
-  void setUnsaved(DraftBox box, boolean isUnsaved) {
-    if (isUnsaved) {
-      unsavedDrafts.add(box);
-    } else {
-      unsavedDrafts.remove(box);
-    }
-  }
-
-  void saveAllDrafts(CallbackGroup cb) {
-    for (DraftBox box : unsavedDrafts) {
-      box.save(cb);
-    }
-  }
-
-  Side getStoredSideFromDisplaySide(DisplaySide side) {
-    if (side == DisplaySide.A && (base.isBaseOrAutoMerge() || base.isParent())) {
-      return Side.PARENT;
-    }
-    return Side.REVISION;
-  }
-
-  int getParentNumFromDisplaySide(DisplaySide side) {
-    if (side == DisplaySide.A) {
-      return base.getParentNum();
-    }
-    return 0;
-  }
-
-  PatchSet.Id getPatchSetIdFromSide(DisplaySide side) {
-    if (side == DisplaySide.A && (base.isPatchSet() || base.isEdit())) {
-      return base.asPatchSetId();
-    }
-    return revision;
-  }
-
-  DisplaySide displaySide(CommentInfo info, DisplaySide forSide) {
-    if (info.side() == Side.PARENT) {
-      return (base.isBaseOrAutoMerge() || base.isParent()) ? DisplaySide.A : null;
-    }
-    return forSide;
-  }
-
-  static FromTo adjustSelection(CodeMirror cm) {
-    FromTo fromTo = cm.getSelectedRange();
-    Pos to = fromTo.to();
-    if (to.ch() == 0) {
-      to.line(to.line() - 1);
-      to.ch(cm.getLine(to.line()).length());
-    }
-    return fromTo;
-  }
-
-  abstract CommentGroup group(DisplaySide side, int cmLinePlusOne);
-
-  /**
-   * Create a new {@link DraftBox} at the specified line and focus it.
-   *
-   * @param side which side the draft will appear on.
-   * @param line the line the draft will be at. Lines are 1-based. Line 0 is a special case creating
-   *     a file level comment.
-   */
-  void insertNewDraft(DisplaySide side, int line) {
-    if (line == 0) {
-      host.skipManager.ensureFirstLineIsVisible();
-    }
-
-    CommentGroup group = group(side, line);
-    if (0 < group.getBoxCount()) {
-      CommentBox last = group.getCommentBox(group.getBoxCount() - 1);
-      if (last instanceof DraftBox) {
-        ((DraftBox) last).setEdit(true);
-      } else {
-        ((PublishedBox) last).doReply();
-      }
-    } else {
-      addDraftBox(
-              side,
-              CommentInfo.create(
-                  getPath(),
-                  getStoredSideFromDisplaySide(side),
-                  getParentNumFromDisplaySide(side),
-                  line,
-                  null,
-                  false))
-          .setEdit(true);
-    }
-  }
-
-  abstract String getTokenSuffixForActiveLine(CodeMirror cm);
-
-  Runnable signInCallback(CodeMirror cm) {
-    return () -> {
-      String token = host.getToken();
-      if (cm.extras().hasActiveLine()) {
-        token += "@" + getTokenSuffixForActiveLine(cm);
-      }
-      Gerrit.doSignIn(token);
-    };
-  }
-
-  abstract void newDraft(CodeMirror cm);
-
-  Runnable newDraftCallback(CodeMirror cm) {
-    if (!Gerrit.isSignedIn()) {
-      return signInCallback(cm);
-    }
-
-    return () -> {
-      if (cm.extras().hasActiveLine()) {
-        newDraft(cm);
-      }
-    };
-  }
-
-  DraftBox addDraftBox(DisplaySide side, CommentInfo info) {
-    int cmLinePlusOne = host.getCmLine(info.line() - 1, side) + 1;
-    CommentGroup group = group(side, cmLinePlusOne);
-    DraftBox box =
-        new DraftBox(
-            group,
-            getCommentLinkProcessor(),
-            project,
-            getPatchSetIdFromSide(side),
-            info,
-            isExpandAll());
-
-    if (info.inReplyTo() != null) {
-      PublishedBox r = getPublished().get(info.inReplyTo());
-      if (r != null) {
-        r.setReplyBox(box);
-      }
-    }
-
-    group.add(box);
-    box.setAnnotation(
-        host.getDiffTable()
-            .scrollbar
-            .draft(host.getCmFromSide(side), Math.max(0, cmLinePlusOne - 1)));
-    return box;
-  }
-
-  void setExpandAllComments(boolean b) {
-    setExpandAll(b);
-    for (CommentGroup g : sideA.values()) {
-      g.setOpenAll(b);
-    }
-    for (CommentGroup g : sideB.values()) {
-      g.setOpenAll(b);
-    }
-  }
-
-  abstract SortedMap<Integer, CommentGroup> getMapForNav(DisplaySide side);
-
-  Runnable commentNav(CodeMirror src, Direction dir) {
-    return () -> {
-      // Every comment appears in both side maps as a linked pair.
-      // It is only necessary to search one side to find a comment
-      // on either side of the editor pair.
-      SortedMap<Integer, CommentGroup> map = getMapForNav(src.side());
-      int line =
-          src.extras().hasActiveLine() ? src.getLineNumber(src.extras().activeLine()) + 1 : 0;
-
-      CommentGroup g;
-      if (dir == Direction.NEXT) {
-        map = map.tailMap(line + 1);
-        if (map.isEmpty()) {
-          return;
-        }
-        g = map.get(map.firstKey());
-        while (g.getBoxCount() == 0) {
-          map = map.tailMap(map.firstKey() + 1);
-          if (map.isEmpty()) {
-            return;
-          }
-          g = map.get(map.firstKey());
-        }
-      } else {
-        map = map.headMap(line);
-        if (map.isEmpty()) {
-          return;
-        }
-        g = map.get(map.lastKey());
-        while (g.getBoxCount() == 0) {
-          map = map.headMap(map.lastKey());
-          if (map.isEmpty()) {
-            return;
-          }
-          g = map.get(map.lastKey());
-        }
-      }
-
-      CodeMirror cm = g.getCm();
-      double y = cm.heightAtLine(g.getLine() - 1, "local");
-      cm.setCursor(Pos.create(g.getLine() - 1));
-      cm.scrollToY(y - 0.5 * cm.scrollbarV().getClientHeight());
-      cm.focus();
-    };
-  }
-
-  void clearLine(DisplaySide side, int line, CommentGroup group) {
-    SortedMap<Integer, CommentGroup> map = map(side);
-    if (map.get(line) == group) {
-      map.remove(line);
-    }
-  }
-
-  void render(CommentsCollections in, boolean expandAll) {
-    if (in.publishedBase != null) {
-      renderPublished(DisplaySide.A, in.publishedBase);
-    }
-    if (in.publishedRevision != null) {
-      renderPublished(DisplaySide.B, in.publishedRevision);
-    }
-    if (in.draftsBase != null) {
-      renderDrafts(DisplaySide.A, in.draftsBase);
-    }
-    if (in.draftsRevision != null) {
-      renderDrafts(DisplaySide.B, in.draftsRevision);
-    }
-    if (expandAll) {
-      setExpandAllComments(true);
-    }
-    for (CommentGroup g : sideA.values()) {
-      g.init(host.getDiffTable());
-    }
-    for (CommentGroup g : sideB.values()) {
-      g.init(host.getDiffTable());
-      g.handleRedraw();
-    }
-    setAttached(true);
-  }
-
-  void renderPublished(DisplaySide forSide, JsArray<CommentInfo> in) {
-    for (CommentInfo info : Natives.asList(in)) {
-      DisplaySide side = displaySide(info, forSide);
-      if (side != null) {
-        int cmLinePlusOne = host.getCmLine(info.line() - 1, side) + 1;
-        CommentGroup group = group(side, cmLinePlusOne);
-        PublishedBox box =
-            new PublishedBox(
-                group,
-                getCommentLinkProcessor(),
-                project,
-                getPatchSetIdFromSide(side),
-                info,
-                side,
-                isOpen());
-        group.add(box);
-        box.setAnnotation(
-            host.getDiffTable().scrollbar.comment(host.getCmFromSide(side), cmLinePlusOne - 1));
-        getPublished().put(info.id(), box);
-      }
-    }
-  }
-
-  abstract Collection<Integer> getLinesWithCommentGroups();
-
-  private static void checkAndAddSkip(List<SkippedLine> out, SkippedLine s) {
-    if (s.getSize() > 1) {
-      out.add(s);
-    }
-  }
-
-  List<SkippedLine> splitSkips(int context, List<SkippedLine> skips) {
-    if (sideA.containsKey(0) || sideB.containsKey(0)) {
-      // Special case of file comment; cannot skip first line.
-      for (SkippedLine skip : skips) {
-        if (skip.getStartA() == 0) {
-          skip.incrementStart(1);
-          break;
-        }
-      }
-    }
-
-    for (int boxLine : getLinesWithCommentGroups()) {
-      List<SkippedLine> temp = new ArrayList<>(skips.size() + 2);
-      for (SkippedLine skip : skips) {
-        int startLine = host.getCmLine(skip.getStartB(), DisplaySide.B);
-        int deltaBefore = boxLine - startLine;
-        int deltaAfter = startLine + skip.getSize() - boxLine;
-        if (deltaBefore < -context || deltaAfter < -context) {
-          temp.add(skip); // Size guaranteed to be greater than 1
-        } else if (deltaBefore > context && deltaAfter > context) {
-          SkippedLine before =
-              new SkippedLine(
-                  skip.getStartA(), skip.getStartB(), skip.getSize() - deltaAfter - context);
-          skip.incrementStart(deltaBefore + context);
-          checkAndAddSkip(temp, before);
-          checkAndAddSkip(temp, skip);
-        } else if (deltaAfter > context) {
-          skip.incrementStart(deltaBefore + context);
-          checkAndAddSkip(temp, skip);
-        } else if (deltaBefore > context) {
-          skip.reduceSize(deltaAfter + context);
-          checkAndAddSkip(temp, skip);
-        }
-      }
-      if (temp.isEmpty()) {
-        return temp;
-      }
-      skips = temp;
-    }
-    return skips;
-  }
-
-  abstract void newDraftOnGutterClick(CodeMirror cm, String gutterClass, int line);
-
-  abstract CommentGroup getCommentGroupOnActiveLine(CodeMirror cm);
-
-  Runnable toggleOpenBox(CodeMirror cm) {
-    return () -> {
-      CommentGroup group = getCommentGroupOnActiveLine(cm);
-      if (group != null) {
-        group.openCloseLast();
-      }
-    };
-  }
-
-  Runnable openCloseAll(CodeMirror cm) {
-    return () -> {
-      CommentGroup group = getCommentGroupOnActiveLine(cm);
-      if (group != null) {
-        group.openCloseAll();
-      }
-    };
-  }
-
-  SortedMap<Integer, CommentGroup> map(DisplaySide side) {
-    return side == DisplaySide.A ? sideA : sideB;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentRange.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentRange.java
deleted file mode 100644
index 0f357d5..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentRange.java
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gwt.core.client.JavaScriptObject;
-import net.codemirror.lib.Pos;
-import net.codemirror.lib.TextMarker.FromTo;
-
-public class CommentRange extends JavaScriptObject {
-  public static CommentRange create(int sl, int sc, int el, int ec) {
-    CommentRange r = createObject().cast();
-    r.set(sl, sc, el, ec);
-    return r;
-  }
-
-  public static CommentRange create(FromTo fromTo) {
-    if (fromTo == null) {
-      return null;
-    }
-
-    Pos from = fromTo.from();
-    Pos to = fromTo.to();
-    return create(
-        from.line() + 1, from.ch(),
-        to.line() + 1, to.ch());
-  }
-
-  public final native int startLine() /*-{ return this.start_line; }-*/;
-
-  public final native int startCharacter() /*-{ return this.start_character; }-*/;
-
-  public final native int endLine() /*-{ return this.end_line; }-*/;
-
-  public final native int endCharacter() /*-{ return this.end_character; }-*/;
-
-  private native void set(int sl, int sc, int el, int ec) /*-{
-    this.start_line = sl;
-    this.start_character = sc;
-    this.end_line = el;
-    this.end_character = ec;
-  }-*/;
-
-  protected CommentRange() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentsCollections.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentsCollections.java
deleted file mode 100644
index 2698584..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentsCollections.java
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import static java.util.Comparator.comparing;
-
-import com.google.gerrit.client.DiffObject;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.CommentApi;
-import com.google.gerrit.client.changes.CommentInfo;
-import com.google.gerrit.client.rpc.CallbackGroup;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.extensions.client.Side;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-/** Collection of published and draft comments loaded from the server. */
-class CommentsCollections {
-  @Nullable private final Project.NameKey project;
-  private final String path;
-  private final DiffObject base;
-  private final PatchSet.Id revision;
-  private NativeMap<JsArray<CommentInfo>> publishedBaseAll;
-  private NativeMap<JsArray<CommentInfo>> publishedRevisionAll;
-  JsArray<CommentInfo> publishedBase;
-  JsArray<CommentInfo> publishedRevision;
-  JsArray<CommentInfo> draftsBase;
-  JsArray<CommentInfo> draftsRevision;
-
-  CommentsCollections(
-      @Nullable Project.NameKey project, DiffObject base, PatchSet.Id revision, String path) {
-    this.project = project;
-    this.path = path;
-    this.base = base;
-    this.revision = revision;
-  }
-
-  void load(CallbackGroup group) {
-    if (base.isPatchSet()) {
-      CommentApi.comments(
-          Project.NameKey.asStringOrNull(project), base.asPatchSetId(), group.add(publishedBase()));
-    }
-    CommentApi.comments(
-        Project.NameKey.asStringOrNull(project), revision, group.add(publishedRevision()));
-
-    if (Gerrit.isSignedIn()) {
-      if (base.isPatchSet()) {
-        CommentApi.drafts(
-            Project.NameKey.asStringOrNull(project), base.asPatchSetId(), group.add(draftsBase()));
-      }
-      CommentApi.drafts(
-          Project.NameKey.asStringOrNull(project), revision, group.add(draftsRevision()));
-    }
-  }
-
-  boolean hasCommentForPath(String filePath) {
-    if (base.isPatchSet()) {
-      JsArray<CommentInfo> forBase = publishedBaseAll.get(filePath);
-      if (forBase != null && forBase.length() > 0) {
-        return true;
-      }
-    }
-    JsArray<CommentInfo> forRevision = publishedRevisionAll.get(filePath);
-    if (forRevision != null && forRevision.length() > 0) {
-      return true;
-    }
-    return false;
-  }
-
-  private AsyncCallback<NativeMap<JsArray<CommentInfo>>> publishedBase() {
-    return new AsyncCallback<NativeMap<JsArray<CommentInfo>>>() {
-      @Override
-      public void onSuccess(NativeMap<JsArray<CommentInfo>> result) {
-        publishedBaseAll = result;
-        publishedBase = sort(result.get(path));
-      }
-
-      @Override
-      public void onFailure(Throwable caught) {}
-    };
-  }
-
-  private AsyncCallback<NativeMap<JsArray<CommentInfo>>> publishedRevision() {
-    return new AsyncCallback<NativeMap<JsArray<CommentInfo>>>() {
-      @Override
-      public void onSuccess(NativeMap<JsArray<CommentInfo>> result) {
-        for (String k : result.keySet()) {
-          result.put(k, filterForParent(result.get(k)));
-        }
-        publishedRevisionAll = result;
-        publishedRevision = sort(result.get(path));
-      }
-
-      @Override
-      public void onFailure(Throwable caught) {}
-    };
-  }
-
-  private JsArray<CommentInfo> filterForParent(JsArray<CommentInfo> list) {
-    JsArray<CommentInfo> result = JsArray.createArray().cast();
-    for (CommentInfo c : Natives.asList(list)) {
-      if (c.side() == Side.REVISION) {
-        result.push(c);
-      } else if (base.isBaseOrAutoMerge() && !c.hasParent()) {
-        result.push(c);
-      } else if (base.isParent() && c.parent() == base.getParentNum()) {
-        result.push(c);
-      }
-    }
-    return result;
-  }
-
-  private AsyncCallback<NativeMap<JsArray<CommentInfo>>> draftsBase() {
-    return new AsyncCallback<NativeMap<JsArray<CommentInfo>>>() {
-      @Override
-      public void onSuccess(NativeMap<JsArray<CommentInfo>> result) {
-        draftsBase = sort(result.get(path));
-      }
-
-      @Override
-      public void onFailure(Throwable caught) {}
-    };
-  }
-
-  private AsyncCallback<NativeMap<JsArray<CommentInfo>>> draftsRevision() {
-    return new AsyncCallback<NativeMap<JsArray<CommentInfo>>>() {
-      @Override
-      public void onSuccess(NativeMap<JsArray<CommentInfo>> result) {
-        for (String k : result.keySet()) {
-          result.put(k, filterForParent(result.get(k)));
-        }
-        draftsRevision = sort(result.get(path));
-      }
-
-      @Override
-      public void onFailure(Throwable caught) {}
-    };
-  }
-
-  private JsArray<CommentInfo> sort(JsArray<CommentInfo> in) {
-    if (in != null) {
-      for (CommentInfo c : Natives.asList(in)) {
-        c.path(path);
-      }
-      Natives.asList(in).sort(comparing(CommentInfo::updated));
-    }
-    return in;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffApi.java
deleted file mode 100644
index 1815920..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffApi.java
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import static com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace.IGNORE_ALL;
-
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.client.info.FileInfo;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.extensions.client.DiffPreferencesInfo;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-public class DiffApi {
-  public static void list(
-      @Nullable String project,
-      int id,
-      String revision,
-      RevisionInfo base,
-      AsyncCallback<NativeMap<FileInfo>> cb) {
-    RestApi api = ChangeApi.revision(project, id, revision).view("files");
-    if (base != null) {
-      if (base._number() < 0) {
-        api.addParameter("parent", -base._number());
-      } else {
-        api.addParameter("base", base.name());
-      }
-    }
-    api.get(NativeMap.copyKeysIntoChildren("path", cb));
-  }
-
-  public static void list(
-      @Nullable String project,
-      PatchSet.Id id,
-      PatchSet.Id base,
-      AsyncCallback<NativeMap<FileInfo>> cb) {
-    RestApi api = ChangeApi.revision(project, id).view("files");
-    if (base != null) {
-      if (base.get() < 0) {
-        api.addParameter("parent", -base.get());
-      } else {
-        api.addParameter("base", base.get());
-      }
-    }
-    api.get(NativeMap.copyKeysIntoChildren("path", cb));
-  }
-
-  public static DiffApi diff(@Nullable String project, PatchSet.Id id, String path) {
-    return new DiffApi(ChangeApi.revision(project, id).view("files").id(path).view("diff"));
-  }
-
-  private final RestApi call;
-
-  private DiffApi(RestApi call) {
-    this.call = call;
-  }
-
-  public DiffApi base(PatchSet.Id id) {
-    if (id != null) {
-      if (id.get() < 0) {
-        call.addParameter("parent", -id.get());
-      } else {
-        call.addParameter("base", id.get());
-      }
-    }
-    return this;
-  }
-
-  public DiffApi webLinksOnly() {
-    call.addParameterTrue("weblinks-only");
-    return this;
-  }
-
-  public DiffApi ignoreWhitespace(DiffPreferencesInfo.Whitespace w) {
-    if (w != null && w != IGNORE_ALL) {
-      call.addParameter("whitespace", w);
-    }
-    return this;
-  }
-
-  public DiffApi intraline(boolean intraline) {
-    if (intraline) {
-      call.addParameterTrue("intraline");
-    }
-    return this;
-  }
-
-  public DiffApi wholeFile() {
-    call.addParameter("context", "ALL");
-    return this;
-  }
-
-  public DiffApi context(int lines) {
-    call.addParameter("context", lines);
-    return this;
-  }
-
-  public void get(AsyncCallback<DiffInfo> cb) {
-    call.get(cb);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffChunkInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffChunkInfo.java
deleted file mode 100644
index 3b1b346..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffChunkInfo.java
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-/** Object recording the position of a diff chunk and whether it's an edit */
-class DiffChunkInfo {
-  private DisplaySide side;
-  private int start;
-  private int end;
-  private boolean edit;
-
-  DiffChunkInfo(DisplaySide side, int start, int end, boolean edit) {
-    this.side = side;
-    this.start = start;
-    this.end = end;
-    this.edit = edit;
-  }
-
-  DisplaySide getSide() {
-    return side;
-  }
-
-  int getStart() {
-    return start;
-  }
-
-  int getEnd() {
-    return end;
-  }
-
-  boolean isEdit() {
-    return edit;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffInfo.java
deleted file mode 100644
index d942c2e..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffInfo.java
+++ /dev/null
@@ -1,193 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gerrit.client.DiffWebLinkInfo;
-import com.google.gerrit.client.info.WebLinkInfo;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DiffView;
-import com.google.gerrit.reviewdb.client.Patch.ChangeType;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.JsArrayString;
-import java.util.ArrayList;
-import java.util.List;
-
-public class DiffInfo extends JavaScriptObject {
-  public final native FileMeta metaA() /*-{ return this.meta_a; }-*/;
-
-  public final native FileMeta metaB() /*-{ return this.meta_b; }-*/;
-
-  public final native JsArrayString diffHeader() /*-{ return this.diff_header; }-*/;
-
-  public final native JsArray<Region> content() /*-{ return this.content; }-*/;
-
-  public final native JsArray<DiffWebLinkInfo> webLinks() /*-{ return this.web_links; }-*/;
-
-  public final native boolean binary() /*-{ return this.binary || false; }-*/;
-
-  public final List<WebLinkInfo> sideBySideWebLinks() {
-    return filterWebLinks(DiffView.SIDE_BY_SIDE);
-  }
-
-  public final List<WebLinkInfo> unifiedWebLinks() {
-    return filterWebLinks(DiffView.UNIFIED_DIFF);
-  }
-
-  private List<WebLinkInfo> filterWebLinks(DiffView diffView) {
-    List<WebLinkInfo> filteredDiffWebLinks = new ArrayList<>();
-    List<DiffWebLinkInfo> allDiffWebLinks = Natives.asList(webLinks());
-    if (allDiffWebLinks != null) {
-      for (DiffWebLinkInfo webLink : allDiffWebLinks) {
-        if (diffView == DiffView.SIDE_BY_SIDE && webLink.showOnSideBySideDiffView()) {
-          filteredDiffWebLinks.add(webLink);
-        }
-        if (diffView == DiffView.UNIFIED_DIFF && webLink.showOnUnifiedDiffView()) {
-          filteredDiffWebLinks.add(webLink);
-        }
-      }
-    }
-    return filteredDiffWebLinks;
-  }
-
-  public final ChangeType changeType() {
-    return ChangeType.valueOf(changeTypeRaw());
-  }
-
-  private native String changeTypeRaw() /*-{ return this.change_type }-*/;
-
-  public final IntraLineStatus intralineStatus() {
-    String s = intralineStatusRaw();
-    return s != null ? IntraLineStatus.valueOf(s) : IntraLineStatus.OFF;
-  }
-
-  private native String intralineStatusRaw() /*-{ return this.intraline_status }-*/;
-
-  public final boolean hasSkip() {
-    JsArray<Region> c = content();
-    for (int i = 0; i < c.length(); i++) {
-      if (c.get(i).skip() != 0) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  public final String textA() {
-    StringBuilder s = new StringBuilder();
-    JsArray<Region> c = content();
-    for (int i = 0; i < c.length(); i++) {
-      Region r = c.get(i);
-      if (r.ab() != null) {
-        append(s, r.ab());
-      } else if (r.a() != null) {
-        append(s, r.a());
-      }
-      // TODO skip may need to be handled
-    }
-    return s.toString();
-  }
-
-  public final String textB() {
-    StringBuilder s = new StringBuilder();
-    JsArray<Region> c = content();
-    for (int i = 0; i < c.length(); i++) {
-      Region r = c.get(i);
-      if (r.ab() != null) {
-        append(s, r.ab());
-      } else if (r.b() != null) {
-        append(s, r.b());
-      }
-      // TODO skip may need to be handled
-    }
-    return s.toString();
-  }
-
-  public final String textUnified() {
-    StringBuilder s = new StringBuilder();
-    JsArray<Region> c = content();
-    for (int i = 0; i < c.length(); i++) {
-      Region r = c.get(i);
-      if (r.ab() != null) {
-        append(s, r.ab());
-      } else {
-        if (r.a() != null) {
-          append(s, r.a());
-        }
-        if (r.b() != null) {
-          append(s, r.b());
-        }
-      }
-      // TODO skip may need to be handled
-    }
-    return s.toString();
-  }
-
-  private static void append(StringBuilder s, JsArrayString lines) {
-    for (int i = 0; i < lines.length(); i++) {
-      if (s.length() > 0) {
-        s.append('\n');
-      }
-      s.append(lines.get(i));
-    }
-  }
-
-  protected DiffInfo() {}
-
-  public enum IntraLineStatus {
-    OFF,
-    OK,
-    TIMEOUT,
-    FAILURE
-  }
-
-  public static class FileMeta extends JavaScriptObject {
-    public final native String name() /*-{ return this.name; }-*/;
-
-    public final native String contentType() /*-{ return this.content_type; }-*/;
-
-    public final native int lines() /*-{ return this.lines || 0 }-*/;
-
-    public final native JsArray<WebLinkInfo> webLinks() /*-{ return this.web_links; }-*/;
-
-    protected FileMeta() {}
-  }
-
-  public static class Region extends JavaScriptObject {
-    public final native JsArrayString ab() /*-{ return this.ab; }-*/;
-
-    public final native JsArrayString a() /*-{ return this.a; }-*/;
-
-    public final native JsArrayString b() /*-{ return this.b; }-*/;
-
-    public final native int skip() /*-{ return this.skip || 0; }-*/;
-
-    public final native boolean common() /*-{ return this.common || false; }-*/;
-
-    public final native JsArray<Span> editA() /*-{ return this.edit_a }-*/;
-
-    public final native JsArray<Span> editB() /*-{ return this.edit_b }-*/;
-
-    protected Region() {}
-  }
-
-  public static class Span extends JavaScriptObject {
-    public final native int skip() /*-{ return this[0]; }-*/;
-
-    public final native int mark() /*-{ return this[1]; }-*/;
-
-    protected Span() {}
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffScreen.java
deleted file mode 100644
index b4221ca..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffScreen.java
+++ /dev/null
@@ -1,931 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impl ied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import static com.google.gerrit.extensions.client.DiffPreferencesInfo.WHOLE_FILE_CONTEXT;
-import static java.lang.Double.POSITIVE_INFINITY;
-
-import com.google.gerrit.client.DiffObject;
-import com.google.gerrit.client.Dispatcher;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.account.DiffPreferences;
-import com.google.gerrit.client.change.ChangeScreen;
-import com.google.gerrit.client.change.FileTable;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.changes.ChangeList;
-import com.google.gerrit.client.diff.DiffInfo.FileMeta;
-import com.google.gerrit.client.diff.LineMapper.LineOnOtherInfo;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.ChangeInfo.CommitInfo;
-import com.google.gerrit.client.info.ChangeInfo.EditInfo;
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.client.info.FileInfo;
-import com.google.gerrit.client.patches.PatchUtil;
-import com.google.gerrit.client.projects.ConfigInfoCache;
-import com.google.gerrit.client.rpc.CallbackGroup;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gerrit.client.ui.Screen;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DiffView;
-import com.google.gerrit.extensions.client.ListChangesOption;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Patch;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.RepeatingCommand;
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.NativeEvent;
-import com.google.gwt.event.dom.client.FocusHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.logical.shared.ResizeEvent;
-import com.google.gwt.event.logical.shared.ResizeHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-import com.google.gwtexpui.globalkey.client.KeyCommand;
-import com.google.gwtexpui.globalkey.client.KeyCommandSet;
-import com.google.gwtexpui.globalkey.client.ShowHelpCommand;
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.List;
-import net.codemirror.lib.CodeMirror;
-import net.codemirror.lib.CodeMirror.BeforeSelectionChangeHandler;
-import net.codemirror.lib.CodeMirror.GutterClickHandler;
-import net.codemirror.lib.CodeMirror.LineHandle;
-import net.codemirror.lib.KeyMap;
-import net.codemirror.lib.Pos;
-import net.codemirror.mode.ModeInfo;
-import net.codemirror.mode.ModeInjector;
-import net.codemirror.theme.ThemeLoader;
-
-/** Base class for SideBySide and Unified */
-abstract class DiffScreen extends Screen {
-  private static final KeyMap RENDER_ENTIRE_FILE_KEYMAP =
-      KeyMap.create().propagate("Ctrl-F").propagate("Ctrl-G").propagate("Shift-Ctrl-G");
-
-  enum FileSize {
-    SMALL(0),
-    LARGE(500),
-    HUGE(4000);
-
-    final int lines;
-
-    FileSize(int n) {
-      this.lines = n;
-    }
-  }
-
-  @Nullable private Project.NameKey project;
-  private final Change.Id changeId;
-  final DiffObject base;
-  final PatchSet.Id revision;
-  final String path;
-  final DiffPreferences prefs;
-  final SkipManager skipManager;
-
-  private DisplaySide startSide;
-  private int startLine;
-  private Change.Status changeStatus;
-
-  private HandlerRegistration resizeHandler;
-  private DiffInfo diff;
-  private FileSize fileSize;
-  private EditInfo edit;
-
-  private KeyCommandSet keysNavigation;
-  private KeyCommandSet keysAction;
-  private KeyCommandSet keysComment;
-  private List<HandlerRegistration> handlers;
-  private PreferencesAction prefsAction;
-  private int reloadVersionId;
-  private int parents;
-
-  @UiField(provided = true)
-  Header header;
-
-  DiffScreen(
-      @Nullable Project.NameKey project,
-      DiffObject base,
-      DiffObject revision,
-      String path,
-      DisplaySide startSide,
-      int startLine,
-      DiffView diffScreenType) {
-    this.project = project;
-    this.base = base;
-    this.revision = revision.asPatchSetId();
-    this.changeId = revision.asPatchSetId().getParentKey();
-    this.path = path;
-    this.startSide = startSide;
-    this.startLine = startLine;
-
-    prefs = DiffPreferences.create(Gerrit.getDiffPreferences());
-    handlers = new ArrayList<>(6);
-    keysNavigation = new KeyCommandSet(Gerrit.C.sectionNavigation());
-    header = new Header(keysNavigation, project, base, revision, path, diffScreenType, prefs);
-    skipManager = new SkipManager(this);
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    setHeaderVisible(false);
-    setWindowTitle(FileInfo.getFileName(path));
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-
-    CallbackGroup group1 = new CallbackGroup();
-    final CallbackGroup group2 = new CallbackGroup();
-
-    CodeMirror.initLibrary(
-        group1.add(
-            new AsyncCallback<Void>() {
-              final AsyncCallback<Void> themeCallback = group2.addEmpty();
-
-              @Override
-              public void onSuccess(Void result) {
-                // Load theme after CM library to ensure theme can override CSS.
-                ThemeLoader.loadTheme(prefs.theme(), themeCallback);
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {}
-            }));
-
-    DiffApi.diff(Project.NameKey.asStringOrNull(project), revision, path)
-        .base(base.asPatchSetId())
-        .wholeFile()
-        .intraline(prefs.intralineDifference())
-        .ignoreWhitespace(prefs.ignoreWhitespace())
-        .get(
-            group1.addFinal(
-                new GerritCallback<DiffInfo>() {
-                  final AsyncCallback<Void> modeInjectorCb = group2.addEmpty();
-
-                  @Override
-                  public void onSuccess(DiffInfo diffInfo) {
-                    diff = diffInfo;
-                    fileSize = bucketFileSize(diffInfo);
-
-                    if (prefs.syntaxHighlighting()) {
-                      if (fileSize.compareTo(FileSize.SMALL) > 0) {
-                        modeInjectorCb.onSuccess(null);
-                      } else {
-                        injectMode(diffInfo, modeInjectorCb);
-                      }
-                    } else {
-                      modeInjectorCb.onSuccess(null);
-                    }
-                  }
-                }));
-
-    if (Gerrit.isSignedIn()) {
-      ChangeApi.edit(
-          Project.NameKey.asStringOrNull(project),
-          changeId.get(),
-          group2.add(
-              new AsyncCallback<EditInfo>() {
-                @Override
-                public void onSuccess(EditInfo result) {
-                  edit = result;
-                }
-
-                @Override
-                public void onFailure(Throwable caught) {}
-              }));
-    }
-
-    final CommentsCollections comments = new CommentsCollections(project, base, revision, path);
-    comments.load(group2);
-
-    countParents(group2);
-
-    RestApi call = ChangeApi.detail(Project.NameKey.asStringOrNull(project), changeId.get());
-    ChangeList.addOptions(call, EnumSet.of(ListChangesOption.ALL_REVISIONS));
-    call.get(
-        group2.add(
-            new AsyncCallback<ChangeInfo>() {
-              @Override
-              public void onSuccess(ChangeInfo info) {
-                changeStatus = info.status();
-                project = info.projectNameKey();
-                info.revisions().copyKeysIntoChildren("name");
-                if (edit != null) {
-                  edit.setName(edit.commit().commit());
-                  info.setEdit(edit);
-                  info.revisions().put(edit.name(), RevisionInfo.fromEdit(edit));
-                }
-                String currentRevision = info.currentRevision();
-                boolean current =
-                    currentRevision != null
-                        && revision.get() == info.revision(currentRevision)._number();
-                JsArray<RevisionInfo> list = info.revisions().values();
-                RevisionInfo.sortRevisionInfoByNumber(list);
-                getDiffTable()
-                    .set(
-                        prefs,
-                        list,
-                        parents,
-                        diff,
-                        edit != null,
-                        current,
-                        changeStatus.isOpen(),
-                        diff.binary());
-                header.setChangeInfo(info);
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {}
-            }));
-
-    ConfigInfoCache.get(changeId, group2.addFinal(getScreenLoadCallback(comments)));
-  }
-
-  private void countParents(CallbackGroup cbg) {
-    ChangeApi.revision(Project.NameKey.asStringOrNull(project), changeId.get(), revision.getId())
-        .view("commit")
-        .get(
-            cbg.add(
-                new AsyncCallback<CommitInfo>() {
-                  @Override
-                  public void onSuccess(CommitInfo info) {
-                    parents = info.parents().length();
-                  }
-
-                  @Override
-                  public void onFailure(Throwable caught) {
-                    parents = 0;
-                  }
-                }));
-  }
-
-  @Override
-  public void onShowView() {
-    super.onShowView();
-
-    Window.enableScrolling(false);
-    if (prefs.hideTopMenu()) {
-      Gerrit.setHeaderVisible(false);
-    }
-    resizeHandler =
-        Window.addResizeHandler(
-            new ResizeHandler() {
-              @Override
-              public void onResize(ResizeEvent event) {
-                resizeCodeMirror();
-              }
-            });
-  }
-
-  KeyCommandSet getKeysNavigation() {
-    return keysNavigation;
-  }
-
-  KeyCommandSet getKeysAction() {
-    return keysAction;
-  }
-
-  @Override
-  protected void onUnload() {
-    super.onUnload();
-
-    removeKeyHandlerRegistrations();
-    if (getCommentManager() != null) {
-      CallbackGroup group = new CallbackGroup();
-      getCommentManager().saveAllDrafts(group);
-      group.done();
-    }
-    if (resizeHandler != null) {
-      resizeHandler.removeHandler();
-      resizeHandler = null;
-    }
-    for (CodeMirror cm : getCms()) {
-      if (cm != null) {
-        cm.getWrapperElement().removeFromParent();
-      }
-    }
-    if (prefsAction != null) {
-      prefsAction.hide();
-    }
-
-    Window.enableScrolling(true);
-    Gerrit.setHeaderVisible(true);
-  }
-
-  private void removeKeyHandlerRegistrations() {
-    for (HandlerRegistration h : handlers) {
-      h.removeHandler();
-    }
-    handlers.clear();
-  }
-
-  void registerCmEvents(CodeMirror cm) {
-    cm.on("cursorActivity", updateActiveLine(cm));
-    cm.on("focus", updateActiveLine(cm));
-    KeyMap keyMap =
-        KeyMap.create()
-            .on("A", upToChange(true))
-            .on("U", upToChange(false))
-            .on("'['", header.navigate(Direction.PREV))
-            .on("']'", header.navigate(Direction.NEXT))
-            .on("R", header.toggleReviewed())
-            .on("O", getCommentManager().toggleOpenBox(cm))
-            .on("N", maybeNextVimSearch(cm))
-            .on("Ctrl-Alt-E", openEditScreen(cm))
-            .on("P", getChunkManager().diffChunkNav(cm, Direction.PREV))
-            .on("Shift-M", header.reviewedAndNext())
-            .on("Shift-N", maybePrevVimSearch(cm))
-            .on("Shift-P", getCommentManager().commentNav(cm, Direction.PREV))
-            .on("Shift-O", getCommentManager().openCloseAll(cm))
-            .on(
-                "I",
-                () -> {
-                  switch (getIntraLineStatus()) {
-                    case OFF:
-                    case OK:
-                      toggleShowIntraline();
-                      break;
-                    case FAILURE:
-                    case TIMEOUT:
-                    default:
-                      break;
-                  }
-                })
-            .on("','", prefsAction::show)
-            .on("Shift-/", () -> new ShowHelpCommand().onKeyPress(null))
-            .on("Space", () -> cm.vim().handleKey("<C-d>"))
-            .on("Shift-Space", () -> cm.vim().handleKey("<C-u>"))
-            .on("Ctrl-F", () -> cm.execCommand("find"))
-            .on("Ctrl-G", () -> cm.execCommand("findNext"))
-            .on("Enter", maybeNextCmSearch(cm))
-            .on("Shift-Ctrl-G", () -> cm.execCommand("findPrev"))
-            .on("Shift-Enter", () -> cm.execCommand("findPrev"))
-            .on(
-                "Esc",
-                () -> {
-                  cm.setCursor(cm.getCursor());
-                  cm.execCommand("clearSearch");
-                  cm.vim().handleEx("nohlsearch");
-                })
-            .on("Ctrl-A", () -> cm.execCommand("selectAll"))
-            .on("G O", () -> Gerrit.display(PageLinks.toChangeQuery("status:open")))
-            .on("G M", () -> Gerrit.display(PageLinks.toChangeQuery("status:merged")))
-            .on("G A", () -> Gerrit.display(PageLinks.toChangeQuery("status:abandoned")));
-    if (Gerrit.isSignedIn()) {
-      keyMap
-          .on("G I", () -> Gerrit.display(PageLinks.MINE))
-          .on("G C", () -> Gerrit.display(PageLinks.toChangeQuery("has:draft")))
-          .on("G W", () -> Gerrit.display(PageLinks.toChangeQuery("is:watched status:open")))
-          .on("G S", () -> Gerrit.display(PageLinks.toChangeQuery("is:starred")));
-    }
-
-    if (revision.get() != 0) {
-      cm.on("beforeSelectionChange", onSelectionChange(cm));
-      cm.on("gutterClick", onGutterClick(cm));
-      keyMap.on("C", getCommentManager().newDraftCallback(cm));
-    }
-    CodeMirror.normalizeKeyMap(keyMap); // Needed to for multi-stroke keymaps
-    cm.addKeyMap(keyMap);
-  }
-
-  void maybeRegisterRenderEntireFileKeyMap(CodeMirror cm) {
-    if (renderEntireFile()) {
-      cm.addKeyMap(RENDER_ENTIRE_FILE_KEYMAP);
-    }
-  }
-
-  private BeforeSelectionChangeHandler onSelectionChange(CodeMirror cm) {
-    return new BeforeSelectionChangeHandler() {
-      private InsertCommentBubble bubble;
-
-      @Override
-      public void handle(CodeMirror cm, Pos anchor, Pos head) {
-        if (anchor.equals(head)) {
-          if (bubble != null) {
-            bubble.setVisible(false);
-          }
-          return;
-        } else if (bubble == null) {
-          init(anchor);
-        } else {
-          bubble.setVisible(true);
-        }
-        bubble.position(cm.charCoords(head, "local"));
-      }
-
-      private void init(Pos anchor) {
-        bubble = new InsertCommentBubble(getCommentManager(), cm);
-        add(bubble);
-        cm.addWidget(anchor, bubble.getElement());
-      }
-    };
-  }
-
-  @Override
-  public void registerKeys() {
-    super.registerKeys();
-
-    keysNavigation.add(new UpToChangeCommand(project, revision, 0, 'u'));
-    keysNavigation.add(
-        new NoOpKeyCommand(0, 'j', PatchUtil.C.lineNext()),
-        new NoOpKeyCommand(0, 'k', PatchUtil.C.linePrev()));
-    keysNavigation.add(
-        new NoOpKeyCommand(0, 'n', PatchUtil.C.chunkNext()),
-        new NoOpKeyCommand(0, 'p', PatchUtil.C.chunkPrev()));
-    keysNavigation.add(
-        new NoOpKeyCommand(KeyCommand.M_SHIFT, 'n', PatchUtil.C.commentNext()),
-        new NoOpKeyCommand(KeyCommand.M_SHIFT, 'p', PatchUtil.C.commentPrev()));
-    keysNavigation.add(new NoOpKeyCommand(KeyCommand.M_CTRL, 'f', Gerrit.C.keySearch()));
-
-    keysAction = new KeyCommandSet(Gerrit.C.sectionActions());
-    keysAction.add(new NoOpKeyCommand(0, KeyCodes.KEY_ENTER, PatchUtil.C.expandComment()));
-    keysAction.add(new NoOpKeyCommand(0, 'o', PatchUtil.C.expandComment()));
-    keysAction.add(
-        new NoOpKeyCommand(KeyCommand.M_SHIFT, 'o', PatchUtil.C.expandAllCommentsOnCurrentLine()));
-    if (Gerrit.isSignedIn()) {
-      keysAction.add(
-          new KeyCommand(0, 'r', PatchUtil.C.toggleReviewed()) {
-            @Override
-            public void onKeyPress(KeyPressEvent event) {
-              header.toggleReviewed().run();
-            }
-          });
-      keysAction.add(
-          new NoOpKeyCommand(KeyCommand.M_CTRL | KeyCommand.M_ALT, 'e', Gerrit.C.keyEditor()));
-    }
-    keysAction.add(
-        new KeyCommand(KeyCommand.M_SHIFT, 'm', PatchUtil.C.markAsReviewedAndGoToNext()) {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            header.reviewedAndNext().run();
-          }
-        });
-    keysAction.add(
-        new KeyCommand(0, 'a', PatchUtil.C.openReply()) {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            upToChange(true).run();
-          }
-        });
-    keysAction.add(
-        new KeyCommand(0, ',', PatchUtil.C.showPreferences()) {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            prefsAction.show();
-          }
-        });
-    if (getIntraLineStatus() == DiffInfo.IntraLineStatus.OFF
-        || getIntraLineStatus() == DiffInfo.IntraLineStatus.OK) {
-      keysAction.add(
-          new KeyCommand(0, 'i', PatchUtil.C.toggleIntraline()) {
-            @Override
-            public void onKeyPress(KeyPressEvent event) {
-              toggleShowIntraline();
-            }
-          });
-    }
-
-    if (Gerrit.isSignedIn()) {
-      keysAction.add(new NoOpKeyCommand(0, 'c', PatchUtil.C.commentInsert()));
-      keysComment = new KeyCommandSet(PatchUtil.C.commentEditorSet());
-      keysComment.add(new NoOpKeyCommand(KeyCommand.M_CTRL, 's', PatchUtil.C.commentSaveDraft()));
-      keysComment.add(new NoOpKeyCommand(0, KeyCodes.KEY_ESCAPE, PatchUtil.C.commentCancelEdit()));
-    } else {
-      keysComment = null;
-    }
-  }
-
-  @Nullable
-  public Project.NameKey getProject() {
-    return project;
-  }
-
-  void registerHandlers() {
-    removeKeyHandlerRegistrations();
-    handlers.add(GlobalKey.add(this, keysAction));
-    handlers.add(GlobalKey.add(this, keysNavigation));
-    if (keysComment != null) {
-      handlers.add(GlobalKey.add(this, keysComment));
-    }
-    handlers.add(ShowHelpCommand.addFocusHandler(getFocusHandler()));
-  }
-
-  void setupSyntaxHighlighting() {
-    if (prefs.syntaxHighlighting() && fileSize.compareTo(FileSize.SMALL) > 0) {
-      Scheduler.get()
-          .scheduleFixedDelay(
-              new RepeatingCommand() {
-                @Override
-                public boolean execute() {
-                  if (prefs.syntaxHighlighting() && isAttached()) {
-                    setSyntaxHighlighting(prefs.syntaxHighlighting());
-                  }
-                  return false;
-                }
-              },
-              250);
-    }
-  }
-
-  abstract CodeMirror newCm(DiffInfo.FileMeta meta, String contents, Element parent);
-
-  void render(DiffInfo diff) {
-    header.setNoDiff(diff);
-    getChunkManager().render(diff);
-  }
-
-  void setShowLineNumbers(boolean b) {
-    if (b) {
-      getDiffTable().addStyleName(Resources.I.diffTableStyle().showLineNumbers());
-    } else {
-      getDiffTable().removeStyleName(Resources.I.diffTableStyle().showLineNumbers());
-    }
-  }
-
-  void setShowIntraline(boolean b) {
-    if (b && getIntraLineStatus() == DiffInfo.IntraLineStatus.OFF) {
-      reloadDiffInfo();
-    } else if (b) {
-      getDiffTable().removeStyleName(Resources.I.diffTableStyle().noIntraline());
-    } else {
-      getDiffTable().addStyleName(Resources.I.diffTableStyle().noIntraline());
-    }
-  }
-
-  private void toggleShowIntraline() {
-    prefs.intralineDifference(!Boolean.valueOf(prefs.intralineDifference()));
-    setShowIntraline(prefs.intralineDifference());
-    prefsAction.update();
-  }
-
-  abstract void setSyntaxHighlighting(boolean b);
-
-  void setContext(int context) {
-    operation(
-        () -> {
-          skipManager.removeAll();
-          skipManager.render(context, diff);
-          updateRenderEntireFile();
-        });
-  }
-
-  private int adjustCommitMessageLine(int line) {
-    /* When commit messages are shown in the diff screen they include
-      a header block that looks like this:
-
-      1 Parent:     deadbeef (Parent commit title)
-      2 Author:     A. U. Thor <author@example.com>
-      3 AuthorDate: 2015-02-27 19:20:52 +0900
-      4 Commit:     A. U. Thor <author@example.com>
-      5 CommitDate: 2015-02-27 19:20:52 +0900
-      6 [blank line]
-      7 Commit message title
-      8
-      9 Commit message body
-     10 ...
-     11 ...
-
-    If the commit is a merge commit, both parent commits are listed in the
-    first two lines instead of a 'Parent' line:
-
-      1 Merge Of:   deadbeef (Parent 1 commit title)
-      2             beefdead (Parent 2 commit title)
-
-    */
-
-    // Offset to compensate for header lines until the blank line
-    // after 'CommitDate'
-    int offset = 6;
-
-    // Adjust for merge commits, which have two parent lines
-    if (diff.textB().startsWith("Merge")) {
-      offset += 1;
-    }
-
-    // If the cursor is inside the header line, reset to the first line of the
-    // commit message. Otherwise if the cursor is on an actual line of the commit
-    // message, adjust the line number to compensate for the header lines, so the
-    // focus is on the correct line.
-    if (line <= offset) {
-      return 1;
-    }
-    return line - offset;
-  }
-
-  private Runnable openEditScreen(CodeMirror cm) {
-    return () -> {
-      LineHandle handle = cm.extras().activeLine();
-      int line = cm.getLineNumber(handle) + 1;
-      if (Patch.COMMIT_MSG.equals(path)) {
-        line = adjustCommitMessageLine(line);
-      }
-      String token = Dispatcher.toEditScreen(project, revision, path, line);
-      if (!Gerrit.isSignedIn()) {
-        Gerrit.doSignIn(token);
-      } else {
-        Gerrit.display(token);
-      }
-    };
-  }
-
-  void updateRenderEntireFile() {
-    boolean entireFile = renderEntireFile();
-    for (CodeMirror cm : getCms()) {
-      cm.removeKeyMap(RENDER_ENTIRE_FILE_KEYMAP);
-      if (entireFile) {
-        cm.addKeyMap(RENDER_ENTIRE_FILE_KEYMAP);
-      }
-      cm.setOption("viewportMargin", entireFile ? POSITIVE_INFINITY : 10);
-    }
-  }
-
-  void resizeCodeMirror() {
-    int height = header.getOffsetHeight() + getDiffTable().getHeaderHeight();
-    for (CodeMirror cm : getCms()) {
-      cm.adjustHeight(height);
-    }
-  }
-
-  abstract ChunkManager getChunkManager();
-
-  abstract CommentManager getCommentManager();
-
-  Change.Status getChangeStatus() {
-    return changeStatus;
-  }
-
-  int getStartLine() {
-    return startLine;
-  }
-
-  void setStartLine(int startLine) {
-    this.startLine = startLine;
-  }
-
-  DisplaySide getStartSide() {
-    return startSide;
-  }
-
-  void setStartSide(DisplaySide startSide) {
-    this.startSide = startSide;
-  }
-
-  DiffInfo getDiff() {
-    return diff;
-  }
-
-  FileSize getFileSize() {
-    return fileSize;
-  }
-
-  PreferencesAction getPrefsAction() {
-    return prefsAction;
-  }
-
-  void setPrefsAction(PreferencesAction prefsAction) {
-    this.prefsAction = prefsAction;
-  }
-
-  abstract void operation(Runnable apply);
-
-  private Runnable upToChange(boolean openReplyBox) {
-    return () -> {
-      CallbackGroup group = new CallbackGroup();
-      getCommentManager().saveAllDrafts(group);
-      group.done();
-      group.addListener(
-          new GerritCallback<Void>() {
-            @Override
-            public void onSuccess(Void result) {
-              String rev = String.valueOf(revision.get());
-              Gerrit.display(
-                  PageLinks.toChange(project, changeId, base.asString(), rev),
-                  new ChangeScreen(
-                      project, changeId, base, rev, openReplyBox, FileTable.Mode.REVIEW));
-            }
-          });
-    };
-  }
-
-  private Runnable maybePrevVimSearch(CodeMirror cm) {
-    return () -> {
-      if (cm.vim().hasSearchHighlight()) {
-        cm.vim().handleKey("N");
-      } else {
-        getCommentManager().commentNav(cm, Direction.NEXT).run();
-      }
-    };
-  }
-
-  private Runnable maybeNextVimSearch(CodeMirror cm) {
-    return () -> {
-      if (cm.vim().hasSearchHighlight()) {
-        cm.vim().handleKey("n");
-      } else {
-        getChunkManager().diffChunkNav(cm, Direction.NEXT).run();
-      }
-    };
-  }
-
-  Runnable maybeNextCmSearch(CodeMirror cm) {
-    return () -> {
-      if (cm.hasSearchHighlight()) {
-        cm.execCommand("findNext");
-      } else {
-        cm.execCommand("clearSearch");
-        getCommentManager().toggleOpenBox(cm).run();
-      }
-    };
-  }
-
-  boolean renderEntireFile() {
-    return prefs.renderEntireFile() && canRenderEntireFile(prefs);
-  }
-
-  boolean canRenderEntireFile(DiffPreferences prefs) {
-    // CodeMirror is too slow to layout an entire huge file.
-    return fileSize.compareTo(FileSize.HUGE) < 0
-        || (prefs.context() != WHOLE_FILE_CONTEXT && prefs.context() < 100);
-  }
-
-  DiffInfo.IntraLineStatus getIntraLineStatus() {
-    return diff.intralineStatus();
-  }
-
-  void setThemeStyles(boolean d) {
-    if (d) {
-      getDiffTable().addStyleName(Resources.I.diffTableStyle().dark());
-    } else {
-      getDiffTable().removeStyleName(Resources.I.diffTableStyle().dark());
-    }
-  }
-
-  void setShowTabs(boolean show) {
-    for (CodeMirror cm : getCms()) {
-      cm.extras().showTabs(show);
-    }
-  }
-
-  void setLineLength(int columns) {
-    for (CodeMirror cm : getCms()) {
-      cm.extras().lineLength(columns);
-    }
-  }
-
-  String getContentType(DiffInfo.FileMeta meta) {
-    if (prefs.syntaxHighlighting() && meta != null && meta.contentType() != null) {
-      ModeInfo m = ModeInfo.findMode(meta.contentType(), path);
-      return m != null ? m.mime() : null;
-    }
-    return null;
-  }
-
-  String getContentType() {
-    return getContentType(diff.metaB());
-  }
-
-  void injectMode(DiffInfo diffInfo, AsyncCallback<Void> cb) {
-    new ModeInjector()
-        .add(getContentType(diffInfo.metaA()))
-        .add(getContentType(diffInfo.metaB()))
-        .inject(cb);
-  }
-
-  abstract void setAutoHideDiffHeader(boolean hide);
-
-  void prefetchNextFile() {
-    String nextPath = header.getNextPath();
-    if (nextPath != null) {
-      DiffApi.diff(Project.NameKey.asStringOrNull(project), revision, nextPath)
-          .base(base.asPatchSetId())
-          .wholeFile()
-          .intraline(prefs.intralineDifference())
-          .ignoreWhitespace(prefs.ignoreWhitespace())
-          .get(
-              new AsyncCallback<DiffInfo>() {
-                @Override
-                public void onSuccess(DiffInfo info) {
-                  new ModeInjector()
-                      .add(getContentType(info.metaA()))
-                      .add(getContentType(info.metaB()))
-                      .inject(CallbackGroup.<Void>emptyCallback());
-                }
-
-                @Override
-                public void onFailure(Throwable caught) {}
-              });
-    }
-  }
-
-  void reloadDiffInfo() {
-    int id = ++reloadVersionId;
-    DiffApi.diff(Project.NameKey.asStringOrNull(project), revision, path)
-        .base(base.asPatchSetId())
-        .wholeFile()
-        .intraline(prefs.intralineDifference())
-        .ignoreWhitespace(prefs.ignoreWhitespace())
-        .get(
-            new GerritCallback<DiffInfo>() {
-              @Override
-              public void onSuccess(DiffInfo diffInfo) {
-                if (id == reloadVersionId && isAttached()) {
-                  diff = diffInfo;
-                  operation(
-                      () -> {
-                        skipManager.removeAll();
-                        getChunkManager().reset();
-                        getDiffTable().scrollbar.removeDiffAnnotations();
-                        setShowIntraline(prefs.intralineDifference());
-                        render(diff);
-                        skipManager.render(prefs.context(), diff);
-                      });
-                }
-              }
-            });
-  }
-
-  private static FileSize bucketFileSize(DiffInfo diff) {
-    FileMeta a = diff.metaA();
-    FileMeta b = diff.metaB();
-    FileSize[] sizes = FileSize.values();
-    for (int i = sizes.length - 1; 0 <= i; i--) {
-      FileSize s = sizes[i];
-      if ((a != null && s.lines <= a.lines()) || (b != null && s.lines <= b.lines())) {
-        return s;
-      }
-    }
-    return FileSize.SMALL;
-  }
-
-  abstract Runnable updateActiveLine(CodeMirror cm);
-
-  private GutterClickHandler onGutterClick(CodeMirror cm) {
-    return new GutterClickHandler() {
-      @Override
-      public void handle(
-          CodeMirror instance, int line, String gutterClass, NativeEvent clickEvent) {
-        if (Element.as(clickEvent.getEventTarget()).hasClassName(getLineNumberClassName())
-            && clickEvent.getButton() == NativeEvent.BUTTON_LEFT
-            && !clickEvent.getMetaKey()
-            && !clickEvent.getAltKey()
-            && !clickEvent.getCtrlKey()
-            && !clickEvent.getShiftKey()) {
-          cm.setCursor(Pos.create(line));
-          Scheduler.get()
-              .scheduleDeferred(
-                  new ScheduledCommand() {
-                    @Override
-                    public void execute() {
-                      getCommentManager().newDraftOnGutterClick(cm, gutterClass, line + 1);
-                    }
-                  });
-        }
-      }
-    };
-  }
-
-  abstract FocusHandler getFocusHandler();
-
-  abstract CodeMirror[] getCms();
-
-  abstract CodeMirror getCmFromSide(DisplaySide side);
-
-  abstract DiffTable getDiffTable();
-
-  abstract int getCmLine(int line, DisplaySide side);
-
-  abstract String getLineNumberClassName();
-
-  LineOnOtherInfo lineOnOther(DisplaySide side, int line) {
-    return getChunkManager().lineMapper.lineOnOther(side, line);
-  }
-
-  abstract ScreenLoadCallback<ConfigInfoCache.Entry> getScreenLoadCallback(
-      CommentsCollections comments);
-
-  abstract boolean isSideBySide();
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.css
deleted file mode 100644
index 7569cf5..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.css
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-.range {
-  background-color: #ffd500 !important;
-}
-.rangeHighlight {
-  background-color: #ffff00 !important;
-}
-
-.fullscreen {
-  background-color: #f7f7f7;
-  border-bottom: 1px solid #ddd;
-}
-
-@external .diffHeader;
-.diffHeader {
-  font-size: 12px;
-  font-weight: bold;
-  color: #5252ad;
-}
-
-.diffHeader pre {
-  margin: 0 0 3px 0;
-}
-
-@external .dark, .noIntraline, .showLineNumbers;
-.dark {}
-.noIntraline {}
-.showLineNumbers {}
\ No newline at end of file
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.java
deleted file mode 100644
index a91f8e6..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.java
+++ /dev/null
@@ -1,184 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gerrit.client.DiffObject;
-import com.google.gerrit.client.account.DiffPreferences;
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.reviewdb.client.Patch.ChangeType;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.Style.Unit;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwt.user.client.ui.Widget;
-import net.codemirror.lib.CodeMirror;
-
-/** Base class for SideBySideTable2 and UnifiedTable2 */
-abstract class DiffTable extends Composite {
-  static {
-    Resources.I.diffTableStyle().ensureInjected();
-  }
-
-  interface Style extends CssResource {
-    String fullscreen();
-
-    String dark();
-
-    String noIntraline();
-
-    String range();
-
-    String rangeHighlight();
-
-    String diffHeader();
-
-    String showLineNumbers();
-  }
-
-  @UiField Element patchSetNavRow;
-  @UiField Element patchSetNavCellA;
-  @UiField Element patchSetNavCellB;
-  @UiField Element diffHeaderRow;
-  @UiField Element diffHeaderText;
-  @UiField FlowPanel widgets;
-
-  @UiField(provided = true)
-  PatchSetSelectBox patchSetSelectBoxA;
-
-  @UiField(provided = true)
-  PatchSetSelectBox patchSetSelectBoxB;
-
-  private boolean header;
-  private ChangeType changeType;
-  Scrollbar scrollbar;
-
-  DiffTable(DiffScreen parent, DiffObject base, DiffObject revision, String path) {
-    patchSetSelectBoxA =
-        new PatchSetSelectBox(
-            parent,
-            DisplaySide.A,
-            parent.getProject(),
-            revision.asPatchSetId().getParentKey(),
-            base,
-            path);
-    patchSetSelectBoxB =
-        new PatchSetSelectBox(
-            parent,
-            DisplaySide.B,
-            parent.getProject(),
-            revision.asPatchSetId().getParentKey(),
-            revision,
-            path);
-    PatchSetSelectBox.link(patchSetSelectBoxA, patchSetSelectBoxB);
-
-    this.scrollbar = new Scrollbar(this);
-  }
-
-  abstract boolean isVisibleA();
-
-  void setHeaderVisible(boolean show) {
-    DiffScreen parent = getDiffScreen();
-    if (show != UIObject.isVisible(patchSetNavRow)) {
-      UIObject.setVisible(patchSetNavRow, show);
-      UIObject.setVisible(diffHeaderRow, show && header);
-      if (show) {
-        parent.header.removeStyleName(Resources.I.diffTableStyle().fullscreen());
-      } else {
-        parent.header.addStyleName(Resources.I.diffTableStyle().fullscreen());
-      }
-      parent.resizeCodeMirror();
-    }
-  }
-
-  abstract int getHeaderHeight();
-
-  ChangeType getChangeType() {
-    return changeType;
-  }
-
-  void setUpBlameIconA(CodeMirror cm, boolean isBase, PatchSet.Id rev, String path) {
-    patchSetSelectBoxA.setUpBlame(cm, isBase, rev, path);
-  }
-
-  void setUpBlameIconB(CodeMirror cm, PatchSet.Id rev, String path) {
-    patchSetSelectBoxB.setUpBlame(cm, false, rev, path);
-  }
-
-  void set(
-      DiffPreferences prefs,
-      JsArray<RevisionInfo> list,
-      int parents,
-      DiffInfo info,
-      boolean editExists,
-      boolean current,
-      boolean open,
-      boolean binary) {
-    this.changeType = info.changeType();
-    patchSetSelectBoxA.setUpPatchSetNav(
-        list, parents, info.metaA(), editExists, current, open, binary);
-    patchSetSelectBoxB.setUpPatchSetNav(
-        list, parents, info.metaB(), editExists, current, open, binary);
-
-    JsArrayString hdr = info.diffHeader();
-    if (hdr != null) {
-      StringBuilder b = new StringBuilder();
-      for (int i = 1; i < hdr.length(); i++) {
-        String s = hdr.get(i);
-        if (!info.binary()
-            && (s.startsWith("diff --git ")
-                || s.startsWith("index ")
-                || s.startsWith("+++ ")
-                || s.startsWith("--- "))) {
-          continue;
-        }
-        b.append(s).append('\n');
-      }
-
-      String hdrTxt = b.toString().trim();
-      header = !hdrTxt.isEmpty();
-      diffHeaderText.setInnerText(hdrTxt);
-      UIObject.setVisible(diffHeaderRow, header);
-    } else {
-      header = false;
-      UIObject.setVisible(diffHeaderRow, false);
-    }
-    setHideEmptyPane(prefs.hideEmptyPane());
-  }
-
-  abstract void setHideEmptyPane(boolean hide);
-
-  void refresh() {
-    if (header) {
-      CodeMirror cm = getDiffScreen().getCmFromSide(DisplaySide.A);
-      diffHeaderText.getStyle().setMarginLeft(cm.getGutterElement().getOffsetWidth(), Unit.PX);
-    }
-  }
-
-  void add(Widget widget) {
-    widgets.add(widget);
-  }
-
-  abstract DiffScreen getDiffScreen();
-
-  boolean hasHeader() {
-    return header;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Direction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Direction.java
deleted file mode 100644
index b1dd87e1..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Direction.java
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-/** Direction of traversal in an ordered list. */
-public enum Direction {
-  PREV,
-  NEXT
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DisplaySide.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DisplaySide.java
deleted file mode 100644
index 6cee174..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DisplaySide.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-/** Enum representing the side on a side-by-side view */
-public enum DisplaySide {
-  A,
-  B;
-
-  DisplaySide otherSide() {
-    return this == A ? B : A;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DraftBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DraftBox.java
deleted file mode 100644
index 33d1ac4..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DraftBox.java
+++ /dev/null
@@ -1,466 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gerrit.client.FormatUtil;
-import com.google.gerrit.client.change.LocalComments;
-import com.google.gerrit.client.changes.CommentApi;
-import com.google.gerrit.client.changes.CommentInfo;
-import com.google.gerrit.client.rpc.CallbackGroup;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.client.ui.CommentLinkProcessor;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.event.dom.client.BlurEvent;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.DoubleClickEvent;
-import com.google.gwt.event.dom.client.DoubleClickHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyDownEvent;
-import com.google.gwt.event.dom.client.MouseMoveEvent;
-import com.google.gwt.event.dom.client.MouseMoveHandler;
-import com.google.gwt.event.dom.client.MouseUpEvent;
-import com.google.gwt.event.dom.client.MouseUpHandler;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.globalkey.client.NpTextArea;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-import net.codemirror.lib.CodeMirror;
-
-/** An HtmlPanel for displaying and editing a draft */
-class DraftBox extends CommentBox {
-  interface Binder extends UiBinder<HTMLPanel, DraftBox> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  private static final int INITIAL_LINES = 5;
-  private static final int MAX_LINES = 30;
-
-  private final CommentLinkProcessor linkProcessor;
-  private final PatchSet.Id psId;
-  @Nullable private final Project.NameKey project;
-  private final boolean expandAll;
-  private CommentInfo comment;
-  private PublishedBox replyToBox;
-  private Timer expandTimer;
-  private Timer resizeTimer;
-  private int editAreaHeight;
-  private boolean autoClosed;
-  private CallbackGroup pendingGroup;
-
-  @UiField Widget header;
-  @UiField Element summary;
-  @UiField Element date;
-
-  @UiField Element p_view;
-  @UiField HTML message;
-  @UiField Button edit;
-  @UiField Button discard1;
-
-  @UiField Element p_edit;
-  @UiField NpTextArea editArea;
-  @UiField Button save;
-  @UiField Button cancel;
-  @UiField Button discard2;
-
-  DraftBox(
-      CommentGroup group,
-      CommentLinkProcessor clp,
-      @Nullable Project.NameKey pj,
-      PatchSet.Id id,
-      CommentInfo info,
-      boolean expandAllComments) {
-    super(group, info.range());
-
-    linkProcessor = clp;
-    psId = id;
-    project = pj;
-    expandAll = expandAllComments;
-    initWidget(uiBinder.createAndBindUi(this));
-
-    expandTimer =
-        new Timer() {
-          @Override
-          public void run() {
-            expandText();
-          }
-        };
-    set(info);
-
-    header.addDomHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            if (!isEdit()) {
-              if (autoClosed && !isOpen()) {
-                setOpen(true);
-                setEdit(true);
-              } else {
-                setOpen(!isOpen());
-              }
-            }
-          }
-        },
-        ClickEvent.getType());
-
-    addDomHandler(
-        new DoubleClickHandler() {
-          @Override
-          public void onDoubleClick(DoubleClickEvent event) {
-            if (isEdit()) {
-              editArea.setFocus(true);
-            } else {
-              setOpen(true);
-              setEdit(true);
-            }
-          }
-        },
-        DoubleClickEvent.getType());
-
-    initResizeHandler();
-  }
-
-  private void set(CommentInfo info) {
-    autoClosed = !expandAll && info.message() != null && info.message().length() < 70;
-    date.setInnerText(FormatUtil.shortFormatDayTime(info.updated()));
-    if (info.message() != null) {
-      String msg = info.message().trim();
-      summary.setInnerText(msg);
-      message.setHTML(linkProcessor.apply(new SafeHtmlBuilder().append(msg).wikify()));
-    }
-    comment = info;
-  }
-
-  @Override
-  CommentInfo getCommentInfo() {
-    return comment;
-  }
-
-  @Override
-  boolean isOpen() {
-    return UIObject.isVisible(p_view);
-  }
-
-  @Override
-  void setOpen(boolean open) {
-    UIObject.setVisible(summary, !open);
-    UIObject.setVisible(p_view, open);
-    super.setOpen(open);
-  }
-
-  private void expandText() {
-    double cols = editArea.getCharacterWidth();
-    int rows = 2;
-    for (String line : editArea.getValue().split("\n")) {
-      rows += Math.ceil((1.0 + line.length()) / cols);
-    }
-    rows = Math.max(INITIAL_LINES, Math.min(rows, MAX_LINES));
-    if (editArea.getVisibleLines() != rows) {
-      editArea.setVisibleLines(rows);
-    }
-    editAreaHeight = editArea.getOffsetHeight();
-    getCommentGroup().resize();
-  }
-
-  boolean isEdit() {
-    return UIObject.isVisible(p_edit);
-  }
-
-  void setEdit(boolean edit) {
-    UIObject.setVisible(summary, false);
-    UIObject.setVisible(p_view, !edit);
-    UIObject.setVisible(p_edit, edit);
-
-    setRangeHighlight(edit);
-    if (edit) {
-      String msg = comment.message() != null ? comment.message() : "";
-      editArea.setValue(msg);
-      cancel.setVisible(!isNew());
-      expandText();
-      editAreaHeight = editArea.getOffsetHeight();
-
-      final int len = msg.length();
-      Scheduler.get()
-          .scheduleDeferred(
-              new ScheduledCommand() {
-                @Override
-                public void execute() {
-                  editArea.setFocus(true);
-                  if (len > 0) {
-                    editArea.setCursorPos(len);
-                  }
-                }
-              });
-    } else {
-      expandTimer.cancel();
-      resizeTimer.cancel();
-    }
-    getCommentManager().setUnsaved(this, edit);
-    getCommentGroup().resize();
-  }
-
-  PublishedBox getReplyToBox() {
-    return replyToBox;
-  }
-
-  void setReplyToBox(PublishedBox box) {
-    replyToBox = box;
-  }
-
-  @Override
-  protected void onUnload() {
-    expandTimer.cancel();
-    resizeTimer.cancel();
-    super.onUnload();
-  }
-
-  private void removeUI() {
-    if (replyToBox != null) {
-      replyToBox.unregisterReplyBox();
-    }
-
-    getCommentManager().setUnsaved(this, false);
-    setRangeHighlight(false);
-    clearRange();
-    getAnnotation().remove();
-    getCommentGroup().remove(this);
-    getCm().focus();
-  }
-
-  private void restoreSelection() {
-    if (getFromTo() != null && comment.inReplyTo() == null) {
-      getCm().setSelection(getFromTo().from(), getFromTo().to());
-    }
-  }
-
-  @UiHandler("message")
-  void onMessageClick(ClickEvent e) {
-    e.stopPropagation();
-  }
-
-  @UiHandler("message")
-  void onMessageDoubleClick(@SuppressWarnings("unused") DoubleClickEvent e) {
-    setEdit(true);
-  }
-
-  @UiHandler("edit")
-  void onEdit(ClickEvent e) {
-    e.stopPropagation();
-    setEdit(true);
-  }
-
-  @UiHandler("save")
-  void onSave(ClickEvent e) {
-    e.stopPropagation();
-    CallbackGroup group = new CallbackGroup();
-    save(group);
-    group.done();
-  }
-
-  void save(CallbackGroup group) {
-    if (pendingGroup != null) {
-      pendingGroup.addListener(group);
-      return;
-    }
-
-    String message = editArea.getValue().trim();
-    if (message.length() == 0) {
-      return;
-    }
-
-    CommentInfo input = CommentInfo.copy(comment);
-    input.message(message);
-    enableEdit(false);
-
-    pendingGroup = group;
-    final LocalComments lc = new LocalComments(project, psId);
-    GerritCallback<CommentInfo> cb =
-        new GerritCallback<CommentInfo>() {
-          @Override
-          public void onSuccess(CommentInfo result) {
-            enableEdit(true);
-            pendingGroup = null;
-            set(result);
-            setEdit(false);
-            if (autoClosed) {
-              setOpen(false);
-            }
-            getCommentManager().setUnsaved(DraftBox.this, false);
-          }
-
-          @Override
-          public void onFailure(Throwable e) {
-            enableEdit(true);
-            pendingGroup = null;
-            if (RestApi.isNotSignedIn(e)) {
-              CommentInfo saved = CommentInfo.copy(comment);
-              saved.message(editArea.getValue().trim());
-              lc.setInlineComment(saved);
-            }
-            super.onFailure(e);
-          }
-        };
-    if (input.id() == null) {
-      CommentApi.createDraft(Project.NameKey.asStringOrNull(project), psId, input, group.add(cb));
-    } else {
-      CommentApi.updateDraft(
-          Project.NameKey.asStringOrNull(project), psId, input.id(), input, group.add(cb));
-    }
-    CodeMirror cm = getCm();
-    cm.vim().handleKey("<Esc>");
-    cm.focus();
-  }
-
-  private void enableEdit(boolean on) {
-    editArea.setEnabled(on);
-    save.setEnabled(on);
-    cancel.setEnabled(on);
-    discard2.setEnabled(on);
-  }
-
-  @UiHandler("cancel")
-  void onCancel(ClickEvent e) {
-    e.stopPropagation();
-    if (isNew() && !isDirty()) {
-      removeUI();
-      restoreSelection();
-    } else {
-      setEdit(false);
-      if (autoClosed) {
-        setOpen(false);
-      }
-      getCm().focus();
-    }
-  }
-
-  @UiHandler({"discard1", "discard2"})
-  void onDiscard(ClickEvent e) {
-    e.stopPropagation();
-    if (isNew()) {
-      removeUI();
-      restoreSelection();
-    } else {
-      setEdit(false);
-      pendingGroup = new CallbackGroup();
-      CommentApi.deleteDraft(
-          Project.NameKey.asStringOrNull(project),
-          psId,
-          comment.id(),
-          pendingGroup.addFinal(
-              new GerritCallback<JavaScriptObject>() {
-                @Override
-                public void onSuccess(JavaScriptObject result) {
-                  pendingGroup = null;
-                  removeUI();
-                }
-              }));
-    }
-  }
-
-  @UiHandler("editArea")
-  void onKeyDown(KeyDownEvent e) {
-    resizeTimer.cancel();
-    if ((e.isControlKeyDown() || e.isMetaKeyDown()) && !e.isAltKeyDown() && !e.isShiftKeyDown()) {
-      switch (e.getNativeKeyCode()) {
-        case 's':
-        case 'S':
-          e.preventDefault();
-          CallbackGroup group = new CallbackGroup();
-          save(group);
-          group.done();
-          return;
-      }
-    } else if (e.getNativeKeyCode() == KeyCodes.KEY_ESCAPE && !isDirty()) {
-      if (isNew()) {
-        removeUI();
-        restoreSelection();
-        return;
-      }
-      setEdit(false);
-      if (autoClosed) {
-        setOpen(false);
-      }
-      getCm().focus();
-      return;
-    }
-    expandTimer.schedule(250);
-  }
-
-  @UiHandler("editArea")
-  void onBlur(@SuppressWarnings("unused") BlurEvent e) {
-    resizeTimer.cancel();
-  }
-
-  private void initResizeHandler() {
-    resizeTimer =
-        new Timer() {
-          @Override
-          public void run() {
-            getCommentGroup().resize();
-          }
-        };
-
-    addDomHandler(
-        new MouseMoveHandler() {
-          @Override
-          public void onMouseMove(MouseMoveEvent event) {
-            int h = editArea.getOffsetHeight();
-            if (isEdit() && h != editAreaHeight) {
-              getCommentGroup().resize();
-              resizeTimer.scheduleRepeating(50);
-              editAreaHeight = h;
-            }
-          }
-        },
-        MouseMoveEvent.getType());
-
-    addDomHandler(
-        new MouseUpHandler() {
-          @Override
-          public void onMouseUp(MouseUpEvent event) {
-            resizeTimer.cancel();
-            getCommentGroup().resize();
-          }
-        },
-        MouseUpEvent.getType());
-  }
-
-  private boolean isNew() {
-    return comment.id() == null;
-  }
-
-  private boolean isDirty() {
-    String msg = editArea.getValue().trim();
-    if (isNew()) {
-      return msg.length() > 0;
-    }
-    return !msg.equals(comment.message() != null ? comment.message().trim() : "");
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DraftBox.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DraftBox.ui.xml
deleted file mode 100644
index a363c06..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DraftBox.ui.xml
+++ /dev/null
@@ -1,96 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:c='urn:import:com.google.gerrit.client'
-    xmlns:e='urn:import:com.google.gwtexpui.globalkey.client'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-  <ui:with field='res' type='com.google.gerrit.client.diff.Resources'/>
-  <ui:style gss='false'>
-    .draft {
-      width: 45px;
-      text-align: center;
-      color: #fff;
-      background-color: #aaa;
-      -webkit-border-radius: 2px;
-    }
-    .editArea { max-width: 637px; }
-    button.button div {
-      width: 35px;
-    }
-    button.discard {
-      color: #d14836;
-      background-color: #d14836;
-      background-image: -webkit-linear-gradient(top, #d14836, #d14836);
-      position: absolute;
-      left: 150px;
-    }
-  </ui:style>
-
-  <g:HTMLPanel styleName='{res.style.commentBox}'>
-    <div class='{res.style.contents}'>
-      <g:HTMLPanel ui:field='header' styleName='{res.style.header}'>
-        <div class='{style.draft}'>Draft</div>
-        <div ui:field='summary' class='{res.style.summary}'/>
-        <div ui:field='date' class='{res.style.date}'/>
-      </g:HTMLPanel>
-      <div ui:field='p_view' aria-hidden='true' style='display: NONE'>
-        <g:HTML ui:field='message' styleName='{res.style.message}'/>
-        <div style='position: relative'>
-          <g:Button ui:field='edit'
-              title='Edit this draft comment'
-              styleName='{style.button}'>
-            <ui:attribute name='title'/>
-            <div><ui:msg>Edit</ui:msg></div>
-          </g:Button>
-          <g:Button ui:field='discard1'
-              title='Discard this draft comment'
-              styleName='{style.button}'
-              addStyleNames='{style.discard}'>
-            <ui:attribute name='title'/>
-            <div><ui:msg>Discard</ui:msg></div>
-          </g:Button>
-        </div>
-      </div>
-      <div ui:field='p_edit' aria-hidden='true' style='display: NONE'>
-        <e:NpTextArea ui:field='editArea'
-            characterWidth='60'
-            visibleLines='5'
-            spellCheck='true'
-            styleName='{style.editArea}'/>
-        <div style='position: relative'>
-          <g:Button ui:field='save'
-              title='Save this draft comment'
-              styleName='{style.button}'>
-            <ui:attribute name='title'/>
-            <div><ui:msg>Save</ui:msg></div>
-          </g:Button>
-          <g:Button ui:field='cancel' styleName='{style.button}'>
-            <div><ui:msg>Cancel</ui:msg></div>
-          </g:Button>
-          <g:Button ui:field='discard2'
-              title='Discard this draft comment'
-              styleName='{style.button}'
-              addStyleNames='{style.discard}'>
-            <ui:attribute name='title'/>
-            <div><ui:msg>Discard</ui:msg></div>
-          </g:Button>
-        </div>
-      </div>
-    </div>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/EditIterator.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/EditIterator.java
deleted file mode 100644
index 4cf78c7..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/EditIterator.java
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gwt.core.client.JsArrayString;
-import net.codemirror.lib.Pos;
-
-/** An iterator for intraline edits */
-class EditIterator {
-  private final JsArrayString lines;
-  private final int startLine;
-  private int line;
-  private int pos;
-
-  EditIterator(JsArrayString lineArray, int start) {
-    lines = lineArray;
-    startLine = start;
-  }
-
-  Pos advance(int numOfChar) {
-    numOfChar = adjustForNegativeDelta(numOfChar);
-
-    while (line < lines.length()) {
-      int len = lines.get(line).length() - pos + 1; // + 1 for LF
-      if (numOfChar < len) {
-        Pos at = Pos.create(startLine + line, numOfChar + pos);
-        pos += numOfChar;
-        return at;
-      }
-
-      numOfChar -= len;
-      line++;
-      pos = 0;
-
-      if (numOfChar == 0) {
-        return Pos.create(startLine + line, 0);
-      }
-    }
-
-    throw new IllegalStateException("EditIterator index out of bounds");
-  }
-
-  private int adjustForNegativeDelta(int n) {
-    while (n < 0) {
-      if (-n <= pos) {
-        pos += n;
-        return 0;
-      }
-
-      n += pos;
-      line--;
-      if (line < 0) {
-        throw new IllegalStateException("EditIterator index out of bounds");
-      }
-      pos = lines.get(line).length() + 1;
-    }
-    return n;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.java
deleted file mode 100644
index 7a97df1..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.java
+++ /dev/null
@@ -1,367 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gerrit.client.DiffObject;
-import com.google.gerrit.client.Dispatcher;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.account.DiffPreferences;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.changes.ReviewInfo;
-import com.google.gerrit.client.changes.Util;
-import com.google.gerrit.client.diff.DiffInfo.Region;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.FileInfo;
-import com.google.gerrit.client.info.WebLinkInfo;
-import com.google.gerrit.client.patches.PatchUtil;
-import com.google.gerrit.client.rpc.CallbackGroup;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.client.ui.InlineHyperlink;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DiffView;
-import com.google.gerrit.reviewdb.client.Patch;
-import com.google.gerrit.reviewdb.client.Patch.ChangeType;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.Style.Visibility;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwtexpui.globalkey.client.KeyCommand;
-import com.google.gwtexpui.globalkey.client.KeyCommandSet;
-import com.google.gwtexpui.safehtml.client.SafeHtml;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-import java.util.List;
-
-public class Header extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, Header> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  static {
-    Resources.I.style().ensureInjected();
-  }
-
-  private enum ReviewedState {
-    AUTO_REVIEW,
-    LOADED
-  }
-
-  @UiField CheckBox reviewed;
-  @UiField Element project;
-  @UiField Element filePath;
-  @UiField Element fileNumber;
-  @UiField Element fileCount;
-
-  @UiField Element noDiff;
-  @UiField FlowPanel linkPanel;
-
-  @UiField InlineHyperlink prev;
-  @UiField InlineHyperlink up;
-  @UiField InlineHyperlink next;
-  @UiField Image preferences;
-
-  private final KeyCommandSet keys;
-  @Nullable private final Project.NameKey projectKey;
-  private final DiffObject base;
-  private final PatchSet.Id patchSetId;
-  private final String path;
-  private final DiffView diffScreenType;
-  private final DiffPreferences prefs;
-  private boolean hasPrev;
-  private boolean hasNext;
-  private String nextPath;
-  private JsArray<FileInfo> files;
-  private PreferencesAction prefsAction;
-  private ReviewedState reviewedState;
-
-  Header(
-      KeyCommandSet keys,
-      @Nullable Project.NameKey project,
-      DiffObject base,
-      DiffObject patchSetId,
-      String path,
-      DiffView diffSreenType,
-      DiffPreferences prefs) {
-    initWidget(uiBinder.createAndBindUi(this));
-    this.keys = keys;
-    this.projectKey = project;
-    this.base = base;
-    this.patchSetId = patchSetId.asPatchSetId();
-    this.path = path;
-    this.diffScreenType = diffSreenType;
-    this.prefs = prefs;
-
-    if (!Gerrit.isSignedIn()) {
-      reviewed.getElement().getStyle().setVisibility(Visibility.HIDDEN);
-    }
-    SafeHtml.setInnerHTML(filePath, formatPath(path));
-    up.setTargetHistoryToken(
-        PageLinks.toChange(
-            project,
-            patchSetId.asPatchSetId().getParentKey(),
-            base.asString(),
-            patchSetId.asPatchSetId().getId()));
-  }
-
-  public static SafeHtml formatPath(String path) {
-    SafeHtmlBuilder b = new SafeHtmlBuilder();
-    if (Patch.COMMIT_MSG.equals(path)) {
-      return b.append(Util.C.commitMessage());
-    } else if (Patch.MERGE_LIST.equals(path)) {
-      return b.append(Util.C.mergeList());
-    }
-
-    int s = path.lastIndexOf('/') + 1;
-    b.append(path.substring(0, s));
-    b.openElement("b");
-    b.append(path.substring(s));
-    b.closeElement("b");
-    return b;
-  }
-
-  private int findCurrentFileIndex(JsArray<FileInfo> files) {
-    int currIndex = 0;
-    for (int i = 0; i < files.length(); i++) {
-      if (path.equals(files.get(i).path())) {
-        currIndex = i;
-        break;
-      }
-    }
-    return currIndex;
-  }
-
-  @Override
-  protected void onLoad() {
-    DiffApi.list(
-        Project.NameKey.asStringOrNull(projectKey),
-        patchSetId,
-        base.asPatchSetId(),
-        new GerritCallback<NativeMap<FileInfo>>() {
-          @Override
-          public void onSuccess(NativeMap<FileInfo> result) {
-            files = result.values();
-            FileInfo.sortFileInfoByPath(files);
-            fileNumber.setInnerText(
-                Integer.toString(Natives.asList(files).indexOf(result.get(path)) + 1));
-            fileCount.setInnerText(Integer.toString(files.length()));
-          }
-        });
-
-    if (Gerrit.isSignedIn()) {
-      ChangeApi.revision(Project.NameKey.asStringOrNull(projectKey), patchSetId)
-          .view("files")
-          .addParameterTrue("reviewed")
-          .get(
-              new AsyncCallback<JsArrayString>() {
-                @Override
-                public void onSuccess(JsArrayString result) {
-                  boolean b = Natives.asList(result).contains(path);
-                  reviewed.setValue(b, false);
-                  if (!b && reviewedState == ReviewedState.AUTO_REVIEW) {
-                    postAutoReviewed();
-                  }
-                  reviewedState = ReviewedState.LOADED;
-                }
-
-                @Override
-                public void onFailure(Throwable caught) {}
-              });
-    }
-  }
-
-  void autoReview() {
-    if (reviewedState == ReviewedState.LOADED && !reviewed.getValue()) {
-      postAutoReviewed();
-    } else {
-      reviewedState = ReviewedState.AUTO_REVIEW;
-    }
-  }
-
-  void setChangeInfo(ChangeInfo info) {
-    project.setInnerText(info.project());
-  }
-
-  void init(PreferencesAction pa, List<InlineHyperlink> links, List<WebLinkInfo> webLinks) {
-    prefsAction = pa;
-    prefsAction.setPartner(preferences);
-
-    for (InlineHyperlink link : links) {
-      linkPanel.add(link);
-    }
-    for (WebLinkInfo webLink : webLinks) {
-      linkPanel.add(webLink.toAnchor());
-    }
-  }
-
-  @UiHandler("reviewed")
-  void onValueChange(ValueChangeEvent<Boolean> event) {
-    if (event.getValue()) {
-      reviewed().put(CallbackGroup.<ReviewInfo>emptyCallback());
-    } else {
-      reviewed().delete(CallbackGroup.<ReviewInfo>emptyCallback());
-    }
-  }
-
-  private void postAutoReviewed() {
-    reviewed()
-        .background()
-        .put(
-            new AsyncCallback<ReviewInfo>() {
-              @Override
-              public void onSuccess(ReviewInfo result) {
-                reviewed.setValue(true, false);
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {}
-            });
-  }
-
-  private RestApi reviewed() {
-    return ChangeApi.revision(Project.NameKey.asStringOrNull(projectKey), patchSetId)
-        .view("files")
-        .id(path)
-        .view("reviewed");
-  }
-
-  @UiHandler("preferences")
-  void onPreferences(@SuppressWarnings("unused") ClickEvent e) {
-    prefsAction.show();
-  }
-
-  private String url(FileInfo info) {
-    return diffScreenType == DiffView.UNIFIED_DIFF
-        ? Dispatcher.toUnified(projectKey, base, patchSetId, info.path())
-        : Dispatcher.toSideBySide(projectKey, base, patchSetId, info.path());
-  }
-
-  private KeyCommand setupNav(InlineHyperlink link, char key, String help, FileInfo info) {
-    if (info != null) {
-      final String url = url(info);
-      link.setTargetHistoryToken(url);
-      link.setTitle(
-          PatchUtil.M.fileNameWithShortcutKey(
-              FileInfo.getFileName(info.path()), Character.toString(key)));
-      KeyCommand k =
-          new KeyCommand(0, key, help) {
-            @Override
-            public void onKeyPress(KeyPressEvent event) {
-              Gerrit.display(url);
-            }
-          };
-      keys.add(k);
-      if (link == prev) {
-        hasPrev = true;
-      } else {
-        hasNext = true;
-      }
-      return k;
-    }
-    link.getElement().getStyle().setVisibility(Visibility.HIDDEN);
-    keys.add(new UpToChangeCommand(projectKey, patchSetId, 0, key));
-    return null;
-  }
-
-  private boolean shouldSkipFile(FileInfo curr, CommentsCollections comments) {
-    return prefs.skipDeleted() && ChangeType.DELETED.matches(curr.status())
-        || prefs.skipUnchanged() && ChangeType.RENAMED.matches(curr.status())
-        || prefs.skipUncommented() && !comments.hasCommentForPath(curr.path());
-  }
-
-  void setupPrevNextFiles(CommentsCollections comments) {
-    FileInfo prevInfo = null;
-    FileInfo nextInfo = null;
-    int currIndex = findCurrentFileIndex(files);
-    for (int i = currIndex - 1; i >= 0; i--) {
-      FileInfo curr = files.get(i);
-      if (shouldSkipFile(curr, comments)) {
-        continue;
-      }
-      prevInfo = curr;
-      break;
-    }
-    for (int i = currIndex + 1; i < files.length(); i++) {
-      FileInfo curr = files.get(i);
-      if (shouldSkipFile(curr, comments)) {
-        continue;
-      }
-      nextInfo = curr;
-      break;
-    }
-    KeyCommand p = setupNav(prev, '[', PatchUtil.C.previousFileHelp(), prevInfo);
-    KeyCommand n = setupNav(next, ']', PatchUtil.C.nextFileHelp(), nextInfo);
-    if (p != null && n != null) {
-      keys.pair(p, n);
-    }
-    nextPath = nextInfo != null ? nextInfo.path() : null;
-  }
-
-  Runnable toggleReviewed() {
-    return () -> reviewed.setValue(!reviewed.getValue(), true);
-  }
-
-  Runnable navigate(Direction dir) {
-    switch (dir) {
-      case PREV:
-        return () -> (hasPrev ? prev : up).go();
-      case NEXT:
-        return () -> (hasNext ? next : up).go();
-      default:
-        return () -> {};
-    }
-  }
-
-  Runnable reviewedAndNext() {
-    return () -> {
-      if (Gerrit.isSignedIn()) {
-        reviewed.setValue(true, true);
-      }
-      navigate(Direction.NEXT).run();
-    };
-  }
-
-  String getNextPath() {
-    return nextPath;
-  }
-
-  void setNoDiff(DiffInfo diff) {
-    if (diff.binary()) {
-      UIObject.setVisible(noDiff, false); // Don't bother showing "No Differences"
-    } else {
-      JsArray<Region> regions = diff.content();
-      boolean b = regions.length() == 0 || (regions.length() == 1 && regions.get(0).ab() != null);
-      UIObject.setVisible(noDiff, b);
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.ui.xml
deleted file mode 100644
index 39eb6cb..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.ui.xml
+++ /dev/null
@@ -1,95 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'
-    xmlns:x='urn:import:com.google.gerrit.client.ui'>
-  <ui:with field='ico' type='com.google.gerrit.client.GerritResources'/>
-  <ui:with field='res' type='com.google.gerrit.client.diff.Resources'/>
-  <ui:style gss='false'>
-  .header {
-    position: relative;
-    height: 16px;
-    line-height: 16px;
-  }
-  .reviewed input {
-    margin: 0;
-    padding: 0;
-    vertical-align: middle;
-  }
-  .path {
-    white-space: nowrap;
-  }
-  .fileCount {
-    white-space: nowrap;
-    position: relative;
-    bottom: 4px;
-  }
-  .navigation {
-    position: absolute;
-    top: 0;
-    right: 10px;
-    height: 16px;
-    line-height: 16px;
-  }
-  .nodiff {
-    white-space: nowrap;
-    color: #B00000;
-    vertical-align: top;
-    font-weight: bold;
-    margin-right: 1em;
-    float: left;
-  }
-  .linkPanel {
-    float: left;
-  }
-  .linkPanel img {
-    padding-right: 3px;
-  }
-  .preferences {
-    cursor: pointer;
-  }
-  </ui:style>
-  <g:HTMLPanel styleName='{style.header}'>
-    <g:CheckBox ui:field='reviewed'
-        styleName='{style.reviewed}'
-        title='Mark file as reviewed (Shortcut: r)'>
-      <ui:attribute name='title'/>
-    </g:CheckBox>
-    <span class='{style.path}'><span ui:field='project'/> / <span ui:field='filePath'/></span>
-    <div class='{style.navigation}'>
-      <span ui:field='noDiff' class='{style.nodiff}'><ui:msg>No Differences</ui:msg></span>
-      <g:FlowPanel ui:field='linkPanel' styleName='{style.linkPanel}'/>
-      <span class='{style.fileCount}'>
-        <ui:msg>File <span ui:field='fileNumber'/> of <span ui:field='fileCount'/></ui:msg>
-      </span>
-      <x:InlineHyperlink ui:field='prev' styleName='{res.style.goPrev}'/>
-      <x:InlineHyperlink ui:field='up'
-          styleName='{res.style.goUp}'
-          title='Up to change (Shortcut: u)'>
-        <ui:attribute name='title'/>
-      </x:InlineHyperlink>
-      <x:InlineHyperlink ui:field='next' styleName='{res.style.goNext}'/>
-      <g:Image ui:field='preferences'
-           styleName='{style.preferences}'
-           resource='{ico.gear}'
-           title='Diff preferences (Shortcut: ,)'>
-         <ui:attribute name='title'/>
-      </g:Image>
-    </div>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/InsertCommentBubble.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/InsertCommentBubble.java
deleted file mode 100644
index f8eab91..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/InsertCommentBubble.java
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Style;
-import com.google.gwt.dom.client.Style.Unit;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.Image;
-import net.codemirror.lib.CodeMirror;
-import net.codemirror.lib.Rect;
-
-/** Bubble displayed near a selected region to create a comment. */
-class InsertCommentBubble extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, InsertCommentBubble> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  @UiField Image icon;
-
-  InsertCommentBubble(CommentManager commentManager, CodeMirror cm) {
-    initWidget(uiBinder.createAndBindUi(this));
-    addDomHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            setVisible(false);
-            commentManager.newDraftCallback(cm).run();
-          }
-        },
-        ClickEvent.getType());
-  }
-
-  void position(Rect r) {
-    Style s = getElement().getStyle();
-    int top = (int) (r.top() - (getOffsetHeight() - 8));
-    if (top < 0) {
-      s.setTop(-3, Unit.PX);
-      s.setLeft(r.right() + 2, Unit.PX);
-    } else {
-      s.setTop(top, Unit.PX);
-      s.setLeft((int) (r.right() - 14), Unit.PX);
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/InsertCommentBubble.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/InsertCommentBubble.ui.xml
deleted file mode 100644
index 6a18c4d..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/InsertCommentBubble.ui.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-  <ui:with field='res' type='com.google.gerrit.client.GerritResources'/>
-  <ui:style gss='false'>
-    .bubble {
-      z-index: 150;
-      white-space: nowrap;
-      line-height: 16px;
-      cursor: pointer;
-    }
-    .message {
-      background: #fff1a8;
-      padding-left: 5px;
-      padding-right: 5px;
-      border-radius: 5px;
-      border: 1px solid #aaa;
-      font-family: sans-serif;
-      font-size: smaller;
-      font-style: italic;
-      vertical-align: top;
-    }
-    .message b {
-      vertical-align: top;
-    }
-  </ui:style>
-  <g:HTMLPanel styleName='{style.bubble}'>
-    <g:Image ui:field='icon'
-        styleName=''
-        resource='{res.draftComments}'
-        title='Create a new inline comment'>
-      <ui:attribute name='title'/>
-    </g:Image><span class='{style.message}'><ui:msg>press <b>c</b> to comment</ui:msg></span>
-  </g:HTMLPanel>
-</ui:UiBinder>
\ No newline at end of file
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/LineMapper.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/LineMapper.java
deleted file mode 100644
index fc83a14..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/LineMapper.java
+++ /dev/null
@@ -1,225 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-
-/** Helper class to handle calculations involving line gaps. */
-class LineMapper {
-  private int lineA;
-  private int lineB;
-  private List<LineGap> lineMapAtoB;
-  private List<LineGap> lineMapBtoA;
-
-  LineMapper() {
-    reset();
-  }
-
-  void reset() {
-    lineA = 0;
-    lineB = 0;
-    lineMapAtoB = new ArrayList<>();
-    lineMapBtoA = new ArrayList<>();
-  }
-
-  int getLineA() {
-    return lineA;
-  }
-
-  int getLineB() {
-    return lineB;
-  }
-
-  void appendCommon(int numLines) {
-    lineA += numLines;
-    lineB += numLines;
-  }
-
-  void appendReplace(int aLen, int bLen) {
-    appendCommon(Math.min(aLen, bLen));
-    if (aLen < bLen) { // Edit with insertion
-      appendInsert(bLen - aLen);
-    } else if (aLen > bLen) { // Edit with deletion
-      appendDelete(aLen - bLen);
-    }
-  }
-
-  void appendInsert(int numLines) {
-    int origLineB = lineB;
-    lineB += numLines;
-    int bAheadOfA = lineB - lineA;
-    lineMapAtoB.add(new LineGap(lineA, -1, bAheadOfA));
-    lineMapBtoA.add(new LineGap(origLineB, lineB - 1, -bAheadOfA));
-  }
-
-  void appendDelete(int numLines) {
-    int origLineA = lineA;
-    lineA += numLines;
-    int aAheadOfB = lineA - lineB;
-    lineMapAtoB.add(new LineGap(origLineA, lineA - 1, -aAheadOfB));
-    lineMapBtoA.add(new LineGap(lineB, -1, aAheadOfB));
-  }
-
-  /**
-   * Helper method to retrieve the line number on the other side.
-   *
-   * <p>Given a line number on one side, performs a binary search in the lineMap to find the
-   * corresponding LineGap record.
-   *
-   * <p>A LineGap records gap information from the start of an actual gap up to the start of the
-   * next gap. In the following example, lineMapAtoB will have LineGap: {start: 1, end: -1, delta:
-   * 3} (end set to -1 to represent a dummy gap of length zero. The binary search only looks at
-   * start so setting it to -1 has no effect here.) lineMapBtoA will have LineGap: {start: 1, end:
-   * 3, delta: -3} These LineGaps control lines between 1 and 5.
-   *
-   * <p>The "delta" is computed as the number to add on our side to get the line number on the other
-   * side given a line after the actual gap, so the result will be (line + delta). All lines within
-   * the actual gap (1 to 3) are considered corresponding to the last line above the region on the
-   * other side, which is 0 in this case. For these lines, we do (end + delta).
-   *
-   * <p>For example, to get the line number on the left corresponding to 1 on the right
-   * (lineOnOther(REVISION, 1)), the method looks up in lineMapBtoA, finds the "delta" to be -3, and
-   * returns 3 + (-3) = 0 since 1 falls in the actual gap. On the other hand, the line corresponding
-   * to 5 on the right will be 5 + (-3) = 2, since 5 is in the region after the gap (but still
-   * controlled by the current LineGap).
-   *
-   * <p>PARENT REVISION 0 | 0 - | 1 \ \ - | 2 | Actual insertion gap | - | 3 / | Region controlled
-   * by one LineGap 1 | 4 <- delta = 4 - 1 = 3 | 2 | 5 / - | 6 ...
-   */
-  LineOnOtherInfo lineOnOther(DisplaySide mySide, int line) {
-    List<LineGap> lineGaps = gapList(mySide);
-    // Create a dummy LineGap for the search.
-    int ret = Collections.binarySearch(lineGaps, new LineGap(line));
-    if (ret == -1) {
-      return new LineOnOtherInfo(line, true);
-    }
-    LineGap lookup = lineGaps.get(0 <= ret ? ret : -ret - 2);
-    int start = lookup.start;
-    int end = lookup.end;
-    int delta = lookup.delta;
-    if (start <= line && line <= end && end != -1) { // Line falls within gap
-      return new LineOnOtherInfo(end + delta, false);
-    }
-    // Line after gap
-    return new LineOnOtherInfo(line + delta, true);
-  }
-
-  AlignedPair align(DisplaySide mySide, int line) {
-    List<LineGap> gaps = gapList(mySide);
-    int idx = Collections.binarySearch(gaps, new LineGap(line));
-    if (idx == -1) {
-      return new AlignedPair(line, line);
-    }
-
-    LineGap g = gaps.get(0 <= idx ? idx : -idx - 2);
-    if (g.start <= line && line <= g.end && g.end != -1) {
-      if (0 < g.start) {
-        // Line falls within this gap, use alignment before.
-        return new AlignedPair(g.start - 1, g.end + g.delta);
-      }
-      return new AlignedPair(g.end, g.end + g.delta + 1);
-    }
-    return new AlignedPair(line, line + g.delta);
-  }
-
-  private List<LineGap> gapList(DisplaySide mySide) {
-    return mySide == DisplaySide.A ? lineMapAtoB : lineMapBtoA;
-  }
-
-  static class AlignedPair {
-    final int src;
-    final int dst;
-
-    AlignedPair(int s, int d) {
-      src = s;
-      dst = d;
-    }
-  }
-
-  /**
-   * @field line The line number on the other side.
-   * @field aligned Whether the two lines are at the same height when displayed.
-   */
-  static class LineOnOtherInfo {
-    private int line;
-    private boolean aligned;
-
-    LineOnOtherInfo(int line, boolean aligned) {
-      this.line = line;
-      this.aligned = aligned;
-    }
-
-    int getLine() {
-      return line;
-    }
-
-    boolean isAligned() {
-      return aligned;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-      if (obj instanceof LineOnOtherInfo) {
-        LineOnOtherInfo other = (LineOnOtherInfo) obj;
-        return aligned == other.aligned && line == other.line;
-      }
-      return false;
-    }
-
-    @Override
-    public int hashCode() {
-      return Objects.hash(line, aligned);
-    }
-
-    @Override
-    public String toString() {
-      return line + " " + aligned;
-    }
-  }
-
-  /**
-   * Helper class to record line gap info and assist in calculation of line number on the other
-   * side.
-   *
-   * <p>For a mapping from A to B, where A is the side with an insertion:
-   *
-   * @field start The start line of the insertion in A.
-   * @field end The exclusive end line of the insertion in A.
-   * @field delta The offset added to A to get the line number in B calculated from end.
-   */
-  private static class LineGap implements Comparable<LineGap> {
-    private final int start;
-    private final int end;
-    private final int delta;
-
-    private LineGap(int start, int end, int delta) {
-      this.start = start;
-      this.end = end;
-      this.delta = delta;
-    }
-
-    private LineGap(int line) {
-      this(line, 0, 0);
-    }
-
-    @Override
-    public int compareTo(LineGap o) {
-      return start - o.start;
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/NoOpKeyCommand.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/NoOpKeyCommand.java
deleted file mode 100644
index 584232d..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/NoOpKeyCommand.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwtexpui.globalkey.client.KeyCommand;
-
-/** A KeyCommand that does nothing, used to display a help message */
-class NoOpKeyCommand extends KeyCommand {
-  NoOpKeyCommand(int mask, int key, String help) {
-    super(mask, key, help);
-  }
-
-  @Override
-  public void onKeyPress(KeyPressEvent event) {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PatchSetSelectBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PatchSetSelectBox.java
deleted file mode 100644
index 292773c..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PatchSetSelectBox.java
+++ /dev/null
@@ -1,240 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gerrit.client.DiffObject;
-import com.google.gerrit.client.Dispatcher;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.blame.BlameInfo;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.changes.Util;
-import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
-import com.google.gerrit.client.info.WebLinkInfo;
-import com.google.gerrit.client.patches.PatchUtil;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.InlineHyperlink;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Patch;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.ImageResourceRenderer;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtorm.client.KeyUtil;
-import java.util.List;
-import net.codemirror.lib.CodeMirror;
-
-/** HTMLPanel to select among patch sets */
-class PatchSetSelectBox extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, PatchSetSelectBox> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  interface BoxStyle extends CssResource {
-    String selected();
-  }
-
-  @UiField Image icon;
-  @UiField HTMLPanel linkPanel;
-  @UiField BoxStyle style;
-
-  @Nullable private final Project.NameKey project;
-  private final Change.Id changeId;
-
-  private DiffScreen parent;
-  private DisplaySide side;
-  private boolean sideA;
-  private String path;
-  private PatchSet.Id revision;
-  private DiffObject idActive;
-  private PatchSetSelectBox other;
-
-  PatchSetSelectBox(
-      DiffScreen parent,
-      DisplaySide side,
-      @Nullable Project.NameKey project,
-      Change.Id changeId,
-      DiffObject diffObject,
-      String path) {
-    initWidget(uiBinder.createAndBindUi(this));
-    icon.setTitle(PatchUtil.C.addFileCommentToolTip());
-    icon.addStyleName(Gerrit.RESOURCES.css().link());
-
-    this.parent = parent;
-    this.side = side;
-    this.sideA = side == DisplaySide.A;
-    this.project = project;
-    this.changeId = changeId;
-    this.revision = diffObject.asPatchSetId();
-    this.idActive = diffObject;
-    this.path = path;
-  }
-
-  void setUpPatchSetNav(
-      JsArray<RevisionInfo> list,
-      int parents,
-      DiffInfo.FileMeta meta,
-      boolean editExists,
-      boolean current,
-      boolean open,
-      boolean binary) {
-    InlineHyperlink selectedLink = null;
-    if (sideA) {
-      if (parents <= 1) {
-        InlineHyperlink link = createLink(PatchUtil.C.patchBase(), DiffObject.base());
-        linkPanel.add(link);
-        selectedLink = link;
-      } else {
-        for (int i = parents; i > 0; i--) {
-          PatchSet.Id id = new PatchSet.Id(changeId, -i);
-          InlineHyperlink link = createLink(Util.M.diffBaseParent(i), DiffObject.patchSet(id));
-          linkPanel.add(link);
-          if (revision != null && id.equals(revision)) {
-            selectedLink = link;
-          }
-        }
-        InlineHyperlink link = createLink(Util.C.autoMerge(), DiffObject.autoMerge());
-        linkPanel.add(link);
-        if (selectedLink == null) {
-          selectedLink = link;
-        }
-      }
-    }
-    for (int i = 0; i < list.length(); i++) {
-      RevisionInfo r = list.get(i);
-      InlineHyperlink link =
-          createLink(r.id(), DiffObject.patchSet(new PatchSet.Id(changeId, r._number())));
-      linkPanel.add(link);
-      if (revision != null && r.id().equals(revision.getId())) {
-        selectedLink = link;
-      }
-    }
-    if (selectedLink != null) {
-      selectedLink.setStyleName(style.selected());
-    }
-
-    if (meta == null) {
-      return;
-    }
-    if (!Patch.isMagic(path)) {
-      linkPanel.add(createDownloadLink());
-    }
-    if (!binary && open && !idActive.isBaseOrAutoMerge() && Gerrit.isSignedIn()) {
-      if ((editExists && idActive.isEdit()) || (!editExists && current)) {
-        linkPanel.add(createEditIcon());
-      }
-    }
-    List<WebLinkInfo> webLinks = Natives.asList(meta.webLinks());
-    if (webLinks != null) {
-      for (WebLinkInfo webLink : webLinks) {
-        linkPanel.add(webLink.toAnchor());
-      }
-    }
-  }
-
-  void setUpBlame(final CodeMirror cm, boolean isBase, PatchSet.Id rev, String path) {
-    if (!Patch.isMagic(path) && Gerrit.isSignedIn() && Gerrit.info().change().allowBlame()) {
-      Anchor blameIcon = createBlameIcon();
-      blameIcon.addClickHandler(
-          new ClickHandler() {
-            @Override
-            public void onClick(ClickEvent clickEvent) {
-              if (cm.extras().getBlameInfo() != null) {
-                cm.extras().toggleAnnotation();
-              } else {
-                ChangeApi.blame(Project.NameKey.asStringOrNull(project), rev, path, isBase)
-                    .get(
-                        new GerritCallback<JsArray<BlameInfo>>() {
-
-                          @Override
-                          public void onSuccess(JsArray<BlameInfo> lines) {
-                            cm.extras().toggleAnnotation(lines);
-                          }
-                        });
-              }
-            }
-          });
-      linkPanel.add(blameIcon);
-    }
-  }
-
-  private Widget createEditIcon() {
-    PatchSet.Id id =
-        idActive.isBaseOrAutoMerge() ? other.idActive.asPatchSetId() : idActive.asPatchSetId();
-    Anchor anchor =
-        new Anchor(
-            new ImageResourceRenderer().render(Gerrit.RESOURCES.edit()),
-            "#" + Dispatcher.toEditScreen(project, id, path));
-    anchor.setTitle(PatchUtil.C.edit());
-    return anchor;
-  }
-
-  private Anchor createBlameIcon() {
-    Anchor anchor = new Anchor(new ImageResourceRenderer().render(Gerrit.RESOURCES.blame()));
-    anchor.setTitle(PatchUtil.C.blame());
-    return anchor;
-  }
-
-  static void link(PatchSetSelectBox a, PatchSetSelectBox b) {
-    a.other = b;
-    b.other = a;
-  }
-
-  private InlineHyperlink createLink(String label, DiffObject id) {
-    assert other != null;
-    if (sideA) {
-      assert !other.idActive.isBaseOrAutoMerge();
-    }
-    DiffObject diffBase = sideA ? id : other.idActive;
-    DiffObject revision = sideA ? other.idActive : id;
-
-    return new InlineHyperlink(
-        label,
-        parent.isSideBySide()
-            ? Dispatcher.toSideBySide(project, diffBase, revision.asPatchSetId(), path)
-            : Dispatcher.toUnified(project, diffBase, revision.asPatchSetId(), path));
-  }
-
-  private Anchor createDownloadLink() {
-    DiffObject diffObject = idActive.isBaseOrAutoMerge() ? other.idActive : idActive;
-    String sideURL = idActive.isBaseOrAutoMerge() ? "1" : "0";
-    String base = GWT.getHostPageBaseURL() + "cat/";
-    Anchor anchor =
-        new Anchor(
-            new ImageResourceRenderer().render(Gerrit.RESOURCES.downloadIcon()),
-            base + KeyUtil.encode(diffObject.asPatchSetId() + "," + path) + "^" + sideURL);
-    anchor.setTitle(PatchUtil.C.download());
-    return anchor;
-  }
-
-  @UiHandler("icon")
-  void onIconClick(@SuppressWarnings("unused") ClickEvent e) {
-    parent.getCmFromSide(side).scrollToY(0);
-    parent.getCommentManager().insertNewDraft(side, 0);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PatchSetSelectBox.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PatchSetSelectBox.ui.xml
deleted file mode 100644
index 6e526ec..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PatchSetSelectBox.ui.xml
+++ /dev/null
@@ -1,74 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-  <ui:with field='res' type='com.google.gerrit.client.GerritResources'/>
-  <ui:with field='patchConstants'
-      type='com.google.gerrit.client.patches.PatchConstants'/>
-  <ui:style gss='false' type='com.google.gerrit.client.diff.PatchSetSelectBox.BoxStyle'>
-    @eval selectionColor com.google.gerrit.client.Gerrit.getTheme().selectionColor;
-    @eval trimColor com.google.gerrit.client.Gerrit.getTheme().trimColor;
-    .table {
-      width: 100%;
-    }
-    .linkCell {
-      text-align: center;
-      font-size: 12px;
-      white-space: normal;
-      font-family: sans-serif;
-      font-weight: bold;
-    }
-    .linkCell div {
-      padding-left: 3px;
-      padding-right: 3px;
-      vertical-align: middle;
-      display: inline-block;
-    }
-    .linkCell a {
-      padding-left: 3px;
-      padding-right: 3px;
-      text-decoration: none;
-      vertical-align: middle;
-      display: inline-block;
-    }
-    .selected {
-      font-weight: bold;
-      background-color: selectionColor;
-    }
-    .hidden {
-      visibility: hidden;
-    }
-    .iconCell {
-      width: 16px;
-    }
-  </ui:style>
-  <g:HTMLPanel>
-    <table class='{style.table}'>
-      <td class='{style.iconCell}'>
-        <g:Image ui:field='icon' resource='{res.addFileComment}'/>
-      </td>
-      <td class='{style.linkCell}'>
-        <g:HTMLPanel ui:field='linkPanel'>
-          <g:Label>
-            <ui:text from='{patchConstants.patchSet}'/>
-          </g:Label>
-        </g:HTMLPanel>
-      </td>
-    </table>
-  </g:HTMLPanel>
-</ui:UiBinder>
\ No newline at end of file
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesAction.java
deleted file mode 100644
index 2d4a4c4..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesAction.java
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gerrit.client.account.DiffPreferences;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.PopupPanel.PositionCallback;
-import com.google.gwt.user.client.ui.Widget;
-
-class PreferencesAction {
-  private final DiffScreen view;
-  private final DiffPreferences prefs;
-  private PopupPanel popup;
-  private PreferencesBox current;
-  private Widget partner;
-
-  PreferencesAction(DiffScreen view, DiffPreferences prefs) {
-    this.view = view;
-    this.prefs = prefs;
-  }
-
-  void update() {
-    if (current != null) {
-      current.set(prefs);
-    }
-  }
-
-  void show() {
-    if (popup != null) {
-      // Already open? Close the dialog.
-      hide();
-      return;
-    }
-
-    current = new PreferencesBox(view);
-    current.set(prefs);
-
-    popup = new PopupPanel(true, false);
-    popup.setStyleName(current.style.dialog());
-    popup.add(current);
-    popup.addAutoHidePartner(partner.getElement());
-    popup.addCloseHandler(
-        new CloseHandler<PopupPanel>() {
-          @Override
-          public void onClose(CloseEvent<PopupPanel> event) {
-            view.getCmFromSide(DisplaySide.B).focus();
-            popup = null;
-            current = null;
-          }
-        });
-    popup.setPopupPositionAndShow(
-        new PositionCallback() {
-          @Override
-          public void setPosition(int offsetWidth, int offsetHeight) {
-            popup.setPopupPosition(300, 120);
-          }
-        });
-    current.setFocus(true);
-  }
-
-  void hide() {
-    if (popup != null) {
-      popup.hide();
-      popup = null;
-      current = null;
-    }
-  }
-
-  void setPartner(Widget w) {
-    partner = w;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesBox.java
deleted file mode 100644
index ed4ac25..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesBox.java
+++ /dev/null
@@ -1,644 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import static com.google.gerrit.extensions.client.DiffPreferencesInfo.DEFAULT_CONTEXT;
-import static com.google.gerrit.extensions.client.DiffPreferencesInfo.WHOLE_FILE_CONTEXT;
-import static com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace.IGNORE_ALL;
-import static com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace.IGNORE_LEADING_AND_TRAILING;
-import static com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace.IGNORE_NONE;
-import static com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace.IGNORE_TRAILING;
-import static com.google.gwt.event.dom.client.KeyCodes.KEY_ESCAPE;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.account.AccountApi;
-import com.google.gerrit.client.account.DiffPreferences;
-import com.google.gerrit.client.patches.PatchUtil;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.NpIntTextBox;
-import com.google.gerrit.extensions.client.DiffPreferencesInfo;
-import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace;
-import com.google.gerrit.extensions.client.Theme;
-import com.google.gerrit.reviewdb.client.Patch;
-import com.google.gerrit.reviewdb.client.Patch.ChangeType;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.Style.Visibility;
-import com.google.gwt.event.dom.client.ChangeEvent;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.KeyDownEvent;
-import com.google.gwt.event.dom.client.KeyDownHandler;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.ListBox;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.ToggleButton;
-import com.google.gwt.user.client.ui.UIObject;
-import java.util.Objects;
-import net.codemirror.lib.CodeMirror;
-import net.codemirror.mode.ModeInfo;
-import net.codemirror.mode.ModeInjector;
-import net.codemirror.theme.ThemeLoader;
-
-/** Displays current diff preferences. */
-public class PreferencesBox extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, PreferencesBox> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  public interface Style extends CssResource {
-    String dialog();
-  }
-
-  private final DiffScreen view;
-  private DiffPreferences prefs;
-  private int contextLastValue;
-  private Timer updateContextTimer;
-
-  @UiField Style style;
-  @UiField Element header;
-  @UiField Anchor close;
-  @UiField ListBox ignoreWhitespace;
-  @UiField NpIntTextBox tabWidth;
-  @UiField NpIntTextBox lineLength;
-  @UiField NpIntTextBox context;
-  @UiField NpIntTextBox cursorBlinkRate;
-  @UiField CheckBox contextEntireFile;
-  @UiField ToggleButton intralineDifference;
-  @UiField ToggleButton syntaxHighlighting;
-  @UiField ToggleButton whitespaceErrors;
-  @UiField ToggleButton showTabs;
-  @UiField ToggleButton lineNumbers;
-  @UiField Element leftSideLabel;
-  @UiField ToggleButton leftSide;
-  @UiField ToggleButton emptyPane;
-  @UiField ToggleButton topMenu;
-  @UiField ToggleButton autoHideDiffTableHeader;
-  @UiField ToggleButton manualReview;
-  @UiField ToggleButton expandAllComments;
-  @UiField ToggleButton renderEntireFile;
-  @UiField ToggleButton matchBrackets;
-  @UiField ToggleButton lineWrapping;
-  @UiField ToggleButton skipDeleted;
-  @UiField ToggleButton skipUnchanged;
-  @UiField ToggleButton skipUncommented;
-  @UiField ListBox theme;
-  @UiField Element modeLabel;
-  @UiField ListBox mode;
-  @UiField Button apply;
-  @UiField Button save;
-
-  public PreferencesBox(DiffScreen view) {
-    this.view = view;
-
-    initWidget(uiBinder.createAndBindUi(this));
-    initIgnoreWhitespace();
-    initTheme();
-
-    if (view != null) {
-      initMode();
-    } else {
-      UIObject.setVisible(header, false);
-      apply.getElement().getStyle().setVisibility(Visibility.HIDDEN);
-    }
-  }
-
-  @Override
-  public void onLoad() {
-    super.onLoad();
-
-    save.setVisible(Gerrit.isSignedIn());
-
-    if (view != null) {
-      addDomHandler(
-          new KeyDownHandler() {
-            @Override
-            public void onKeyDown(KeyDownEvent event) {
-              if (event.getNativeKeyCode() == KEY_ESCAPE || event.getNativeKeyCode() == ',') {
-                close();
-              }
-            }
-          },
-          KeyDownEvent.getType());
-
-      updateContextTimer =
-          new Timer() {
-            @Override
-            public void run() {
-              if (prefs.context() == WHOLE_FILE_CONTEXT) {
-                contextEntireFile.setValue(true);
-              }
-              if (view.canRenderEntireFile(prefs)) {
-                renderEntireFile.setEnabled(true);
-                renderEntireFile.setValue(prefs.renderEntireFile());
-              } else {
-                renderEntireFile.setValue(false);
-                renderEntireFile.setEnabled(false);
-              }
-              view.setContext(prefs.context());
-            }
-          };
-    }
-  }
-
-  public Style getStyle() {
-    return style;
-  }
-
-  public void set(DiffPreferences prefs) {
-    this.prefs = prefs;
-
-    setIgnoreWhitespace(prefs.ignoreWhitespace());
-    tabWidth.setIntValue(prefs.tabSize());
-    if (view != null && Patch.COMMIT_MSG.equals(view.path)) {
-      lineLength.setEnabled(false);
-      lineLength.setIntValue(72);
-    } else {
-      lineLength.setEnabled(true);
-      lineLength.setIntValue(prefs.lineLength());
-    }
-    cursorBlinkRate.setIntValue(prefs.cursorBlinkRate());
-    syntaxHighlighting.setValue(prefs.syntaxHighlighting());
-    whitespaceErrors.setValue(prefs.showWhitespaceErrors());
-    showTabs.setValue(prefs.showTabs());
-    lineNumbers.setValue(prefs.showLineNumbers());
-    emptyPane.setValue(!prefs.hideEmptyPane());
-    if (view != null) {
-      leftSide.setValue(view.getDiffTable().isVisibleA());
-      leftSide.setEnabled(
-          !(prefs.hideEmptyPane() && view.getDiffTable().getChangeType() == ChangeType.ADDED));
-    } else {
-      UIObject.setVisible(leftSideLabel, false);
-      leftSide.setVisible(false);
-    }
-    topMenu.setValue(!prefs.hideTopMenu());
-    autoHideDiffTableHeader.setValue(!prefs.autoHideDiffTableHeader());
-    manualReview.setValue(prefs.manualReview());
-    expandAllComments.setValue(prefs.expandAllComments());
-    matchBrackets.setValue(prefs.matchBrackets());
-    lineWrapping.setValue(prefs.lineWrapping());
-    skipDeleted.setValue(!prefs.skipDeleted());
-    skipUnchanged.setValue(!prefs.skipUnchanged());
-    skipUncommented.setValue(!prefs.skipUncommented());
-    setTheme(prefs.theme());
-
-    if (view == null || view.canRenderEntireFile(prefs)) {
-      renderEntireFile.setValue(prefs.renderEntireFile());
-      renderEntireFile.setEnabled(true);
-    } else {
-      renderEntireFile.setValue(false);
-      renderEntireFile.setEnabled(false);
-    }
-
-    if (view != null) {
-      mode.setEnabled(prefs.syntaxHighlighting());
-      if (prefs.syntaxHighlighting()) {
-        setMode(view.getCmFromSide(DisplaySide.B).getStringOption("mode"));
-      }
-    } else {
-      UIObject.setVisible(modeLabel, false);
-      mode.setVisible(false);
-    }
-
-    if (view != null) {
-      switch (view.getIntraLineStatus()) {
-        case OFF:
-        case OK:
-          intralineDifference.setValue(prefs.intralineDifference());
-          break;
-
-        case TIMEOUT:
-        case FAILURE:
-          intralineDifference.setValue(false);
-          intralineDifference.setEnabled(false);
-          break;
-      }
-    } else {
-      intralineDifference.setValue(prefs.intralineDifference());
-    }
-
-    if (prefs.context() == WHOLE_FILE_CONTEXT) {
-      contextLastValue = DEFAULT_CONTEXT;
-      context.setText("");
-      contextEntireFile.setValue(true);
-    } else {
-      context.setIntValue(prefs.context());
-      contextEntireFile.setValue(false);
-    }
-  }
-
-  @UiHandler("ignoreWhitespace")
-  void onIgnoreWhitespace(@SuppressWarnings("unused") ChangeEvent e) {
-    prefs.ignoreWhitespace(
-        Whitespace.valueOf(ignoreWhitespace.getValue(ignoreWhitespace.getSelectedIndex())));
-    if (view != null) {
-      view.reloadDiffInfo();
-    }
-  }
-
-  @UiHandler("intralineDifference")
-  void onIntralineDifference(ValueChangeEvent<Boolean> e) {
-    prefs.intralineDifference(Boolean.valueOf(e.getValue()));
-    if (view != null) {
-      view.setShowIntraline(prefs.intralineDifference());
-    }
-  }
-
-  @UiHandler("context")
-  void onContextKey(KeyPressEvent e) {
-    if (contextEntireFile.getValue()) {
-      char c = e.getCharCode();
-      if ('0' <= c && c <= '9') {
-        contextEntireFile.setValue(false);
-      }
-    }
-  }
-
-  @UiHandler("context")
-  void onContext(ValueChangeEvent<String> e) {
-    String v = e.getValue();
-    int c;
-    if (v != null && v.length() > 0) {
-      c = Math.min(Math.max(0, Integer.parseInt(v)), 32767);
-      contextEntireFile.setValue(false);
-    } else if (v == null || v.isEmpty()) {
-      c = WHOLE_FILE_CONTEXT;
-    } else {
-      return;
-    }
-    prefs.context(c);
-    if (view != null) {
-      updateContextTimer.schedule(200);
-    }
-  }
-
-  @UiHandler("contextEntireFile")
-  void onContextEntireFile(ValueChangeEvent<Boolean> e) {
-    // If a click arrives too fast after onContext applied an update
-    // the user committed the context line update by clicking on the
-    // whole file checkmark. Drop this event, but transfer focus.
-    if (e.getValue()) {
-      contextLastValue = context.getIntValue();
-      context.setText("");
-      prefs.context(WHOLE_FILE_CONTEXT);
-    } else {
-      prefs.context(contextLastValue > 0 ? contextLastValue : DEFAULT_CONTEXT);
-      context.setIntValue(prefs.context());
-      context.setFocus(true);
-      context.setSelectionRange(0, context.getText().length());
-    }
-    if (view != null) {
-      updateContextTimer.schedule(200);
-    }
-  }
-
-  @UiHandler("tabWidth")
-  void onTabWidth(ValueChangeEvent<String> e) {
-    String v = e.getValue();
-    if (v != null && v.length() > 0) {
-      prefs.tabSize(Math.max(1, Integer.parseInt(v)));
-      if (view != null) {
-        view.operation(
-            () -> {
-              int size = prefs.tabSize();
-              for (CodeMirror cm : view.getCms()) {
-                cm.setOption("tabSize", size);
-              }
-            });
-      }
-    }
-  }
-
-  @UiHandler("lineLength")
-  void onLineLength(ValueChangeEvent<String> e) {
-    String v = e.getValue();
-    if (v != null && v.length() > 0) {
-      prefs.lineLength(Math.max(1, Integer.parseInt(v)));
-      if (view != null) {
-        view.operation(() -> view.setLineLength(prefs.lineLength()));
-      }
-    }
-  }
-
-  @UiHandler("expandAllComments")
-  void onExpandAllComments(ValueChangeEvent<Boolean> e) {
-    prefs.expandAllComments(e.getValue());
-    if (view != null) {
-      view.getCommentManager().setExpandAllComments(prefs.expandAllComments());
-    }
-  }
-
-  @UiHandler("cursorBlinkRate")
-  void onCursoBlinkRate(ValueChangeEvent<String> e) {
-    String v = e.getValue();
-    if (v != null && v.length() > 0) {
-      // A negative value hides the cursor entirely:
-      // don't let user shoot himself in the foot.
-      prefs.cursorBlinkRate(Math.max(0, Integer.parseInt(v)));
-      view.getCmFromSide(DisplaySide.A).setOption("cursorBlinkRate", prefs.cursorBlinkRate());
-      view.getCmFromSide(DisplaySide.B).setOption("cursorBlinkRate", prefs.cursorBlinkRate());
-    }
-  }
-
-  @UiHandler("showTabs")
-  void onShowTabs(ValueChangeEvent<Boolean> e) {
-    prefs.showTabs(e.getValue());
-    if (view != null) {
-      view.setShowTabs(prefs.showTabs());
-    }
-  }
-
-  @UiHandler("lineNumbers")
-  void onLineNumbers(ValueChangeEvent<Boolean> e) {
-    prefs.showLineNumbers(e.getValue());
-    if (view != null) {
-      view.setShowLineNumbers(prefs.showLineNumbers());
-    }
-  }
-
-  @UiHandler("leftSide")
-  void onLeftSide(ValueChangeEvent<Boolean> e) {
-    if (view.getDiffTable() instanceof SideBySideTable) {
-      ((SideBySideTable) view.getDiffTable()).setVisibleA(e.getValue());
-    }
-  }
-
-  @UiHandler("emptyPane")
-  void onHideEmptyPane(ValueChangeEvent<Boolean> e) {
-    prefs.hideEmptyPane(!e.getValue());
-    if (view != null) {
-      view.getDiffTable().setHideEmptyPane(prefs.hideEmptyPane());
-      if (prefs.hideEmptyPane()) {
-        if (view.getDiffTable().getChangeType() == ChangeType.ADDED) {
-          leftSide.setValue(false);
-          leftSide.setEnabled(false);
-        }
-      } else {
-        leftSide.setValue(view.getDiffTable().isVisibleA());
-        leftSide.setEnabled(true);
-      }
-    }
-  }
-
-  @UiHandler("topMenu")
-  void onTopMenu(ValueChangeEvent<Boolean> e) {
-    prefs.hideTopMenu(!e.getValue());
-    if (view != null) {
-      Gerrit.setHeaderVisible(!prefs.hideTopMenu());
-      view.resizeCodeMirror();
-    }
-  }
-
-  @UiHandler("autoHideDiffTableHeader")
-  void onAutoHideDiffTableHeader(ValueChangeEvent<Boolean> e) {
-    prefs.autoHideDiffTableHeader(!e.getValue());
-    if (view != null) {
-      view.setAutoHideDiffHeader(!e.getValue());
-    }
-  }
-
-  @UiHandler("manualReview")
-  void onManualReview(ValueChangeEvent<Boolean> e) {
-    prefs.manualReview(e.getValue());
-  }
-
-  @UiHandler("syntaxHighlighting")
-  void onSyntaxHighlighting(ValueChangeEvent<Boolean> e) {
-    prefs.syntaxHighlighting(e.getValue());
-    if (view != null) {
-      mode.setEnabled(prefs.syntaxHighlighting());
-      if (prefs.syntaxHighlighting()) {
-        setMode(view.getContentType());
-      }
-      view.setSyntaxHighlighting(prefs.syntaxHighlighting());
-    }
-  }
-
-  @UiHandler("mode")
-  void onMode(@SuppressWarnings("unused") ChangeEvent e) {
-    String mode = getSelectedMode();
-    prefs.syntaxHighlighting(true);
-    syntaxHighlighting.setValue(true, false);
-    new ModeInjector()
-        .add(mode)
-        .inject(
-            new GerritCallback<Void>() {
-              @Override
-              public void onSuccess(Void result) {
-                if (prefs.syntaxHighlighting()
-                    && Objects.equals(mode, getSelectedMode())
-                    && view.isAttached()) {
-                  view.operation(
-                      () -> {
-                        view.getCmFromSide(DisplaySide.A).setOption("mode", mode);
-                        view.getCmFromSide(DisplaySide.B).setOption("mode", mode);
-                      });
-                }
-              }
-            });
-  }
-
-  private String getSelectedMode() {
-    String m = mode.getValue(mode.getSelectedIndex());
-    return m != null && !m.isEmpty() ? m : null;
-  }
-
-  @UiHandler("whitespaceErrors")
-  void onWhitespaceErrors(ValueChangeEvent<Boolean> e) {
-    prefs.showWhitespaceErrors(e.getValue());
-    if (view != null) {
-      view.operation(
-          () -> {
-            boolean s = prefs.showWhitespaceErrors();
-            for (CodeMirror cm : view.getCms()) {
-              cm.setOption("showTrailingSpace", s);
-            }
-          });
-    }
-  }
-
-  @UiHandler("renderEntireFile")
-  void onRenderEntireFile(ValueChangeEvent<Boolean> e) {
-    prefs.renderEntireFile(e.getValue());
-    if (view != null) {
-      view.updateRenderEntireFile();
-    }
-  }
-
-  @UiHandler("matchBrackets")
-  void onMatchBrackets(ValueChangeEvent<Boolean> e) {
-    prefs.matchBrackets(e.getValue());
-    view.getCmFromSide(DisplaySide.A).setOption("matchBrackets", prefs.matchBrackets());
-    view.getCmFromSide(DisplaySide.B).setOption("matchBrackets", prefs.matchBrackets());
-  }
-
-  @UiHandler("lineWrapping")
-  void onLineWrapping(ValueChangeEvent<Boolean> e) {
-    prefs.lineWrapping(e.getValue());
-    view.getCmFromSide(DisplaySide.A).setOption("lineWrapping", prefs.lineWrapping());
-    view.getCmFromSide(DisplaySide.B).setOption("lineWrapping", prefs.lineWrapping());
-  }
-
-  @UiHandler("skipDeleted")
-  void onSkipDeleted(ValueChangeEvent<Boolean> e) {
-    prefs.skipDeleted(!e.getValue());
-    // TODO: Update the navigation links on the current DiffScreen
-  }
-
-  @UiHandler("skipUnchanged")
-  void onSkipUnchanged(ValueChangeEvent<Boolean> e) {
-    prefs.skipUnchanged(!e.getValue());
-    // TODO: Update the navigation links on the current DiffScreen
-  }
-
-  @UiHandler("skipUncommented")
-  void onSkipUncommented(ValueChangeEvent<Boolean> e) {
-    prefs.skipUncommented(!e.getValue());
-    // TODO: Update the navigation links on the current DiffScreen
-  }
-
-  @UiHandler("theme")
-  void onTheme(@SuppressWarnings("unused") ChangeEvent e) {
-    Theme newTheme = getSelectedTheme();
-    prefs.theme(newTheme);
-    if (view != null) {
-      ThemeLoader.loadTheme(
-          newTheme,
-          new GerritCallback<Void>() {
-            @Override
-            public void onSuccess(Void result) {
-              view.operation(
-                  () -> {
-                    if (getSelectedTheme() == newTheme && isAttached()) {
-                      String t = newTheme.name().toLowerCase();
-                      view.getCmFromSide(DisplaySide.A).setOption("theme", t);
-                      view.getCmFromSide(DisplaySide.B).setOption("theme", t);
-                      view.setThemeStyles(newTheme.isDark());
-                    }
-                  });
-            }
-          });
-    }
-  }
-
-  private Theme getSelectedTheme() {
-    return Theme.valueOf(theme.getValue(theme.getSelectedIndex()));
-  }
-
-  @UiHandler("apply")
-  void onApply(@SuppressWarnings("unused") ClickEvent e) {
-    close();
-  }
-
-  @UiHandler("save")
-  void onSave(@SuppressWarnings("unused") ClickEvent e) {
-    AccountApi.putDiffPreferences(
-        prefs,
-        new GerritCallback<DiffPreferences>() {
-          @Override
-          public void onSuccess(DiffPreferences result) {
-            DiffPreferencesInfo p = new DiffPreferencesInfo();
-            result.copyTo(p);
-            Gerrit.setDiffPreferences(p);
-          }
-        });
-    if (view != null) {
-      close();
-    }
-  }
-
-  @UiHandler("close")
-  void onClose(ClickEvent e) {
-    e.preventDefault();
-    close();
-  }
-
-  void setFocus(boolean focus) {
-    ignoreWhitespace.setFocus(focus);
-  }
-
-  private void close() {
-    ((PopupPanel) getParent()).hide();
-  }
-
-  private void setIgnoreWhitespace(Whitespace v) {
-    String name = v != null ? v.name() : IGNORE_NONE.name();
-    for (int i = 0; i < ignoreWhitespace.getItemCount(); i++) {
-      if (ignoreWhitespace.getValue(i).equals(name)) {
-        ignoreWhitespace.setSelectedIndex(i);
-        return;
-      }
-    }
-    ignoreWhitespace.setSelectedIndex(0);
-  }
-
-  private void initIgnoreWhitespace() {
-    ignoreWhitespace.addItem(PatchUtil.C.whitespaceIGNORE_NONE(), IGNORE_NONE.name());
-    ignoreWhitespace.addItem(PatchUtil.C.whitespaceIGNORE_TRAILING(), IGNORE_TRAILING.name());
-    ignoreWhitespace.addItem(
-        PatchUtil.C.whitespaceIGNORE_LEADING_AND_TRAILING(), IGNORE_LEADING_AND_TRAILING.name());
-    ignoreWhitespace.addItem(PatchUtil.C.whitespaceIGNORE_ALL(), IGNORE_ALL.name());
-  }
-
-  private void initMode() {
-    mode.addItem("", "");
-    for (ModeInfo m : Natives.asList(ModeInfo.all())) {
-      mode.addItem(m.name(), m.mime());
-    }
-  }
-
-  private void setMode(String modeType) {
-    if (modeType != null && !modeType.isEmpty()) {
-      ModeInfo m = ModeInfo.findModeByMIME(modeType);
-      if (m != null) {
-        for (int i = 0; i < mode.getItemCount(); i++) {
-          if (mode.getValue(i).equals(m.mime())) {
-            mode.setSelectedIndex(i);
-            return;
-          }
-        }
-      }
-    }
-    mode.setSelectedIndex(0);
-  }
-
-  private void setTheme(Theme v) {
-    String name = v != null ? v.name() : Theme.DEFAULT.name();
-    for (int i = 0; i < theme.getItemCount(); i++) {
-      if (theme.getValue(i).equals(name)) {
-        theme.setSelectedIndex(i);
-        return;
-      }
-    }
-    theme.setSelectedIndex(0);
-  }
-
-  private void initTheme() {
-    for (Theme t : Theme.values()) {
-      theme.addItem(t.name().toLowerCase(), t.name());
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesBox.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesBox.ui.xml
deleted file mode 100644
index 4465d63..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesBox.ui.xml
+++ /dev/null
@@ -1,341 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'
-    xmlns:x='urn:import:com.google.gerrit.client.ui'>
-  <ui:style gss='false' type='com.google.gerrit.client.diff.PreferencesBox.Style'>
-    @external .gwt-TextBox;
-    @external .gwt-ToggleButton .html-face;
-    @external .gwt-ToggleButton-up;
-    @external .gwt-ToggleButton-up-hovering;
-    @external .gwt-ToggleButton-up-disabled;
-    @external .gwt-ToggleButton-down;
-    @external .gwt-ToggleButton-down-hovering;
-    @external .gwt-ToggleButton-down-disabled;
-
-    .dialog {
-      background: rgba(0, 0, 0, 0.85) none repeat scroll 0 50%;
-      color: #ffffff;
-      font-family: arial,sans-serif;
-      font-weight: bold;
-      overflow: auto !important;
-      bottom: 0;
-      text-align: left;
-      text-shadow: 1px 1px 7px #000000;
-      min-width: 300px;
-      z-index: 200;
-      border-radius: 10px;
-    }
-
-    @if user.agent safari {
-      .dialog {
-        \-webkit-border-radius: 10px;
-      }
-    }
-
-    @if user.agent gecko1_8 {
-      .dialog {
-        \-moz-border-radius: 10px;
-      }
-    }
-
-    .box { margin: 10px; }
-    .box .gwt-TextBox { padding: 0; }
-    .context { vertical-align: bottom; }
-
-    .table tr { min-height: 23px; }
-    .table th,
-    .table td {
-      white-space: nowrap;
-      color: #ffffff;
-    }
-    .table th {
-      padding-right: 8px;
-      text-align: right;
-    }
-
-    .box a,
-    .box a:visited,
-    .box a:hover {
-      color: #dddd00;
-    }
-
-    .box input.gwt-TextBox:disabled {
-      background-color: #cacaca;
-    }
-
-    .box .gwt-ToggleButton {
-      position: relative;
-      height: 19px;
-      width: 140px;
-      background: #fff;
-      color: #000;
-      text-shadow: none;
-    }
-    .box .gwt-ToggleButton .html-face {
-      position: absolute;
-      top: 0;
-      width: 68px;
-      height: 17px;
-      line-height: 17px;
-      text-align: center;
-      border-width: 1px;
-    }
-
-    .box .gwt-ToggleButton-up,
-    .box .gwt-ToggleButton-up-hovering,
-    .box .gwt-ToggleButton-up-disabled,
-    .box .gwt-ToggleButton-down,
-    .box .gwt-ToggleButton-down-hovering,
-    .box .gwt-ToggleButton-down-disabled {
-      padding: 0;
-      border: 0;
-    }
-    .box .gwt-ToggleButton-up .html-face,
-    .box .gwt-ToggleButton-up-hovering .html-face {
-      left: 0;
-      background: #cacaca;
-      border-style: outset;
-    }
-    .box .gwt-ToggleButton-down .html-face,
-    .box .gwt-ToggleButton-down-hovering .html-face {
-      right: 0;
-      background: #bcf;
-      border-style: inset;
-    }
-
-    .box button {
-      margin: 6px 3px 0 0;
-      border-color: rgba(0, 0, 0, 0.1);
-      text-align: center;
-      font-size: 8pt;
-      font-weight: bold;
-      border: 1px solid;
-      cursor: pointer;
-      color: #444;
-      background-color: #f5f5f5;
-      background-image: -webkit-linear-gradient(top, #f5f5f5, #f1f1f1);
-      -webkit-border-radius: 2px;
-      -webkit-box-sizing: content-box;
-    }
-    .box button div {
-      color: #444;
-      height: 10px;
-      min-width: 54px;
-      line-height: 10px;
-      white-space: nowrap;
-    }
-
-    button.apply {
-      background-color: #4d90fe;
-      background-image: -webkit-linear-gradient(top, #4d90fe, #4d90fe);
-    }
-    button.apply div { color: #fff; }
-
-    button.save {
-      margin-left: 10px;
-      color: #d14836;
-      background-color: #d14836;
-      background-image: -webkit-linear-gradient(top, #d14836, #d14836);
-    }
-    button.save div { color: #fff; }
-  </ui:style>
-
-  <g:HTMLPanel styleName='{style.box}'>
-    <div ui:field='header'>
-      <table style='width: 100%'>
-        <tr>
-          <td><ui:msg>Diff Preferences</ui:msg></td>
-          <td style='text-align: right'>
-            <g:Anchor ui:field='close' href='javascript:;'><ui:msg>Close</ui:msg></g:Anchor>
-          </td>
-        </tr>
-      </table>
-      <hr/>
-    </div>
-    <table class='{style.table}'>
-      <tr>
-        <th><ui:msg>Theme</ui:msg></th>
-        <td><g:ListBox ui:field='theme'/></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Ignore Whitespace</ui:msg></th>
-        <td><g:ListBox ui:field='ignoreWhitespace'/></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Tab Width</ui:msg></th>
-        <td><x:NpIntTextBox ui:field='tabWidth'
-            visibleLength='4'
-            alignment='RIGHT'/></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Columns</ui:msg></th>
-        <td><x:NpIntTextBox ui:field='lineLength'
-            visibleLength='4'
-            alignment='RIGHT'/></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Lines of Context</ui:msg></th>
-        <td><ui:msg><x:NpIntTextBox ui:field='context'
-            addStyleNames='{style.context}'
-            visibleLength='4'
-            alignment='RIGHT'/>
-          or <g:CheckBox ui:field='contextEntireFile'>entire file</g:CheckBox></ui:msg></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Cursor Blink Rate</ui:msg></th>
-        <td><x:NpIntTextBox ui:field='cursorBlinkRate'
-            visibleLength='4'
-            alignment='RIGHT'/></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Intraline Difference</ui:msg></th>
-        <td><g:ToggleButton ui:field='intralineDifference'>
-          <g:upFace><ui:msg>Hide</ui:msg></g:upFace>
-          <g:downFace><ui:msg>Show</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Syntax Highlighting</ui:msg></th>
-        <td><g:ToggleButton ui:field='syntaxHighlighting'>
-          <g:upFace><ui:msg>Hide</ui:msg></g:upFace>
-          <g:downFace><ui:msg>Show</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><div ui:field='modeLabel'><ui:msg>Language</ui:msg></div></th>
-        <td><g:ListBox ui:field='mode'/></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Whitespace Errors</ui:msg></th>
-        <td><g:ToggleButton ui:field='whitespaceErrors'>
-          <g:upFace><ui:msg>Hide</ui:msg></g:upFace>
-          <g:downFace><ui:msg>Show</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Show Tabs</ui:msg></th>
-        <td><g:ToggleButton ui:field='showTabs'>
-          <g:upFace><ui:msg>Hide</ui:msg></g:upFace>
-          <g:downFace><ui:msg>Show</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Line Numbers</ui:msg></th>
-        <td><g:ToggleButton ui:field='lineNumbers'>
-          <g:upFace><ui:msg>Hide</ui:msg></g:upFace>
-          <g:downFace><ui:msg>Show</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Empty Pane</ui:msg></th>
-        <td><g:ToggleButton ui:field='emptyPane'>
-          <g:upFace><ui:msg>Hide</ui:msg></g:upFace>
-          <g:downFace><ui:msg>Show</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><div ui:field='leftSideLabel'><ui:msg>Left Side</ui:msg></div></th>
-        <td><g:ToggleButton ui:field='leftSide'>
-          <g:upFace><ui:msg>Hide</ui:msg></g:upFace>
-          <g:downFace><ui:msg>Show</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Top Menu</ui:msg></th>
-        <td><g:ToggleButton ui:field='topMenu'>
-          <g:upFace><ui:msg>Hide</ui:msg></g:upFace>
-          <g:downFace><ui:msg>Show</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Auto Hide Diff Table Header</ui:msg></th>
-        <td><g:ToggleButton ui:field='autoHideDiffTableHeader'>
-          <g:upFace><ui:msg>Yes</ui:msg></g:upFace>
-          <g:downFace><ui:msg>No</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Mark Reviewed</ui:msg></th>
-        <td><g:ToggleButton ui:field='manualReview'>
-          <g:upFace><ui:msg>Automatic</ui:msg></g:upFace>
-          <g:downFace><ui:msg>Manual</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Expand All Comments</ui:msg></th>
-        <td><g:ToggleButton ui:field='expandAllComments'>
-          <g:upFace><ui:msg>Collapse</ui:msg></g:upFace>
-          <g:downFace><ui:msg>Expand</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Render</ui:msg></th>
-        <td><g:ToggleButton ui:field='renderEntireFile'>
-          <g:upFace><ui:msg>Fast</ui:msg></g:upFace>
-          <g:downFace><ui:msg>Slow</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Match Brackets</ui:msg></th>
-        <td><g:ToggleButton ui:field='matchBrackets'>
-          <g:upFace><ui:msg>Off</ui:msg></g:upFace>
-          <g:downFace><ui:msg>On</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Line Wrapping</ui:msg></th>
-        <td><g:ToggleButton ui:field='lineWrapping'>
-          <g:upFace><ui:msg>Off</ui:msg></g:upFace>
-          <g:downFace><ui:msg>On</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Skip Deleted Files</ui:msg></th>
-        <td><g:ToggleButton ui:field='skipDeleted'>
-          <g:upFace><ui:msg>Yes</ui:msg></g:upFace>
-          <g:downFace><ui:msg>No</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Skip Unchanged Files</ui:msg></th>
-        <td><g:ToggleButton ui:field='skipUnchanged'>
-          <g:upFace><ui:msg>Yes</ui:msg></g:upFace>
-          <g:downFace><ui:msg>No</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Skip Uncommented Files</ui:msg></th>
-        <td><g:ToggleButton ui:field='skipUncommented'>
-          <g:upFace><ui:msg>Yes</ui:msg></g:upFace>
-          <g:downFace><ui:msg>No</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <td></td>
-        <td>
-          <g:Button ui:field='apply' styleName='{style.apply}'>
-            <div><ui:msg>Apply</ui:msg></div>
-          </g:Button>
-          <g:Button ui:field='save' styleName='{style.save}'>
-            <div><ui:msg>Save</ui:msg></div>
-          </g:Button>
-        </td>
-      </tr>
-    </table>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PublishedBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PublishedBox.java
deleted file mode 100644
index 1ddf895..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PublishedBox.java
+++ /dev/null
@@ -1,239 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gerrit.client.AvatarImage;
-import com.google.gerrit.client.Dispatcher;
-import com.google.gerrit.client.FormatUtil;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.api.ApiGlue;
-import com.google.gerrit.client.change.ReplyBox;
-import com.google.gerrit.client.changes.CommentApi;
-import com.google.gerrit.client.changes.CommentInfo;
-import com.google.gerrit.client.changes.Util;
-import com.google.gerrit.client.patches.PatchUtil;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.ui.CommentLinkProcessor;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-
-/** An HtmlPanel for displaying a published comment */
-class PublishedBox extends CommentBox {
-  interface Binder extends UiBinder<HTMLPanel, PublishedBox> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  interface Style extends CssResource {
-    String closed();
-  }
-
-  private final PatchSet.Id psId;
-  @Nullable private final Project.NameKey project;
-  private final CommentInfo comment;
-  private final DisplaySide displaySide;
-  private DraftBox replyBox;
-
-  @UiField Style style;
-  @UiField Widget header;
-  @UiField Element name;
-  @UiField Element summary;
-  @UiField Element date;
-  @UiField Element message;
-  @UiField Element buttons;
-  @UiField Button reply;
-  @UiField Button done;
-  @UiField Button fix;
-
-  @UiField(provided = true)
-  AvatarImage avatar;
-
-  PublishedBox(
-      CommentGroup group,
-      CommentLinkProcessor clp,
-      @Nullable Project.NameKey project,
-      PatchSet.Id psId,
-      CommentInfo info,
-      DisplaySide displaySide,
-      boolean open) {
-    super(group, info.range());
-
-    this.psId = psId;
-    this.project = project;
-    this.comment = info;
-    this.displaySide = displaySide;
-
-    if (info.author() != null) {
-      avatar = new AvatarImage(info.author());
-      avatar.setSize("", "");
-    } else {
-      avatar = new AvatarImage();
-    }
-
-    initWidget(uiBinder.createAndBindUi(this));
-    header.addDomHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            setOpen(!isOpen());
-          }
-        },
-        ClickEvent.getType());
-
-    name.setInnerText(authorName(info));
-    date.setInnerText(FormatUtil.shortFormatDayTime(info.updated()));
-    if (info.message() != null) {
-      String msg = info.message().trim();
-      summary.setInnerText(msg);
-      message.setInnerSafeHtml(clp.apply(new SafeHtmlBuilder().append(msg).wikify()));
-      ApiGlue.fireEvent("comment", message);
-    }
-
-    fix.setVisible(open);
-  }
-
-  @Override
-  CommentInfo getCommentInfo() {
-    return comment;
-  }
-
-  @Override
-  boolean isOpen() {
-    return UIObject.isVisible(message);
-  }
-
-  @Override
-  void setOpen(boolean open) {
-    UIObject.setVisible(summary, !open);
-    UIObject.setVisible(message, open);
-    UIObject.setVisible(buttons, open && replyBox == null);
-    if (open) {
-      removeStyleName(style.closed());
-    } else {
-      addStyleName(style.closed());
-    }
-    super.setOpen(open);
-  }
-
-  void setReplyBox(DraftBox box) {
-    replyBox = box;
-    UIObject.setVisible(buttons, false);
-    box.setReplyToBox(this);
-  }
-
-  void unregisterReplyBox() {
-    replyBox = null;
-    UIObject.setVisible(buttons, isOpen());
-  }
-
-  private void openReplyBox() {
-    replyBox.setOpen(true);
-    replyBox.setEdit(true);
-  }
-
-  void addReplyBox(boolean quote) {
-    CommentInfo commentReply = CommentInfo.createReply(comment);
-    if (quote) {
-      commentReply.message(ReplyBox.quote(comment.message()));
-    }
-    getCommentManager().addDraftBox(displaySide, commentReply).setEdit(true);
-  }
-
-  void doReply() {
-    if (!Gerrit.isSignedIn()) {
-      Gerrit.doSignIn(getCommentManager().host.getToken());
-    } else if (replyBox == null) {
-      addReplyBox(false);
-    } else {
-      openReplyBox();
-    }
-  }
-
-  @UiHandler("reply")
-  void onReply(ClickEvent e) {
-    e.stopPropagation();
-    doReply();
-  }
-
-  @UiHandler("quote")
-  void onQuote(ClickEvent e) {
-    e.stopPropagation();
-    if (!Gerrit.isSignedIn()) {
-      Gerrit.doSignIn(getCommentManager().host.getToken());
-    }
-    addReplyBox(true);
-  }
-
-  @UiHandler("done")
-  void onReplyDone(ClickEvent e) {
-    e.stopPropagation();
-    if (!Gerrit.isSignedIn()) {
-      Gerrit.doSignIn(getCommentManager().host.getToken());
-    } else if (replyBox == null) {
-      done.setEnabled(false);
-      CommentInfo input = CommentInfo.createReply(comment);
-      input.message(PatchUtil.C.cannedReplyDone());
-      CommentApi.createDraft(
-          Project.NameKey.asStringOrNull(project),
-          psId,
-          input,
-          new GerritCallback<CommentInfo>() {
-            @Override
-            public void onSuccess(CommentInfo result) {
-              done.setEnabled(true);
-              setOpen(false);
-              getCommentManager().addDraftBox(displaySide, result);
-            }
-          });
-    } else {
-      openReplyBox();
-      setOpen(false);
-    }
-  }
-
-  @UiHandler("fix")
-  void onFix(ClickEvent e) {
-    e.stopPropagation();
-    String t = Dispatcher.toEditScreen(project, psId, comment.path(), comment.line());
-    if (!Gerrit.isSignedIn()) {
-      Gerrit.doSignIn(t);
-    } else {
-      Gerrit.display(t);
-    }
-  }
-
-  private static String authorName(CommentInfo info) {
-    if (info.author() != null) {
-      if (info.author().name() != null) {
-        return info.author().name();
-      }
-      return Gerrit.info().user().anonymousCowardName();
-    }
-    return Util.C.messageNoAuthor();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PublishedBox.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PublishedBox.ui.xml
deleted file mode 100644
index cbea847..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PublishedBox.ui.xml
+++ /dev/null
@@ -1,82 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:c='urn:import:com.google.gerrit.client'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-  <ui:with field='res' type='com.google.gerrit.client.diff.Resources'/>
-  <ui:style gss='false' type='com.google.gerrit.client.diff.PublishedBox.Style'>
-    .avatar {
-      position: absolute;
-      width: 26px;
-      height: 26px;
-    }
-    .closed .avatar {
-      position: absolute;
-      width: 16px;
-      height: 16px;
-    }
-
-    .name {
-      white-space: nowrap;
-      font-weight: bold;
-    }
-    .closed .name {
-      width: 120px;
-      overflow: hidden;
-      text-overflow: ellipsis;
-      font-weight: normal;
-    }
-  </ui:style>
-
-  <g:HTMLPanel
-      styleName='{res.style.commentBox}'
-      addStyleNames='{style.closed}'>
-    <c:AvatarImage ui:field='avatar' styleName='{style.avatar}'/>
-    <div class='{res.style.contents}'>
-      <g:HTMLPanel ui:field='header' styleName='{res.style.header}'>
-        <div ui:field='name' class='{style.name}'/>
-        <div ui:field='summary' class='{res.style.summary}'/>
-        <div ui:field='date' class='{res.style.date}'/>
-      </g:HTMLPanel>
-      <div ui:field='message' class='{res.style.message}'
-           aria-hidden='true' style='display: NONE'/>
-      <div ui:field='buttons' aria-hidden='true' style='display: NONE'>
-        <g:Button ui:field='reply' styleName=''
-            title='Reply to this comment'>
-          <ui:attribute name='title'/>
-          <div><ui:msg>Reply</ui:msg></div>
-        </g:Button>
-        <g:Button ui:field='quote' styleName=''
-            title='Reply to this comment with quoting it'>
-          <ui:attribute name='title'/>
-          <div><ui:msg>Quote</ui:msg></div>
-        </g:Button>
-        <g:Button ui:field='done' styleName=''
-            title='Reply "Done" to this comment'>
-          <ui:attribute name='title'/>
-          <div><ui:msg>Done</ui:msg></div>
-        </g:Button>
-        <g:Button ui:field='fix' styleName='' visible='false'
-            title='Fix this comment in the inline editor'>
-          <ui:attribute name='title'/>
-          <div><ui:msg>Fix</ui:msg></div>
-        </g:Button>
-      </div>
-    </div>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Resources.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Resources.java
deleted file mode 100644
index e590333..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Resources.java
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.resources.client.ClientBundle;
-import com.google.gwt.resources.client.ImageResource;
-
-/** Resources used by diff. */
-interface Resources extends ClientBundle {
-  Resources I = GWT.create(Resources.class);
-
-  @Source("CommentBox.css")
-  CommentBox.Style style();
-
-  @Source("Scrollbar.css")
-  Scrollbar.Style scrollbarStyle();
-
-  @Source("DiffTable.css")
-  DiffTable.Style diffTableStyle();
-
-  /** tango icon library (public domain): http://tango.freedesktop.org/Tango_Icon_Library */
-  @Source("goPrev.png")
-  ImageResource goPrev();
-
-  @Source("goNext.png")
-  ImageResource goNext();
-
-  @Source("goUp.png")
-  ImageResource goUp();
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/ScrollSynchronizer.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/ScrollSynchronizer.java
deleted file mode 100644
index 35e3e7d..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/ScrollSynchronizer.java
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gwt.user.client.Timer;
-import net.codemirror.lib.CodeMirror;
-import net.codemirror.lib.ScrollInfo;
-
-class ScrollSynchronizer {
-  private SideBySideTable diffTable;
-  private LineMapper mapper;
-  private ScrollCallback active;
-  private ScrollCallback callbackA;
-  private ScrollCallback callbackB;
-  private CodeMirror cmB;
-  private boolean autoHideDiffTableHeader;
-
-  ScrollSynchronizer(SideBySideTable diffTable, CodeMirror cmA, CodeMirror cmB, LineMapper mapper) {
-    this.diffTable = diffTable;
-    this.mapper = mapper;
-    this.cmB = cmB;
-
-    callbackA = new ScrollCallback(cmA, cmB, DisplaySide.A);
-    callbackB = new ScrollCallback(cmB, cmA, DisplaySide.B);
-    cmA.on("scroll", callbackA);
-    cmB.on("scroll", callbackB);
-  }
-
-  void setAutoHideDiffTableHeader(boolean autoHide) {
-    if (autoHide) {
-      updateDiffTableHeader(cmB.getScrollInfo());
-    } else {
-      diffTable.setHeaderVisible(true);
-    }
-    autoHideDiffTableHeader = autoHide;
-  }
-
-  void syncScroll(DisplaySide masterSide) {
-    (masterSide == DisplaySide.A ? callbackA : callbackB).sync();
-  }
-
-  private void updateDiffTableHeader(ScrollInfo si) {
-    if (si.top() == 0) {
-      diffTable.setHeaderVisible(true);
-    } else if (si.top() > 0.5 * si.clientHeight()) {
-      diffTable.setHeaderVisible(false);
-    }
-  }
-
-  class ScrollCallback implements Runnable {
-    private final CodeMirror src;
-    private final CodeMirror dst;
-    private final DisplaySide srcSide;
-    private final Timer fixup;
-    private int state;
-
-    ScrollCallback(CodeMirror src, CodeMirror dst, DisplaySide srcSide) {
-      this.src = src;
-      this.dst = dst;
-      this.srcSide = srcSide;
-      this.fixup =
-          new Timer() {
-            @Override
-            public void run() {
-              if (active == ScrollCallback.this) {
-                fixup();
-              }
-            }
-          };
-    }
-
-    void sync() {
-      dst.scrollToY(align(src.getScrollInfo().top()));
-    }
-
-    @Override
-    public void run() {
-      if (active == null) {
-        active = this;
-        fixup.scheduleRepeating(20);
-      }
-      if (active == this) {
-        ScrollInfo si = src.getScrollInfo();
-        if (autoHideDiffTableHeader) {
-          updateDiffTableHeader(si);
-        }
-        dst.scrollTo(si.left(), align(si.top()));
-        state = 0;
-      }
-    }
-
-    private void fixup() {
-      switch (state) {
-        case 0:
-          state = 1;
-          dst.scrollToY(align(src.getScrollInfo().top()));
-          break;
-        case 1:
-          state = 2;
-          break;
-        case 2:
-          active = null;
-          fixup.cancel();
-          break;
-      }
-    }
-
-    private double align(double srcTop) {
-      // Since CM doesn't always take the height of line widgets into
-      // account when calculating scrollInfo when scrolling too fast (e.g.
-      // throw scrolling), simply setting scrollTop to be the same doesn't
-      // guarantee alignment.
-
-      int line = src.lineAtHeight(srcTop, "local");
-      if (line == 0) {
-        // Padding for insert at start of file occurs above line 0,
-        // and CM3 doesn't always compute heightAtLine correctly.
-        return srcTop;
-      }
-
-      // Find a pair of lines that are aligned and near the top of
-      // the viewport. Use that distance to correct the Y coordinate.
-      LineMapper.AlignedPair p = mapper.align(srcSide, line);
-      double sy = src.heightAtLine(p.src, "local");
-      double dy = dst.heightAtLine(p.dst, "local");
-      return Math.max(0, dy + (srcTop - sy));
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Scrollbar.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Scrollbar.css
deleted file mode 100644
index 26f8ff5..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Scrollbar.css
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-.comment, .draft, .insert, .delete, .edit {
-  min-height: 5px;
-  position: absolute;
-  right: 0;
-  z-index: 7;
-}
-
-.comment, .draft {
-  color: #0d0d0d;
-  font-size: 9px;
-}
-
-.delete {
-  background-color: #faa;
-  min-width: 12px;
-}
-.insert {
-  background-color: #9f9;
-  min-width: 12px;
-}
-.edit {
-  border-left: 6px solid #faa;
-  width: 6px !important;
-  background-color: #9f9;
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Scrollbar.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Scrollbar.java
deleted file mode 100644
index 83ada90..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Scrollbar.java
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gwt.resources.client.CssResource;
-import java.util.ArrayList;
-import java.util.List;
-import net.codemirror.lib.CodeMirror;
-import net.codemirror.lib.Pos;
-
-/** Displays overview of all edits and comments in this file. */
-class Scrollbar {
-  static {
-    Resources.I.scrollbarStyle().ensureInjected();
-  }
-
-  interface Style extends CssResource {
-    String comment();
-
-    String draft();
-
-    String insert();
-
-    String delete();
-
-    String edit();
-  }
-
-  private final List<ScrollbarAnnotation> diff = new ArrayList<>();
-  private final DiffTable parent;
-
-  Scrollbar(DiffTable d) {
-    parent = d;
-  }
-
-  ScrollbarAnnotation comment(CodeMirror cm, int line) {
-    ScrollbarAnnotation a = new ScrollbarAnnotation(cm);
-    a.setStyleName(Resources.I.scrollbarStyle().comment());
-    a.at(line);
-    a.getElement().setInnerText("\u2736"); // Six pointed black star
-    parent.add(a);
-    return a;
-  }
-
-  ScrollbarAnnotation draft(CodeMirror cm, int line) {
-    ScrollbarAnnotation a = new ScrollbarAnnotation(cm);
-    a.setStyleName(Resources.I.scrollbarStyle().draft());
-    a.at(line);
-    a.getElement().setInnerText("\u270D"); // Writing hand
-    parent.add(a);
-    return a;
-  }
-
-  ScrollbarAnnotation insert(CodeMirror cm, int line, int len) {
-    ScrollbarAnnotation a = diff(cm, line, len);
-    a.setStyleName(Resources.I.scrollbarStyle().insert());
-    parent.add(a);
-    return a;
-  }
-
-  ScrollbarAnnotation delete(CodeMirror cmA, CodeMirror cmB, int line, int len) {
-    ScrollbarAnnotation a = diff(cmA, line, len);
-    a.setStyleName(Resources.I.scrollbarStyle().delete());
-    a.renderOn(cmB);
-    parent.add(a);
-    return a;
-  }
-
-  ScrollbarAnnotation edit(CodeMirror cm, int line, int len) {
-    ScrollbarAnnotation a = diff(cm, line, len);
-    a.setStyleName(Resources.I.scrollbarStyle().edit());
-    parent.add(a);
-    return a;
-  }
-
-  private ScrollbarAnnotation diff(CodeMirror cm, int s, int n) {
-    ScrollbarAnnotation a = new ScrollbarAnnotation(cm);
-    a.at(Pos.create(s), Pos.create(s + n));
-    diff.add(a);
-    return a;
-  }
-
-  void removeDiffAnnotations() {
-    for (ScrollbarAnnotation a : diff) {
-      a.remove();
-    }
-    diff.clear();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/ScrollbarAnnotation.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/ScrollbarAnnotation.java
deleted file mode 100644
index ecdac46..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/ScrollbarAnnotation.java
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.Style.Unit;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.ui.Widget;
-import net.codemirror.lib.CodeMirror;
-import net.codemirror.lib.CodeMirror.RegisteredHandler;
-import net.codemirror.lib.Pos;
-
-/** Displayed on the vertical scrollbar to place a chunk or comment. */
-class ScrollbarAnnotation extends Widget implements ClickHandler {
-  private final CodeMirror cm;
-  private CodeMirror cmB;
-  private RegisteredHandler refresh;
-  private Pos from;
-  private Pos to;
-  private double scale;
-
-  ScrollbarAnnotation(CodeMirror cm) {
-    setElement((Element) DOM.createDiv());
-    getElement().setAttribute("not-content", "true");
-    addDomHandler(this, ClickEvent.getType());
-    this.cm = cm;
-    this.cmB = cm;
-  }
-
-  void remove() {
-    removeFromParent();
-  }
-
-  void at(int line) {
-    at(Pos.create(line), Pos.create(line + 1));
-  }
-
-  void at(Pos from, Pos to) {
-    this.from = from;
-    this.to = to;
-  }
-
-  void renderOn(CodeMirror cm) {
-    this.cmB = cm;
-  }
-
-  @Override
-  protected void onLoad() {
-    cmB.getWrapperElement().appendChild(getElement());
-    refresh =
-        cmB.on(
-            "refresh",
-            () -> {
-              if (updateScale()) {
-                updatePosition();
-              }
-            });
-    updateScale();
-    updatePosition();
-  }
-
-  @Override
-  protected void onUnload() {
-    cmB.off("refresh", refresh);
-  }
-
-  private boolean updateScale() {
-    double old = scale;
-    double docHeight = cmB.getWrapperElement().getClientHeight();
-    double lineHeight = cmB.heightAtLine(cmB.lastLine() + 1, "local");
-    scale = (docHeight - cmB.barHeight()) / lineHeight;
-    return old != scale;
-  }
-
-  private void updatePosition() {
-    double top = cm.charCoords(from, "local").top() * scale;
-    double bottom = cm.charCoords(to, "local").bottom() * scale;
-
-    Element e = getElement();
-    e.getStyle().setTop(top, Unit.PX);
-    e.getStyle().setWidth(Math.max(2, cm.barWidth() - 1), Unit.PX);
-    e.getStyle().setHeight(Math.max(3, bottom - top), Unit.PX);
-  }
-
-  @Override
-  public void onClick(ClickEvent event) {
-    event.stopPropagation();
-
-    int line = from.line();
-    int h = to.line() - line;
-    if (h > 5) {
-      // Map click inside of the annotation to the relative position
-      // within the region covered by the annotation.
-      double s = ((double) event.getY()) / getElement().getOffsetHeight();
-      line += (int) (s * h);
-    }
-
-    double y = cm.heightAtLine(line, "local");
-    double viewport = cm.getScrollInfo().clientHeight();
-    cm.setCursor(from);
-    cm.scrollTo(0, y - 0.5 * viewport);
-    cm.focus();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide.java
deleted file mode 100644
index d052323..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide.java
+++ /dev/null
@@ -1,414 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import static java.lang.Double.POSITIVE_INFINITY;
-
-import com.google.gerrit.client.DiffObject;
-import com.google.gerrit.client.Dispatcher;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.diff.LineMapper.LineOnOtherInfo;
-import com.google.gerrit.client.patches.PatchUtil;
-import com.google.gerrit.client.projects.ConfigInfoCache;
-import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gerrit.client.ui.InlineHyperlink;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DiffView;
-import com.google.gerrit.reviewdb.client.Patch;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.event.dom.client.FocusEvent;
-import com.google.gwt.event.dom.client.FocusHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.ImageResourceRenderer;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-import com.google.gwtexpui.globalkey.client.KeyCommand;
-import java.util.Collections;
-import java.util.List;
-import net.codemirror.lib.CodeMirror;
-import net.codemirror.lib.CodeMirror.LineHandle;
-import net.codemirror.lib.Configuration;
-import net.codemirror.lib.KeyMap;
-import net.codemirror.lib.Pos;
-
-public class SideBySide extends DiffScreen {
-  interface Binder extends UiBinder<FlowPanel, SideBySide> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-  private static final String LINE_NUMBER_CLASSNAME = "CodeMirror-linenumber";
-
-  @UiField(provided = true)
-  SideBySideTable diffTable;
-
-  private CodeMirror cmA;
-  private CodeMirror cmB;
-
-  private ScrollSynchronizer scrollSynchronizer;
-
-  private SideBySideChunkManager chunkManager;
-  private SideBySideCommentManager commentManager;
-
-  public SideBySide(
-      @Nullable Project.NameKey project,
-      DiffObject base,
-      DiffObject revision,
-      String path,
-      DisplaySide startSide,
-      int startLine) {
-    super(project, base, revision, path, startSide, startLine, DiffView.SIDE_BY_SIDE);
-
-    diffTable = new SideBySideTable(this, base, revision, path);
-    add(uiBinder.createAndBindUi(this));
-    addDomHandler(GlobalKey.STOP_PROPAGATION, KeyPressEvent.getType());
-  }
-
-  @Override
-  ScreenLoadCallback<ConfigInfoCache.Entry> getScreenLoadCallback(
-      final CommentsCollections comments) {
-    return new ScreenLoadCallback<ConfigInfoCache.Entry>(SideBySide.this) {
-      @Override
-      protected void preDisplay(ConfigInfoCache.Entry result) {
-        commentManager =
-            new SideBySideCommentManager(
-                SideBySide.this,
-                getProject(),
-                base,
-                revision,
-                path,
-                result.getCommentLinkProcessor(),
-                getChangeStatus().isOpen());
-        setTheme(result.getTheme());
-        display(comments);
-        header.setupPrevNextFiles(comments);
-      }
-    };
-  }
-
-  @Override
-  public void onShowView() {
-    super.onShowView();
-
-    operation(
-        () -> {
-          resizeCodeMirror();
-          chunkManager.adjustPadding();
-          cmA.refresh();
-          cmB.refresh();
-        });
-    setLineLength(Patch.COMMIT_MSG.equals(path) ? 72 : prefs.lineLength());
-    diffTable.refresh();
-
-    if (getStartLine() == 0) {
-      DiffChunkInfo d = chunkManager.getFirst();
-      if (d != null) {
-        if (d.isEdit() && d.getSide() == DisplaySide.A) {
-          setStartSide(DisplaySide.B);
-          setStartLine(lineOnOther(d.getSide(), d.getStart()).getLine() + 1);
-        } else {
-          setStartSide(d.getSide());
-          setStartLine(d.getStart() + 1);
-        }
-      }
-    }
-    if (getStartSide() != null && getStartLine() > 0) {
-      CodeMirror cm = getCmFromSide(getStartSide());
-      cm.scrollToLine(getStartLine() - 1);
-      cm.focus();
-    } else {
-      cmA.setCursor(Pos.create(0));
-      cmA.focus();
-    }
-    if (Gerrit.isSignedIn() && prefs.autoReview()) {
-      header.autoReview();
-    }
-    prefetchNextFile();
-  }
-
-  @Override
-  void registerCmEvents(CodeMirror cm) {
-    super.registerCmEvents(cm);
-
-    KeyMap keyMap =
-        KeyMap.create()
-            .on("Shift-A", diffTable.toggleA())
-            .on("Shift-Left", moveCursorToSide(cm, DisplaySide.A))
-            .on("Shift-Right", moveCursorToSide(cm, DisplaySide.B));
-    cm.addKeyMap(keyMap);
-    maybeRegisterRenderEntireFileKeyMap(cm);
-  }
-
-  @Override
-  public void registerKeys() {
-    super.registerKeys();
-
-    getKeysNavigation()
-        .add(
-            new NoOpKeyCommand(KeyCommand.M_SHIFT, KeyCodes.KEY_LEFT, PatchUtil.C.focusSideA()),
-            new NoOpKeyCommand(KeyCommand.M_SHIFT, KeyCodes.KEY_RIGHT, PatchUtil.C.focusSideB()));
-    getKeysAction()
-        .add(
-            new KeyCommand(KeyCommand.M_SHIFT, 'a', PatchUtil.C.toggleSideA()) {
-              @Override
-              public void onKeyPress(KeyPressEvent event) {
-                diffTable.toggleA().run();
-              }
-            });
-
-    registerHandlers();
-  }
-
-  @Override
-  FocusHandler getFocusHandler() {
-    return new FocusHandler() {
-      @Override
-      public void onFocus(FocusEvent event) {
-        cmB.focus();
-      }
-    };
-  }
-
-  private void display(CommentsCollections comments) {
-    DiffInfo diff = getDiff();
-    setThemeStyles(prefs.theme().isDark());
-    setShowIntraline(prefs.intralineDifference());
-    if (prefs.showLineNumbers()) {
-      diffTable.addStyleName(Resources.I.diffTableStyle().showLineNumbers());
-    }
-
-    cmA = newCm(diff.metaA(), diff.textA(), diffTable.cmA);
-    cmB = newCm(diff.metaB(), diff.textB(), diffTable.cmB);
-
-    getDiffTable()
-        .setUpBlameIconA(
-            cmA,
-            base.isBaseOrAutoMerge(),
-            base.isBaseOrAutoMerge() ? revision : base.asPatchSetId(),
-            path);
-    getDiffTable().setUpBlameIconB(cmB, revision, path);
-
-    cmA.extras().side(DisplaySide.A);
-    cmB.extras().side(DisplaySide.B);
-    setShowTabs(prefs.showTabs());
-
-    chunkManager = new SideBySideChunkManager(this, cmA, cmB, diffTable.scrollbar);
-
-    operation(
-        () -> {
-          // Estimate initial CodeMirror height, fixed up in onShowView.
-          int height = Window.getClientHeight() - (Gerrit.getHeaderFooterHeight() + 18);
-          cmA.setHeight(height);
-          cmB.setHeight(height);
-
-          render(diff);
-          commentManager.render(comments, prefs.expandAllComments());
-          skipManager.render(prefs.context(), diff);
-        });
-
-    registerCmEvents(cmA);
-    registerCmEvents(cmB);
-    scrollSynchronizer = new ScrollSynchronizer(diffTable, cmA, cmB, chunkManager.lineMapper);
-
-    setPrefsAction(new PreferencesAction(this, prefs));
-    header.init(getPrefsAction(), getUnifiedDiffLink(), diff.sideBySideWebLinks());
-    scrollSynchronizer.setAutoHideDiffTableHeader(prefs.autoHideDiffTableHeader());
-
-    setupSyntaxHighlighting();
-  }
-
-  private List<InlineHyperlink> getUnifiedDiffLink() {
-    InlineHyperlink toUnifiedDiffLink = new InlineHyperlink();
-    toUnifiedDiffLink.setHTML(new ImageResourceRenderer().render(Gerrit.RESOURCES.unifiedDiff()));
-    toUnifiedDiffLink.setTargetHistoryToken(
-        Dispatcher.toUnified(getProject(), base, revision, path));
-    toUnifiedDiffLink.setTitle(PatchUtil.C.unifiedDiff());
-    return Collections.singletonList(toUnifiedDiffLink);
-  }
-
-  @Override
-  CodeMirror newCm(DiffInfo.FileMeta meta, String contents, Element parent) {
-    return CodeMirror.create(
-        parent,
-        Configuration.create()
-            .set("cursorBlinkRate", prefs.cursorBlinkRate())
-            .set("cursorHeight", 0.85)
-            .set("inputStyle", "textarea")
-            .set("keyMap", "vim_ro")
-            .set("lineNumbers", prefs.showLineNumbers())
-            .set("matchBrackets", prefs.matchBrackets())
-            .set("lineWrapping", prefs.lineWrapping())
-            .set("mode", getFileSize() == FileSize.SMALL ? getContentType(meta) : null)
-            .set("readOnly", true)
-            .set("scrollbarStyle", "overlay")
-            .set("showTrailingSpace", prefs.showWhitespaceErrors())
-            .set("styleSelectedText", true)
-            .set("tabSize", prefs.tabSize())
-            .set("theme", prefs.theme().name().toLowerCase())
-            .set("value", meta != null ? contents : "")
-            .set("viewportMargin", renderEntireFile() ? POSITIVE_INFINITY : 10));
-  }
-
-  @Override
-  void setShowLineNumbers(boolean b) {
-    super.setShowLineNumbers(b);
-
-    cmA.setOption("lineNumbers", b);
-    cmB.setOption("lineNumbers", b);
-  }
-
-  @Override
-  void setSyntaxHighlighting(boolean b) {
-    final DiffInfo diff = getDiff();
-    if (b) {
-      injectMode(
-          diff,
-          new AsyncCallback<Void>() {
-            @Override
-            public void onSuccess(Void result) {
-              if (prefs.syntaxHighlighting()) {
-                cmA.setOption("mode", getContentType(diff.metaA()));
-                cmB.setOption("mode", getContentType(diff.metaB()));
-              }
-            }
-
-            @Override
-            public void onFailure(Throwable caught) {
-              prefs.syntaxHighlighting(false);
-            }
-          });
-    } else {
-      cmA.setOption("mode", (String) null);
-      cmB.setOption("mode", (String) null);
-    }
-  }
-
-  @Override
-  void setAutoHideDiffHeader(boolean hide) {
-    scrollSynchronizer.setAutoHideDiffTableHeader(hide);
-  }
-
-  CodeMirror otherCm(CodeMirror me) {
-    return me == cmA ? cmB : cmA;
-  }
-
-  @Override
-  CodeMirror getCmFromSide(DisplaySide side) {
-    return side == DisplaySide.A ? cmA : cmB;
-  }
-
-  @Override
-  int getCmLine(int line, DisplaySide side) {
-    return line;
-  }
-
-  @Override
-  Runnable updateActiveLine(CodeMirror cm) {
-    CodeMirror other = otherCm(cm);
-    return () -> {
-      // The rendering of active lines has to be deferred. Reflow
-      // caused by adding and removing styles chokes Firefox when arrow
-      // key (or j/k) is held down. Performance on Chrome is fine
-      // without the deferral.
-      //
-      Scheduler.get()
-          .scheduleDeferred(
-              new ScheduledCommand() {
-                @Override
-                public void execute() {
-                  operation(
-                      () -> {
-                        LineHandle handle = cm.getLineHandleVisualStart(cm.getCursor("end").line());
-                        if (!cm.extras().activeLine(handle)) {
-                          return;
-                        }
-
-                        LineOnOtherInfo info = lineOnOther(cm.side(), cm.getLineNumber(handle));
-                        if (info.isAligned()) {
-                          other.extras().activeLine(other.getLineHandle(info.getLine()));
-                        } else {
-                          other.extras().clearActiveLine();
-                        }
-                      });
-                }
-              });
-    };
-  }
-
-  private Runnable moveCursorToSide(CodeMirror cmSrc, DisplaySide sideDst) {
-    CodeMirror cmDst = getCmFromSide(sideDst);
-    if (cmDst == cmSrc) {
-      return () -> {};
-    }
-
-    DisplaySide sideSrc = cmSrc.side();
-    return () -> {
-      if (cmSrc.extras().hasActiveLine()) {
-        cmDst.setCursor(
-            Pos.create(
-                lineOnOther(sideSrc, cmSrc.getLineNumber(cmSrc.extras().activeLine())).getLine()));
-      }
-      cmDst.focus();
-    };
-  }
-
-  void syncScroll(DisplaySide masterSide) {
-    if (scrollSynchronizer != null) {
-      scrollSynchronizer.syncScroll(masterSide);
-    }
-  }
-
-  @Override
-  void operation(Runnable apply) {
-    cmA.operation(() -> cmB.operation(apply::run));
-  }
-
-  @Override
-  CodeMirror[] getCms() {
-    return new CodeMirror[] {cmA, cmB};
-  }
-
-  @Override
-  SideBySideTable getDiffTable() {
-    return diffTable;
-  }
-
-  @Override
-  SideBySideChunkManager getChunkManager() {
-    return chunkManager;
-  }
-
-  @Override
-  SideBySideCommentManager getCommentManager() {
-    return commentManager;
-  }
-
-  @Override
-  boolean isSideBySide() {
-    return true;
-  }
-
-  @Override
-  String getLineNumberClassName() {
-    return LINE_NUMBER_CLASSNAME;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide.ui.xml
deleted file mode 100644
index 55c9de0..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide.ui.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'
-    xmlns:d='urn:import:com.google.gerrit.client.diff'>
-  <ui:style gss='false'>
-    .sbs {
-      margin-left: -5px;
-      margin-right: -5px;
-    }
-  </ui:style>
-  <g:FlowPanel styleName='{style.sbs}'>
-    <d:Header ui:field='header'/>
-    <d:SideBySideTable ui:field='diffTable'/>
-  </g:FlowPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySideChunkManager.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySideChunkManager.java
deleted file mode 100644
index 2877794..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySideChunkManager.java
+++ /dev/null
@@ -1,262 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import static com.google.gerrit.client.diff.DisplaySide.A;
-import static com.google.gerrit.client.diff.DisplaySide.B;
-
-import com.google.gerrit.client.diff.DiffInfo.Region;
-import com.google.gerrit.client.diff.DiffInfo.Span;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.NativeEvent;
-import com.google.gwt.dom.client.Style.Unit;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.EventListener;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import net.codemirror.lib.CodeMirror;
-import net.codemirror.lib.CodeMirror.LineClassWhere;
-import net.codemirror.lib.Configuration;
-import net.codemirror.lib.LineWidget;
-import net.codemirror.lib.Pos;
-
-/** Colors modified regions for {@link SideBySide}. */
-class SideBySideChunkManager extends ChunkManager {
-  private static final String DATA_LINES = "_cs2h";
-  private static double guessedLineHeightPx = 15;
-  private static final JavaScriptObject focusA = initOnClick(A);
-  private static final JavaScriptObject focusB = initOnClick(B);
-
-  private static native JavaScriptObject initOnClick(DisplaySide s) /*-{
-    return $entry(function(e){
-      @com.google.gerrit.client.diff.SideBySideChunkManager::focus(
-        Lcom/google/gwt/dom/client/NativeEvent;
-        Lcom/google/gerrit/client/diff/DisplaySide;)(e,s)
-    });
-  }-*/;
-
-  private static void focus(NativeEvent event, DisplaySide side) {
-    Element e = Element.as(event.getEventTarget());
-    for (e = DOM.getParent(e); e != null; e = DOM.getParent(e)) {
-      EventListener l = DOM.getEventListener(e);
-      if (l instanceof SideBySide) {
-        ((SideBySide) l).getCmFromSide(side).focus();
-        event.stopPropagation();
-      }
-    }
-  }
-
-  static void focusOnClick(Element e, DisplaySide side) {
-    onClick(e, side == A ? focusA : focusB);
-  }
-
-  private final SideBySide host;
-  private final CodeMirror cmA;
-  private final CodeMirror cmB;
-
-  private List<DiffChunkInfo> chunks;
-  private List<LineWidget> padding;
-  private List<Element> paddingDivs;
-
-  SideBySideChunkManager(SideBySide host, CodeMirror cmA, CodeMirror cmB, Scrollbar scrollbar) {
-    super(scrollbar);
-
-    this.host = host;
-    this.cmA = cmA;
-    this.cmB = cmB;
-  }
-
-  @Override
-  DiffChunkInfo getFirst() {
-    return !chunks.isEmpty() ? chunks.get(0) : null;
-  }
-
-  @Override
-  void reset() {
-    super.reset();
-
-    for (LineWidget w : padding) {
-      w.clear();
-    }
-  }
-
-  @Override
-  void render(DiffInfo diff) {
-    super.render();
-
-    chunks = new ArrayList<>();
-    padding = new ArrayList<>();
-    paddingDivs = new ArrayList<>();
-
-    String diffColor =
-        diff.metaA() == null || diff.metaB() == null
-            ? SideBySideTable.style.intralineBg()
-            : SideBySideTable.style.diff();
-
-    for (Region current : Natives.asList(diff.content())) {
-      if (current.ab() != null) {
-        lineMapper.appendCommon(current.ab().length());
-      } else if (current.skip() > 0) {
-        lineMapper.appendCommon(current.skip());
-      } else if (current.common()) {
-        lineMapper.appendCommon(current.b().length());
-      } else {
-        render(current, diffColor);
-      }
-    }
-
-    if (paddingDivs.isEmpty()) {
-      paddingDivs = null;
-    }
-  }
-
-  void adjustPadding() {
-    if (paddingDivs != null) {
-      double h = cmB.extras().lineHeightPx();
-      for (Element div : paddingDivs) {
-        int lines = div.getPropertyInt(DATA_LINES);
-        div.getStyle().setHeight(lines * h, Unit.PX);
-      }
-      for (LineWidget w : padding) {
-        w.changed();
-      }
-      paddingDivs = null;
-      guessedLineHeightPx = h;
-    }
-  }
-
-  private void render(Region region, String diffColor) {
-    int startA = lineMapper.getLineA();
-    int startB = lineMapper.getLineB();
-
-    JsArrayString a = region.a();
-    JsArrayString b = region.b();
-    int aLen = a != null ? a.length() : 0;
-    int bLen = b != null ? b.length() : 0;
-
-    String color = a == null || b == null ? diffColor : SideBySideTable.style.intralineBg();
-
-    colorLines(cmA, color, startA, aLen);
-    colorLines(cmB, color, startB, bLen);
-    markEdit(cmA, startA, a, region.editA());
-    markEdit(cmB, startB, b, region.editB());
-    addPadding(cmA, startA + aLen - 1, bLen - aLen);
-    addPadding(cmB, startB + bLen - 1, aLen - bLen);
-    addGutterTag(region, startA, startB);
-    lineMapper.appendReplace(aLen, bLen);
-
-    int endA = lineMapper.getLineA() - 1;
-    int endB = lineMapper.getLineB() - 1;
-    if (aLen > 0) {
-      addDiffChunk(cmB, endA, aLen, bLen > 0);
-    }
-    if (bLen > 0) {
-      addDiffChunk(cmA, endB, bLen, aLen > 0);
-    }
-  }
-
-  private void addGutterTag(Region region, int startA, int startB) {
-    if (region.a() == null) {
-      scrollbar.insert(cmB, startB, region.b().length());
-    } else if (region.b() == null) {
-      scrollbar.delete(cmA, cmB, startA, region.a().length());
-    } else {
-      scrollbar.edit(cmB, startB, region.b().length());
-    }
-  }
-
-  private void markEdit(CodeMirror cm, int startLine, JsArrayString lines, JsArray<Span> edits) {
-    if (lines == null || edits == null) {
-      return;
-    }
-
-    EditIterator iter = new EditIterator(lines, startLine);
-    Configuration bg =
-        Configuration.create()
-            .set("className", SideBySideTable.style.intralineBg())
-            .set("readOnly", true);
-
-    Configuration diff =
-        Configuration.create().set("className", SideBySideTable.style.diff()).set("readOnly", true);
-
-    Pos last = Pos.create(0, 0);
-    for (Span span : Natives.asList(edits)) {
-      Pos from = iter.advance(span.skip());
-      Pos to = iter.advance(span.mark());
-      if (from.line() == last.line()) {
-        getMarkers().add(cm.markText(last, from, bg));
-      } else {
-        getMarkers().add(cm.markText(Pos.create(from.line(), 0), from, bg));
-      }
-      getMarkers().add(cm.markText(from, to, diff));
-      last = to;
-      colorLines(
-          cm, LineClassWhere.BACKGROUND, SideBySideTable.style.diff(), from.line(), to.line());
-    }
-  }
-
-  /**
-   * Insert a new padding div below the given line.
-   *
-   * @param cm parent CodeMirror to add extra space into.
-   * @param line line to put the padding below.
-   * @param len number of lines to pad. Padding is inserted only if {@code len >= 1}.
-   */
-  private void addPadding(CodeMirror cm, int line, int len) {
-    if (0 < len) {
-      Element pad = DOM.createDiv();
-      pad.setClassName(SideBySideTable.style.padding());
-      pad.setPropertyInt(DATA_LINES, len);
-      pad.getStyle().setHeight(guessedLineHeightPx * len, Unit.PX);
-      focusOnClick(pad, cm.side());
-      paddingDivs.add(pad);
-      padding.add(
-          cm.addLineWidget(
-              line == -1 ? 0 : line,
-              pad,
-              Configuration.create()
-                  .set("coverGutter", true)
-                  .set("noHScroll", true)
-                  .set("above", line == -1)));
-    }
-  }
-
-  private void addDiffChunk(CodeMirror cmToPad, int lineOnOther, int chunkSize, boolean edit) {
-    chunks.add(
-        new DiffChunkInfo(
-            host.otherCm(cmToPad).side(), lineOnOther - chunkSize + 1, lineOnOther, edit));
-  }
-
-  @Override
-  Runnable diffChunkNav(CodeMirror cm, Direction dir) {
-    return () -> {
-      int line = cm.extras().hasActiveLine() ? cm.getLineNumber(cm.extras().activeLine()) : 0;
-      int res =
-          Collections.binarySearch(
-              chunks, new DiffChunkInfo(cm.side(), line, 0, false), getDiffChunkComparator());
-      diffChunkNavHelper(chunks, host, res, dir);
-    };
-  }
-
-  @Override
-  int getCmLine(int line, DisplaySide side) {
-    return line;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySideCommentGroup.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySideCommentGroup.java
deleted file mode 100644
index c728f6f..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySideCommentGroup.java
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.Style.Unit;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Timer;
-import java.util.PriorityQueue;
-import net.codemirror.lib.CodeMirror;
-
-/**
- * LineWidget attached to a CodeMirror container.
- *
- * <p>When a comment is placed on a line a CommentWidget is created on both sides. The group tracks
- * all comment boxes on that same line, and also includes an empty padding element to keep
- * subsequent lines vertically aligned.
- */
-class SideBySideCommentGroup extends CommentGroup implements Comparable<SideBySideCommentGroup> {
-  static void pair(SideBySideCommentGroup a, SideBySideCommentGroup b) {
-    a.peers.add(b);
-    b.peers.add(a);
-  }
-
-  private final Element padding;
-  private final PriorityQueue<SideBySideCommentGroup> peers;
-
-  SideBySideCommentGroup(
-      SideBySideCommentManager manager, CodeMirror cm, DisplaySide side, int line) {
-    super(manager, cm, side, line);
-
-    padding = DOM.createDiv();
-    padding.setClassName(SideBySideTable.style.padding());
-    SideBySideChunkManager.focusOnClick(padding, cm.side());
-    getElement().appendChild(padding);
-    peers = new PriorityQueue<>();
-  }
-
-  SideBySideCommentGroup getPeer() {
-    return peers.peek();
-  }
-
-  @Override
-  void remove(DraftBox box) {
-    super.remove(box);
-
-    if (getBoxCount() == 0 && peers.size() == 1 && peers.peek().peers.size() > 1) {
-      SideBySideCommentGroup peer = peers.peek();
-      peer.peers.remove(this);
-      detach();
-      if (peer.getBoxCount() == 0
-          && peer.peers.size() == 1
-          && peer.peers.peek().getBoxCount() == 0) {
-        peer.detach();
-      } else {
-        peer.resize();
-      }
-    } else {
-      resize();
-    }
-  }
-
-  @Override
-  void init(DiffTable parent) {
-    if (getLineWidget() == null) {
-      attach(parent);
-    }
-    for (CommentGroup peer : peers) {
-      if (peer.getLineWidget() == null) {
-        peer.attach(parent);
-      }
-    }
-  }
-
-  @Override
-  void handleRedraw() {
-    getLineWidget()
-        .onRedraw(
-            () -> {
-              if (canComputeHeight() && peers.peek().canComputeHeight()) {
-                if (getResizeTimer() != null) {
-                  getResizeTimer().cancel();
-                  setResizeTimer(null);
-                }
-                adjustPadding(SideBySideCommentGroup.this, peers.peek());
-              } else if (getResizeTimer() == null) {
-                setResizeTimer(
-                    new Timer() {
-                      @Override
-                      public void run() {
-                        if (canComputeHeight() && peers.peek().canComputeHeight()) {
-                          cancel();
-                          setResizeTimer(null);
-                          adjustPadding(SideBySideCommentGroup.this, peers.peek());
-                        }
-                      }
-                    });
-                getResizeTimer().scheduleRepeating(5);
-              }
-            });
-  }
-
-  @Override
-  void resize() {
-    if (getLineWidget() != null) {
-      adjustPadding(this, peers.peek());
-    }
-  }
-
-  private int computeHeight() {
-    if (getComments().isVisible()) {
-      // Include margin-bottom: 5px from CSS class.
-      return getComments().getOffsetHeight() + 5;
-    }
-    return 0;
-  }
-
-  private static void adjustPadding(SideBySideCommentGroup a, SideBySideCommentGroup b) {
-    int apx = a.computeHeight();
-    int bpx = b.computeHeight();
-    for (SideBySideCommentGroup otherPeer : a.peers) {
-      if (otherPeer != b) {
-        bpx += otherPeer.computeHeight();
-      }
-    }
-    for (SideBySideCommentGroup otherPeer : b.peers) {
-      if (otherPeer != a) {
-        apx += otherPeer.computeHeight();
-      }
-    }
-    int h = Math.max(apx, bpx);
-    a.padding.getStyle().setHeight(Math.max(0, h - apx), Unit.PX);
-    b.padding.getStyle().setHeight(Math.max(0, h - bpx), Unit.PX);
-    a.getLineWidget().changed();
-    b.getLineWidget().changed();
-    a.updateSelection();
-    b.updateSelection();
-  }
-
-  @Override
-  public int compareTo(SideBySideCommentGroup o) {
-    if (side == o.side) {
-      return line - o.line;
-    }
-    throw new IllegalStateException("Cannot compare SideBySideCommentGroup with different sides");
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySideCommentManager.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySideCommentManager.java
deleted file mode 100644
index 09c5b07..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySideCommentManager.java
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gerrit.client.DiffObject;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.CommentInfo;
-import com.google.gerrit.client.ui.CommentLinkProcessor;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import java.util.Collection;
-import java.util.Map;
-import java.util.SortedMap;
-import net.codemirror.lib.CodeMirror;
-import net.codemirror.lib.TextMarker.FromTo;
-
-/** Tracks comment widgets for {@link SideBySide}. */
-class SideBySideCommentManager extends CommentManager {
-  SideBySideCommentManager(
-      SideBySide host,
-      @Nullable Project.NameKey project,
-      DiffObject base,
-      PatchSet.Id revision,
-      String path,
-      CommentLinkProcessor clp,
-      boolean open) {
-    super(host, project, base, revision, path, clp, open);
-  }
-
-  @Override
-  SortedMap<Integer, CommentGroup> getMapForNav(DisplaySide side) {
-    return map(side);
-  }
-
-  @Override
-  void clearLine(DisplaySide side, int line, CommentGroup group) {
-    super.clearLine(side, line, group);
-  }
-
-  @Override
-  void newDraftOnGutterClick(CodeMirror cm, String gutterClass, int line) {
-    if (!Gerrit.isSignedIn()) {
-      signInCallback(cm).run();
-    } else {
-      insertNewDraft(cm.side(), line);
-    }
-  }
-
-  @Override
-  CommentGroup getCommentGroupOnActiveLine(CodeMirror cm) {
-    CommentGroup group = null;
-    if (cm.extras().hasActiveLine()) {
-      group = map(cm.side()).get(cm.getLineNumber(cm.extras().activeLine()) + 1);
-    }
-    return group;
-  }
-
-  @Override
-  Collection<Integer> getLinesWithCommentGroups() {
-    return sideB.tailMap(1).keySet();
-  }
-
-  @Override
-  String getTokenSuffixForActiveLine(CodeMirror cm) {
-    return (cm.side() == DisplaySide.A ? "a" : "")
-        + (cm.getLineNumber(cm.extras().activeLine()) + 1);
-  }
-
-  @Override
-  void newDraft(CodeMirror cm) {
-    int line = cm.getLineNumber(cm.extras().activeLine()) + 1;
-    if (cm.somethingSelected()) {
-      FromTo fromTo = adjustSelection(cm);
-      addDraftBox(
-              cm.side(),
-              CommentInfo.create(
-                  getPath(),
-                  getStoredSideFromDisplaySide(cm.side()),
-                  getParentNumFromDisplaySide(cm.side()),
-                  line,
-                  CommentRange.create(fromTo),
-                  false))
-          .setEdit(true);
-      cm.setCursor(fromTo.to());
-      cm.setSelection(cm.getCursor());
-    } else {
-      insertNewDraft(cm.side(), line);
-    }
-  }
-
-  @Override
-  CommentGroup group(DisplaySide side, int line) {
-    CommentGroup existing = map(side).get(line);
-    if (existing != null) {
-      return existing;
-    }
-
-    SideBySideCommentGroup newGroup = newGroup(side, line);
-    Map<Integer, CommentGroup> map = side == DisplaySide.A ? sideA : sideB;
-    Map<Integer, CommentGroup> otherMap = side == DisplaySide.A ? sideB : sideA;
-    map.put(line, newGroup);
-    int otherLine = host.lineOnOther(side, line - 1).getLine() + 1;
-    existing = map(side.otherSide()).get(otherLine);
-    CommentGroup otherGroup;
-    if (existing != null) {
-      otherGroup = existing;
-    } else {
-      otherGroup = newGroup(side.otherSide(), otherLine);
-      otherMap.put(otherLine, otherGroup);
-    }
-    SideBySideCommentGroup.pair(newGroup, (SideBySideCommentGroup) otherGroup);
-
-    if (isAttached()) {
-      newGroup.init(host.getDiffTable());
-      otherGroup.handleRedraw();
-    }
-    return newGroup;
-  }
-
-  private SideBySideCommentGroup newGroup(DisplaySide side, int line) {
-    return new SideBySideCommentGroup(this, host.getCmFromSide(side), side, line);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySideTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySideTable.java
deleted file mode 100644
index c65dcf0..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySideTable.java
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gerrit.client.DiffObject;
-import com.google.gerrit.reviewdb.client.Patch.ChangeType;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.user.client.ui.HTMLPanel;
-
-/**
- * A table with one row and two columns to hold the two CodeMirrors displaying the files to be
- * compared.
- */
-class SideBySideTable extends DiffTable {
-  interface Binder extends UiBinder<HTMLPanel, SideBySideTable> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  interface DiffTableStyle extends CssResource {
-    String intralineBg();
-
-    String diff();
-
-    String hideA();
-
-    String hideB();
-
-    String padding();
-  }
-
-  private SideBySide parent;
-  @UiField Element cmA;
-  @UiField Element cmB;
-  @UiField static DiffTableStyle style;
-
-  private boolean visibleA;
-
-  SideBySideTable(SideBySide parent, DiffObject base, DiffObject revision, String path) {
-    super(parent, base, revision, path);
-
-    initWidget(uiBinder.createAndBindUi(this));
-    this.visibleA = true;
-    this.parent = parent;
-  }
-
-  @Override
-  boolean isVisibleA() {
-    return visibleA;
-  }
-
-  void setVisibleA(boolean show) {
-    visibleA = show;
-    if (show) {
-      removeStyleName(style.hideA());
-      parent.syncScroll(DisplaySide.B); // match B's viewport
-    } else {
-      addStyleName(style.hideA());
-    }
-  }
-
-  Runnable toggleA() {
-    return () -> setVisibleA(!isVisibleA());
-  }
-
-  void setVisibleB(boolean show) {
-    if (show) {
-      removeStyleName(style.hideB());
-      parent.syncScroll(DisplaySide.A); // match A's viewport
-    } else {
-      addStyleName(style.hideB());
-    }
-  }
-
-  @Override
-  void setHideEmptyPane(boolean hide) {
-    if (getChangeType() == ChangeType.ADDED) {
-      setVisibleA(!hide);
-    } else if (getChangeType() == ChangeType.DELETED) {
-      setVisibleB(!hide);
-    }
-  }
-
-  @Override
-  SideBySide getDiffScreen() {
-    return parent;
-  }
-
-  @Override
-  int getHeaderHeight() {
-    int h = patchSetSelectBoxA.getOffsetHeight();
-    if (hasHeader()) {
-      h += diffHeaderRow.getOffsetHeight();
-    }
-    return h;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySideTable.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySideTable.ui.xml
deleted file mode 100644
index b2e3f43..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySideTable.ui.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'
-    xmlns:d='urn:import:com.google.gerrit.client.diff'>
-  <ui:with field='res' type='com.google.gerrit.client.diff.Resources'/>
-  <ui:style gss='false' type='com.google.gerrit.client.diff.SideBySideTable.DiffTableStyle'>
-    @external .CodeMirror, .CodeMirror-selectedtext;
-    @external .CodeMirror-linenumber;
-    @external .CodeMirror-overlayscroll-vertical, .CodeMirror-scroll;
-    @external .CodeMirror-dialog-bottom;
-    @external .CodeMirror-cursor;
-
-    @external .dark, .noIntraline, .showLineNumbers;
-
-    .difftable .patchSetNav,
-    .difftable .CodeMirror {
-      -webkit-touch-callout: none;
-      -webkit-user-select: none;
-      -khtml-user-select: none;
-      -moz-user-select: none;
-      -ms-user-select: none;
-    }
-
-    .difftable .CodeMirror pre {
-      overflow: visible;
-      border-right: 0;
-      width: auto;
-    }
-
-    /* Preserve space for underscores. If this changes
-     * see ChunkManager.addPadding() and adjust there.
-     */
-    .difftable .CodeMirror pre,
-    .difftable .CodeMirror pre span {
-      padding-bottom: 1px;
-    }
-
-    .hideA .psNavA,
-    .hideA .a {
-      display: none;
-    }
-
-    .hideB .psNavB,
-    .hideB .b {
-      display: none;
-    }
-
-    .table {
-      width: 100%;
-      table-layout: fixed;
-      border-spacing: 0;
-    }
-    .table td { padding: 0 }
-    .a, .b { width: 50% }
-    .hideA .psNavB, .hideA .b { width: 100% }
-    .hideB .psNavA, .hideB .a { width: 100% }
-
-    /* Hide scrollbars on A, B controls both views. */
-    .a .CodeMirror-scroll { margin-right: -36px; }
-    .a .CodeMirror-overlayscroll-vertical { display: none !important; }
-
-    .showLineNumbers .b { border-left: none; }
-    .b { border-left: 1px solid #ddd; }
-
-    .a .diff { background-color: #faa; }
-    /* Set min-width for lineWrapping to make sure it gets enough width
-       before lineWrapping and to make sure it dosent do a ugly line wrap */
-    .b .diff { background-color: #9f9; min-width: 60em; }
-    .a .intralineBg { background-color: #fee; }
-    .b .intralineBg { background-color: #dfd; }
-    .noIntraline .a .intralineBg { background-color: #faa; }
-    .noIntraline .b .intralineBg { background-color: #9f9; }
-
-    .dark .a .diff { background-color: #400; }
-    .dark .b .diff { background-color: #444; }
-
-    .dark .a .intralineBg { background-color: #888; }
-    .dark .b .intralineBg { background-color: #bbb; }
-    .dark .noIntraline .a .intralineBg { background-color: #400; }
-    .dark .noIntraline .b .intralineBg { background-color: #444; }
-
-    .patchSetNav, .diff_header {
-      background-color: #f7f7f7;
-      line-height: 1;
-    }
-
-    .difftable .CodeMirror-selectedtext {
-      background-color: inherit !important;
-    }
-    .difftable .CodeMirror-linenumber {
-      height: 1.11em;
-      cursor: pointer;
-    }
-    .difftable .CodeMirror div.CodeMirror-cursor {
-      border-left: 2px solid black;
-    }
-    .difftable .CodeMirror-dialog-bottom {
-      border-top: 0;
-      border-left: 1px solid #000;
-      border-bottom: 1px solid #000;
-      background-color: #f7f7f7;
-      top: 0;
-      right: 0;
-      bottom: auto;
-      left: auto;
-    }
-    .showLineNumbers .padding {
-      margin-left: 21px;
-      border-left: 2px solid #d64040;
-    }
-  </ui:style>
-  <g:HTMLPanel styleName='{style.difftable}'>
-    <table class='{style.table}'>
-      <tr ui:field='patchSetNavRow' class='{style.patchSetNav}'>
-        <td ui:field='patchSetNavCellA' class='{style.psNavA}'>
-          <d:PatchSetSelectBox ui:field='patchSetSelectBoxA' />
-        </td>
-        <td ui:field='patchSetNavCellB' class='{style.psNavB}'>
-          <d:PatchSetSelectBox ui:field='patchSetSelectBoxB' />
-        </td>
-      </tr>
-      <tr ui:field='diffHeaderRow' class='{res.diffTableStyle.diffHeader}'>
-        <td colspan='2'><pre ui:field='diffHeaderText' /></td>
-      </tr>
-      <tr>
-        <td ui:field='cmA' class='{style.a}' />
-        <td ui:field='cmB' class='{style.b}' />
-      </tr>
-    </table>
-    <g:FlowPanel ui:field='widgets' visible='false'/>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SkipBar.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SkipBar.java
deleted file mode 100644
index c138f37..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SkipBar.java
+++ /dev/null
@@ -1,217 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gerrit.client.patches.PatchUtil;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Style.Unit;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import net.codemirror.lib.CodeMirror;
-import net.codemirror.lib.Configuration;
-import net.codemirror.lib.LineWidget;
-import net.codemirror.lib.Pos;
-import net.codemirror.lib.TextMarker;
-import net.codemirror.lib.TextMarker.FromTo;
-
-class SkipBar extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, SkipBar> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-  private static final int NUM_ROWS_TO_EXPAND = 10;
-  private static final int UP_DOWN_THRESHOLD = 30;
-
-  interface SkipBarStyle extends CssResource {
-    String noExpand();
-  }
-
-  @UiField(provided = true)
-  Anchor skipNum;
-
-  @UiField(provided = true)
-  Anchor upArrow;
-
-  @UiField(provided = true)
-  Anchor downArrow;
-
-  @UiField SkipBarStyle style;
-
-  private final SkipManager manager;
-  private final CodeMirror cm;
-
-  private LineWidget lineWidget;
-  private TextMarker textMarker;
-  private SkipBar otherBar;
-
-  SkipBar(SkipManager manager, CodeMirror cm) {
-    this.manager = manager;
-    this.cm = cm;
-
-    skipNum = new Anchor(true);
-    upArrow = new Anchor(true);
-    downArrow = new Anchor(true);
-    initWidget(uiBinder.createAndBindUi(this));
-    addDomHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            cm.focus();
-          }
-        },
-        ClickEvent.getType());
-  }
-
-  void collapse(int start, int end, boolean attach) {
-    if (attach) {
-      boolean isNew = lineWidget == null;
-      Configuration cfg = Configuration.create().set("coverGutter", true).set("noHScroll", true);
-      if (start == 0) { // First line workaround
-        lineWidget = cm.addLineWidget(end + 1, getElement(), cfg.set("above", true));
-      } else {
-        lineWidget = cm.addLineWidget(start - 1, getElement(), cfg);
-      }
-      if (isNew) {
-        lineWidget.onFirstRedraw(
-            () -> {
-              int w = cm.getGutterElement().getOffsetWidth();
-              getElement().getStyle().setPaddingLeft(w, Unit.PX);
-            });
-      }
-    }
-
-    textMarker =
-        cm.markText(
-            Pos.create(start, 0),
-            Pos.create(end),
-            Configuration.create()
-                .set("collapsed", true)
-                .set("inclusiveLeft", true)
-                .set("inclusiveRight", true));
-
-    textMarker.on("beforeCursorEnter", this::expandAll);
-
-    int skipped = end - start + 1;
-    if (skipped <= UP_DOWN_THRESHOLD) {
-      addStyleName(style.noExpand());
-    } else {
-      upArrow.setHTML(PatchUtil.M.expandBefore(NUM_ROWS_TO_EXPAND));
-      downArrow.setHTML(PatchUtil.M.expandAfter(NUM_ROWS_TO_EXPAND));
-    }
-    skipNum.setText(PatchUtil.M.patchSkipRegion(Integer.toString(skipped)));
-  }
-
-  static void link(SkipBar barA, SkipBar barB) {
-    barA.otherBar = barB;
-    barB.otherBar = barA;
-  }
-
-  private void clearMarkerAndWidget() {
-    textMarker.clear();
-    lineWidget.clear();
-  }
-
-  void expandBefore(int cnt) {
-    expandSideBefore(cnt);
-
-    if (otherBar != null) {
-      otherBar.expandSideBefore(cnt);
-    }
-  }
-
-  private void expandSideBefore(int cnt) {
-    FromTo range = textMarker.find();
-    int oldStart = range.from().line();
-    int newStart = oldStart + cnt;
-    int end = range.to().line();
-    clearMarkerAndWidget();
-    collapse(newStart, end, true);
-    updateSelection();
-  }
-
-  void expandSideAll() {
-    clearMarkerAndWidget();
-    removeFromParent();
-  }
-
-  private void expandAfter() {
-    FromTo range = textMarker.find();
-    int start = range.from().line();
-    int oldEnd = range.to().line();
-    int newEnd = oldEnd - NUM_ROWS_TO_EXPAND;
-    boolean attach = start == 0;
-    if (attach) {
-      clearMarkerAndWidget();
-    } else {
-      textMarker.clear();
-    }
-    collapse(start, newEnd, attach);
-    updateSelection();
-  }
-
-  private void updateSelection() {
-    if (cm.somethingSelected()) {
-      FromTo sel = cm.getSelectedRange();
-      cm.setSelection(sel.from(), sel.to());
-    }
-  }
-
-  @UiHandler("skipNum")
-  void onExpandAll(@SuppressWarnings("unused") ClickEvent e) {
-    expandAll();
-    updateSelection();
-    if (otherBar != null) {
-      otherBar.expandAll();
-      otherBar.updateSelection();
-    }
-    cm.refresh();
-    cm.focus();
-  }
-
-  private void expandAll() {
-    expandSideAll();
-    if (otherBar != null) {
-      otherBar.expandSideAll();
-    }
-    manager.remove(this, otherBar);
-  }
-
-  @UiHandler("upArrow")
-  void onExpandBefore(@SuppressWarnings("unused") ClickEvent e) {
-    expandBefore(NUM_ROWS_TO_EXPAND);
-    if (otherBar != null) {
-      otherBar.expandBefore(NUM_ROWS_TO_EXPAND);
-    }
-    cm.refresh();
-    cm.focus();
-  }
-
-  @UiHandler("downArrow")
-  void onExpandAfter(@SuppressWarnings("unused") ClickEvent e) {
-    expandAfter();
-
-    if (otherBar != null) {
-      otherBar.expandAfter();
-    }
-    cm.refresh();
-    cm.focus();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SkipBar.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SkipBar.ui.xml
deleted file mode 100644
index bf3c425..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SkipBar.ui.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-  <ui:style gss='false' type='com.google.gerrit.client.diff.SkipBar.SkipBarStyle'>
-    .skipBar {
-      background-color: #def;
-      height: 1.3em;
-      overflow: hidden;
-    }
-    .text {
-      display: table;
-      margin: 0 auto;
-      color: #777;
-      font-style: italic;
-      overflow: hidden;
-    }
-    .anchor {
-      color: inherit;
-      text-decoration: none;
-    }
-    .noExpand .arrow {
-      display: none;
-    }
-    .arrow {
-      font-family: Arial Unicode MS, sans-serif;
-    }
-  </ui:style>
-  <g:HTMLPanel addStyleNames='{style.skipBar}'>
-  <div class='{style.text}'>
-    <ui:msg>
-      <g:Anchor ui:field='upArrow' addStyleNames='{style.arrow} {style.anchor}' />
-      <g:Anchor ui:field='skipNum' addStyleNames='{style.anchor}' />
-      <g:Anchor ui:field='downArrow' addStyleNames=' {style.arrow} {style.anchor}' />
-    </ui:msg>
-  </div>
-  </g:HTMLPanel>
-</ui:UiBinder>
\ No newline at end of file
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SkipManager.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SkipManager.java
deleted file mode 100644
index 533ba1f..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SkipManager.java
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gerrit.client.diff.DiffInfo.Region;
-import com.google.gerrit.client.patches.SkippedLine;
-import com.google.gerrit.extensions.client.DiffPreferencesInfo;
-import com.google.gwt.core.client.JsArray;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import net.codemirror.lib.CodeMirror;
-
-/** Collapses common regions with {@link SkipBar} for {@link SideBySide} and {@link Unified}. */
-class SkipManager {
-  private final Set<SkipBar> skipBars;
-  private final DiffScreen host;
-  private SkipBar line0;
-
-  SkipManager(DiffScreen host) {
-    this.host = host;
-    this.skipBars = new HashSet<>();
-  }
-
-  void render(int context, DiffInfo diff) {
-    if (context == DiffPreferencesInfo.WHOLE_FILE_CONTEXT) {
-      return;
-    }
-
-    List<SkippedLine> skips = new ArrayList<>();
-    int lineA = 0;
-    int lineB = 0;
-    JsArray<Region> regions = diff.content();
-    for (int i = 0; i < regions.length(); i++) {
-      Region current = regions.get(i);
-      if (current.ab() != null || current.common() || current.skip() > 0) {
-        int len =
-            current.skip() > 0
-                ? current.skip()
-                : (current.ab() != null ? current.ab() : current.b()).length();
-        if (i == 0 && len > context + 1) {
-          skips.add(new SkippedLine(0, 0, len - context));
-        } else if (i == regions.length() - 1 && len > context + 1) {
-          skips.add(new SkippedLine(lineA + context, lineB + context, len - context));
-        } else if (len > 2 * context + 1) {
-          skips.add(new SkippedLine(lineA + context, lineB + context, len - 2 * context));
-        }
-        lineA += len;
-        lineB += len;
-      } else {
-        lineA += current.a() != null ? current.a().length() : 0;
-        lineB += current.b() != null ? current.b().length() : 0;
-      }
-    }
-    skips = host.getCommentManager().splitSkips(context, skips);
-    renderSkips(skips, lineA, lineB);
-  }
-
-  private void renderSkips(List<SkippedLine> skips, int lineA, int lineB) {
-    if (!skips.isEmpty()) {
-      boolean isSideBySide = host.isSideBySide();
-      CodeMirror cmA = null;
-      if (isSideBySide) {
-        cmA = host.getCmFromSide(DisplaySide.A);
-      }
-      CodeMirror cmB = host.getCmFromSide(DisplaySide.B);
-
-      for (SkippedLine skip : skips) {
-        SkipBar barA = null;
-        SkipBar barB = newSkipBar(cmB, DisplaySide.B, skip);
-        skipBars.add(barB);
-        if (isSideBySide) {
-          barA = newSkipBar(cmA, DisplaySide.A, skip);
-          SkipBar.link(barA, barB);
-          skipBars.add(barA);
-        }
-
-        if (skip.getStartA() == 0 || skip.getStartB() == 0) {
-          if (isSideBySide) {
-            barA.upArrow.setVisible(false);
-          }
-          barB.upArrow.setVisible(false);
-          setLine0(barB);
-        } else if (skip.getStartA() + skip.getSize() == lineA
-            || skip.getStartB() + skip.getSize() == lineB) {
-          if (isSideBySide) {
-            barA.downArrow.setVisible(false);
-          }
-          barB.downArrow.setVisible(false);
-        }
-      }
-    }
-  }
-
-  private SkipBar newSkipBar(CodeMirror cm, DisplaySide side, SkippedLine skip) {
-    int start = host.getCmLine(side == DisplaySide.A ? skip.getStartA() : skip.getStartB(), side);
-    int end = start + skip.getSize() - 1;
-
-    SkipBar bar = new SkipBar(this, cm);
-    host.getDiffTable().add(bar);
-    bar.collapse(start, end, true);
-    return bar;
-  }
-
-  void ensureFirstLineIsVisible() {
-    if (line0 != null) {
-      line0.expandBefore(1);
-      line0 = null;
-    }
-  }
-
-  void removeAll() {
-    if (!skipBars.isEmpty()) {
-      for (SkipBar bar : skipBars) {
-        bar.expandSideAll();
-      }
-      line0 = null;
-    }
-  }
-
-  void remove(SkipBar a, SkipBar b) {
-    skipBars.remove(a);
-    skipBars.remove(b);
-    if (getLine0() == a || getLine0() == b) {
-      setLine0(null);
-    }
-  }
-
-  SkipBar getLine0() {
-    return line0;
-  }
-
-  void setLine0(SkipBar bar) {
-    line0 = bar;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Unified.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Unified.java
deleted file mode 100644
index 7bd9804..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Unified.java
+++ /dev/null
@@ -1,383 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import static java.lang.Double.POSITIVE_INFINITY;
-
-import com.google.gerrit.client.DiffObject;
-import com.google.gerrit.client.Dispatcher;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.diff.UnifiedChunkManager.LineRegionInfo;
-import com.google.gerrit.client.patches.PatchUtil;
-import com.google.gerrit.client.projects.ConfigInfoCache;
-import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gerrit.client.ui.InlineHyperlink;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DiffView;
-import com.google.gerrit.reviewdb.client.Patch;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.event.dom.client.FocusEvent;
-import com.google.gwt.event.dom.client.FocusHandler;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.ImageResourceRenderer;
-import com.google.gwt.user.client.ui.InlineHTML;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-import com.google.gwtexpui.safehtml.client.SafeHtml;
-import java.util.Collections;
-import java.util.List;
-import net.codemirror.lib.CodeMirror;
-import net.codemirror.lib.CodeMirror.LineHandle;
-import net.codemirror.lib.Configuration;
-import net.codemirror.lib.Pos;
-import net.codemirror.lib.ScrollInfo;
-
-public class Unified extends DiffScreen {
-  interface Binder extends UiBinder<FlowPanel, Unified> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  @UiField(provided = true)
-  UnifiedTable diffTable;
-
-  private CodeMirror cm;
-
-  private UnifiedChunkManager chunkManager;
-  private UnifiedCommentManager commentManager;
-
-  private boolean autoHideDiffTableHeader;
-
-  public Unified(
-      @Nullable Project.NameKey project,
-      DiffObject base,
-      DiffObject revision,
-      String path,
-      DisplaySide startSide,
-      int startLine) {
-    super(project, base, revision, path, startSide, startLine, DiffView.UNIFIED_DIFF);
-
-    diffTable = new UnifiedTable(this, base, revision, path);
-    add(uiBinder.createAndBindUi(this));
-    addDomHandler(GlobalKey.STOP_PROPAGATION, KeyPressEvent.getType());
-  }
-
-  @Override
-  ScreenLoadCallback<ConfigInfoCache.Entry> getScreenLoadCallback(
-      final CommentsCollections comments) {
-    return new ScreenLoadCallback<ConfigInfoCache.Entry>(Unified.this) {
-      @Override
-      protected void preDisplay(ConfigInfoCache.Entry result) {
-        commentManager =
-            new UnifiedCommentManager(
-                Unified.this,
-                getProject(),
-                base,
-                revision,
-                path,
-                result.getCommentLinkProcessor(),
-                getChangeStatus().isOpen());
-        setTheme(result.getTheme());
-        display(comments);
-        header.setupPrevNextFiles(comments);
-      }
-    };
-  }
-
-  @Override
-  public void onShowView() {
-    super.onShowView();
-
-    operation(
-        () -> {
-          resizeCodeMirror();
-          cm.refresh();
-        });
-    setLineLength(Patch.COMMIT_MSG.equals(path) ? 72 : prefs.lineLength());
-    diffTable.refresh();
-
-    if (getStartLine() == 0) {
-      DiffChunkInfo d = chunkManager.getFirst();
-      if (d != null) {
-        if (d.isEdit() && d.getSide() == DisplaySide.A) {
-          setStartSide(DisplaySide.B);
-        } else {
-          setStartSide(d.getSide());
-        }
-        setStartLine(chunkManager.getCmLine(d.getStart(), d.getSide()) + 1);
-      }
-    }
-    if (getStartSide() != null && getStartLine() > 0) {
-      cm.scrollToLine(chunkManager.getCmLine(getStartLine() - 1, getStartSide()));
-      cm.focus();
-    } else {
-      cm.setCursor(Pos.create(0));
-      cm.focus();
-    }
-    if (Gerrit.isSignedIn() && prefs.autoReview()) {
-      header.autoReview();
-    }
-    prefetchNextFile();
-  }
-
-  @Override
-  void registerCmEvents(CodeMirror cm) {
-    super.registerCmEvents(cm);
-
-    cm.on(
-        "scroll",
-        () -> {
-          ScrollInfo si = cm.getScrollInfo();
-          if (autoHideDiffTableHeader) {
-            updateDiffTableHeader(si);
-          }
-        });
-    maybeRegisterRenderEntireFileKeyMap(cm);
-  }
-
-  @Override
-  public void registerKeys() {
-    super.registerKeys();
-
-    registerHandlers();
-  }
-
-  @Override
-  FocusHandler getFocusHandler() {
-    return new FocusHandler() {
-      @Override
-      public void onFocus(FocusEvent event) {
-        cm.focus();
-      }
-    };
-  }
-
-  private void display(CommentsCollections comments) {
-    DiffInfo diff = getDiff();
-    setThemeStyles(prefs.theme().isDark());
-    setShowIntraline(prefs.intralineDifference());
-    if (prefs.showLineNumbers()) {
-      diffTable.addStyleName(Resources.I.diffTableStyle().showLineNumbers());
-    }
-
-    cm =
-        newCm(diff.metaA() == null ? diff.metaB() : diff.metaA(), diff.textUnified(), diffTable.cm);
-    setShowTabs(prefs.showTabs());
-
-    chunkManager = new UnifiedChunkManager(this, cm, diffTable.scrollbar);
-
-    operation(
-        () -> {
-          // Estimate initial CodeMirror height, fixed up in onShowView.
-          int height = Window.getClientHeight() - (Gerrit.getHeaderFooterHeight() + 18);
-          cm.setHeight(height);
-
-          render(diff);
-          commentManager.render(comments, prefs.expandAllComments());
-          skipManager.render(prefs.context(), diff);
-        });
-
-    registerCmEvents(cm);
-
-    setPrefsAction(new PreferencesAction(this, prefs));
-    header.init(getPrefsAction(), getSideBySideDiffLink(), diff.unifiedWebLinks());
-    setAutoHideDiffHeader(prefs.autoHideDiffTableHeader());
-
-    setupSyntaxHighlighting();
-  }
-
-  private List<InlineHyperlink> getSideBySideDiffLink() {
-    InlineHyperlink toSideBySideDiffLink = new InlineHyperlink();
-    toSideBySideDiffLink.setHTML(
-        new ImageResourceRenderer().render(Gerrit.RESOURCES.sideBySideDiff()));
-    toSideBySideDiffLink.setTargetHistoryToken(
-        Dispatcher.toSideBySide(getProject(), base, revision, path));
-    toSideBySideDiffLink.setTitle(PatchUtil.C.sideBySideDiff());
-    return Collections.singletonList(toSideBySideDiffLink);
-  }
-
-  @Override
-  CodeMirror newCm(DiffInfo.FileMeta meta, String contents, Element parent) {
-    JsArrayString gutters = JavaScriptObject.createArray().cast();
-    gutters.push(UnifiedTable.style.lineNumbersLeft());
-    gutters.push(UnifiedTable.style.lineNumbersRight());
-
-    return CodeMirror.create(
-        parent,
-        Configuration.create()
-            .set("cursorBlinkRate", prefs.cursorBlinkRate())
-            .set("cursorHeight", 0.85)
-            .set("gutters", gutters)
-            .set("inputStyle", "textarea")
-            .set("keyMap", "vim_ro")
-            .set("lineNumbers", false)
-            .set("lineWrapping", prefs.lineWrapping())
-            .set("matchBrackets", prefs.matchBrackets())
-            .set("mode", getFileSize() == FileSize.SMALL ? getContentType(meta) : null)
-            .set("readOnly", true)
-            .set("scrollbarStyle", "overlay")
-            .set("styleSelectedText", true)
-            .set("showTrailingSpace", prefs.showWhitespaceErrors())
-            .set("tabSize", prefs.tabSize())
-            .set("theme", prefs.theme().name().toLowerCase())
-            .set("value", meta != null ? contents : "")
-            .set("viewportMargin", renderEntireFile() ? POSITIVE_INFINITY : 10));
-  }
-
-  @Override
-  void setShowLineNumbers(boolean b) {
-    super.setShowLineNumbers(b);
-
-    cm.refresh();
-  }
-
-  private void setLineNumber(DisplaySide side, int cmLine, Integer line, String styleName) {
-    SafeHtml html = SafeHtml.asis(line != null ? line.toString() : "&nbsp;");
-    InlineHTML gutter = new InlineHTML(html);
-    diffTable.add(gutter);
-    gutter.setStyleName(styleName);
-    cm.setGutterMarker(
-        cmLine,
-        side == DisplaySide.A
-            ? UnifiedTable.style.lineNumbersLeft()
-            : UnifiedTable.style.lineNumbersRight(),
-        gutter.getElement());
-  }
-
-  void setLineNumber(DisplaySide side, int cmLine, int line) {
-    setLineNumber(side, cmLine, line, UnifiedTable.style.unifiedLineNumber());
-  }
-
-  void setLineNumberEmpty(DisplaySide side, int cmLine) {
-    setLineNumber(side, cmLine, null, UnifiedTable.style.unifiedLineNumberEmpty());
-  }
-
-  @Override
-  void setSyntaxHighlighting(boolean b) {
-    final DiffInfo diff = getDiff();
-    if (b) {
-      injectMode(
-          diff,
-          new AsyncCallback<Void>() {
-            @Override
-            public void onSuccess(Void result) {
-              if (prefs.syntaxHighlighting()) {
-                cm.setOption(
-                    "mode", getContentType(diff.metaA() == null ? diff.metaB() : diff.metaA()));
-              }
-            }
-
-            @Override
-            public void onFailure(Throwable caught) {
-              prefs.syntaxHighlighting(false);
-            }
-          });
-    } else {
-      cm.setOption("mode", (String) null);
-    }
-  }
-
-  @Override
-  void setAutoHideDiffHeader(boolean autoHide) {
-    if (autoHide) {
-      updateDiffTableHeader(cm.getScrollInfo());
-    } else {
-      diffTable.setHeaderVisible(true);
-    }
-    autoHideDiffTableHeader = autoHide;
-  }
-
-  private void updateDiffTableHeader(ScrollInfo si) {
-    if (si.top() == 0) {
-      diffTable.setHeaderVisible(true);
-    } else if (si.top() > 0.5 * si.clientHeight()) {
-      diffTable.setHeaderVisible(false);
-    }
-  }
-
-  @Override
-  Runnable updateActiveLine(CodeMirror cm) {
-    return () -> {
-      // The rendering of active lines has to be deferred. Reflow
-      // caused by adding and removing styles chokes Firefox when arrow
-      // key (or j/k) is held down. Performance on Chrome is fine
-      // without the deferral.
-      //
-      Scheduler.get()
-          .scheduleDeferred(
-              () -> {
-                LineHandle handle = cm.getLineHandleVisualStart(cm.getCursor("end").line());
-                cm.extras().activeLine(handle);
-              });
-    };
-  }
-
-  @Override
-  CodeMirror getCmFromSide(DisplaySide side) {
-    return cm;
-  }
-
-  @Override
-  int getCmLine(int line, DisplaySide side) {
-    return chunkManager.getCmLine(line, side);
-  }
-
-  LineRegionInfo getLineRegionInfoFromCmLine(int cmLine) {
-    return chunkManager.getLineRegionInfoFromCmLine(cmLine);
-  }
-
-  @Override
-  void operation(Runnable apply) {
-    cm.operation(apply::run);
-  }
-
-  @Override
-  CodeMirror[] getCms() {
-    return new CodeMirror[] {cm};
-  }
-
-  @Override
-  UnifiedTable getDiffTable() {
-    return diffTable;
-  }
-
-  @Override
-  UnifiedChunkManager getChunkManager() {
-    return chunkManager;
-  }
-
-  @Override
-  UnifiedCommentManager getCommentManager() {
-    return commentManager;
-  }
-
-  @Override
-  boolean isSideBySide() {
-    return false;
-  }
-
-  @Override
-  String getLineNumberClassName() {
-    return UnifiedTable.style.unifiedLineNumber();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Unified.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Unified.ui.xml
deleted file mode 100644
index 85f46a6..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Unified.ui.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'
-    xmlns:d='urn:import:com.google.gerrit.client.diff'>
-  <ui:style>
-    .unified {
-      margin-left: -5px;
-      margin-right: -5px;
-    }
-  </ui:style>
-  <g:FlowPanel styleName='{style.unified}'>
-    <d:Header ui:field='header'/>
-    <d:UnifiedTable ui:field='diffTable'/>
-  </g:FlowPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedChunkManager.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedChunkManager.java
deleted file mode 100644
index 98ad023..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedChunkManager.java
+++ /dev/null
@@ -1,330 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import static java.util.Comparator.comparing;
-
-import com.google.gerrit.client.diff.DiffInfo.Region;
-import com.google.gerrit.client.diff.DiffInfo.Span;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.NativeEvent;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.EventListener;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import net.codemirror.lib.CodeMirror;
-import net.codemirror.lib.CodeMirror.LineClassWhere;
-import net.codemirror.lib.Configuration;
-import net.codemirror.lib.Pos;
-
-/** Colors modified regions for {@link Unified}. */
-class UnifiedChunkManager extends ChunkManager {
-  private static final JavaScriptObject focus = initOnClick();
-
-  private static native JavaScriptObject initOnClick() /*-{
-    return $entry(function(e){
-      @com.google.gerrit.client.diff.UnifiedChunkManager::focus(
-        Lcom/google/gwt/dom/client/NativeEvent;)(e)
-    });
-  }-*/;
-
-  private List<UnifiedDiffChunkInfo> chunks;
-
-  @Override
-  DiffChunkInfo getFirst() {
-    return !chunks.isEmpty() ? chunks.get(0) : null;
-  }
-
-  private static void focus(NativeEvent event) {
-    Element e = Element.as(event.getEventTarget());
-    for (e = DOM.getParent(e); e != null; e = DOM.getParent(e)) {
-      EventListener l = DOM.getEventListener(e);
-      if (l instanceof Unified) {
-        ((Unified) l).getCmFromSide(DisplaySide.A).focus();
-        event.stopPropagation();
-      }
-    }
-  }
-
-  static void focusOnClick(Element e) {
-    onClick(e, focus);
-  }
-
-  private final Unified host;
-  private final CodeMirror cm;
-
-  UnifiedChunkManager(Unified host, CodeMirror cm, Scrollbar scrollbar) {
-    super(scrollbar);
-
-    this.host = host;
-    this.cm = cm;
-  }
-
-  @Override
-  void render(DiffInfo diff) {
-    super.render();
-
-    chunks = new ArrayList<>();
-
-    int cmLine = 0;
-    boolean useIntralineBg = diff.metaA() == null || diff.metaB() == null;
-
-    for (Region current : Natives.asList(diff.content())) {
-      int origLineA = lineMapper.getLineA();
-      int origLineB = lineMapper.getLineB();
-      if (current.ab() != null) {
-        int length = current.ab().length();
-        lineMapper.appendCommon(length);
-        for (int i = 0; i < length; i++) {
-          host.setLineNumber(DisplaySide.A, cmLine + i, origLineA + i + 1);
-          host.setLineNumber(DisplaySide.B, cmLine + i, origLineB + i + 1);
-        }
-        cmLine += length;
-      } else if (current.skip() > 0) {
-        lineMapper.appendCommon(current.skip());
-        cmLine += current.skip(); // Maybe current.ab().length();
-      } else if (current.common()) {
-        lineMapper.appendCommon(current.b().length());
-        cmLine += current.b().length();
-      } else {
-        cmLine += render(current, cmLine, useIntralineBg);
-      }
-    }
-    host.setLineNumber(DisplaySide.A, cmLine, lineMapper.getLineA() + 1);
-    host.setLineNumber(DisplaySide.B, cmLine, lineMapper.getLineB() + 1);
-  }
-
-  private int render(Region region, int cmLine, boolean useIntralineBg) {
-    int startA = lineMapper.getLineA();
-    int startB = lineMapper.getLineB();
-
-    JsArrayString a = region.a();
-    JsArrayString b = region.b();
-    int aLen = a != null ? a.length() : 0;
-    int bLen = b != null ? b.length() : 0;
-    boolean insertOrDelete = a == null || b == null;
-
-    colorLines(
-        cm,
-        insertOrDelete && !useIntralineBg
-            ? UnifiedTable.style.diffDelete()
-            : UnifiedTable.style.intralineDelete(),
-        cmLine,
-        aLen);
-    colorLines(
-        cm,
-        insertOrDelete && !useIntralineBg
-            ? UnifiedTable.style.diffInsert()
-            : UnifiedTable.style.intralineInsert(),
-        cmLine + aLen,
-        bLen);
-    markEdit(DisplaySide.A, cmLine, a, region.editA());
-    markEdit(DisplaySide.B, cmLine + aLen, b, region.editB());
-    addGutterTag(region, cmLine); // TODO: verify addGutterTag
-    lineMapper.appendReplace(aLen, bLen);
-
-    int endA = lineMapper.getLineA() - 1;
-    int endB = lineMapper.getLineB() - 1;
-    if (aLen > 0) {
-      addDiffChunk(DisplaySide.A, endA, aLen, cmLine, bLen > 0);
-      for (int j = 0; j < aLen; j++) {
-        host.setLineNumber(DisplaySide.A, cmLine + j, startA + j + 1);
-        host.setLineNumberEmpty(DisplaySide.B, cmLine + j);
-      }
-    }
-    if (bLen > 0) {
-      addDiffChunk(DisplaySide.B, endB, bLen, cmLine + aLen, aLen > 0);
-      for (int j = 0; j < bLen; j++) {
-        host.setLineNumberEmpty(DisplaySide.A, cmLine + aLen + j);
-        host.setLineNumber(DisplaySide.B, cmLine + aLen + j, startB + j + 1);
-      }
-    }
-    return aLen + bLen;
-  }
-
-  private void addGutterTag(Region region, int cmLine) {
-    if (region.a() == null) {
-      scrollbar.insert(cm, cmLine, region.b().length());
-    } else if (region.b() == null) {
-      scrollbar.delete(cm, cm, cmLine, region.a().length());
-    } else {
-      scrollbar.edit(cm, cmLine, region.b().length());
-    }
-  }
-
-  private void markEdit(DisplaySide side, int startLine, JsArrayString lines, JsArray<Span> edits) {
-    if (lines == null || edits == null) {
-      return;
-    }
-
-    EditIterator iter = new EditIterator(lines, startLine);
-    Configuration bg =
-        Configuration.create().set("className", getIntralineBgFromSide(side)).set("readOnly", true);
-
-    Configuration diff =
-        Configuration.create().set("className", getDiffColorFromSide(side)).set("readOnly", true);
-
-    Pos last = Pos.create(0, 0);
-    for (Span span : Natives.asList(edits)) {
-      Pos from = iter.advance(span.skip());
-      Pos to = iter.advance(span.mark());
-      if (from.line() == last.line()) {
-        getMarkers().add(cm.markText(last, from, bg));
-      } else {
-        getMarkers().add(cm.markText(Pos.create(from.line(), 0), from, bg));
-      }
-      getMarkers().add(cm.markText(from, to, diff));
-      last = to;
-      colorLines(cm, LineClassWhere.BACKGROUND, getDiffColorFromSide(side), from.line(), to.line());
-    }
-  }
-
-  private String getIntralineBgFromSide(DisplaySide side) {
-    return side == DisplaySide.A
-        ? UnifiedTable.style.intralineDelete()
-        : UnifiedTable.style.intralineInsert();
-  }
-
-  private String getDiffColorFromSide(DisplaySide side) {
-    return side == DisplaySide.A
-        ? UnifiedTable.style.diffDelete()
-        : UnifiedTable.style.diffInsert();
-  }
-
-  private void addDiffChunk(
-      DisplaySide side, int chunkEnd, int chunkSize, int cmLine, boolean edit) {
-    chunks.add(new UnifiedDiffChunkInfo(side, chunkEnd - chunkSize + 1, chunkEnd, cmLine, edit));
-  }
-
-  @Override
-  Runnable diffChunkNav(CodeMirror cm, Direction dir) {
-    return () -> {
-      int line = cm.extras().hasActiveLine() ? cm.getLineNumber(cm.extras().activeLine()) : 0;
-      int res =
-          Collections.binarySearch(
-              chunks,
-              new UnifiedDiffChunkInfo(cm.side(), 0, 0, line, false),
-              getDiffChunkComparatorCmLine());
-      diffChunkNavHelper(chunks, host, res, dir);
-    };
-  }
-
-  /** Diff chunks are ordered by their starting lines in CodeMirror */
-  private Comparator<UnifiedDiffChunkInfo> getDiffChunkComparatorCmLine() {
-    return comparing(UnifiedDiffChunkInfo::getCmLine);
-  }
-
-  @Override
-  int getCmLine(int line, DisplaySide side) {
-    int res =
-        Collections.binarySearch(
-            chunks,
-            new UnifiedDiffChunkInfo(side, line, 0, 0, false), // Dummy DiffChunkInfo
-            getDiffChunkComparator());
-    if (res >= 0) {
-      return chunks.get(res).getCmLine();
-    }
-    // The line might be within a DiffChunk
-    res = -res - 1;
-    if (res > 0) {
-      UnifiedDiffChunkInfo info = chunks.get(res - 1);
-      if (side == DisplaySide.A && info.isEdit() && info.getSide() == DisplaySide.B) {
-        // Need to use the start and cmLine of the deletion chunk
-        UnifiedDiffChunkInfo delete = chunks.get(res - 2);
-        if (line <= delete.getEnd()) {
-          return delete.getCmLine() + line - delete.getStart();
-        }
-        // Need to add the length of the insertion chunk
-        return delete.getCmLine() + line - delete.getStart() + info.getEnd() - info.getStart() + 1;
-      } else if (side == info.getSide()) {
-        return info.getCmLine() + line - info.getStart();
-      } else {
-        return info.getCmLine() + lineMapper.lineOnOther(side, line).getLine() - info.getStart();
-      }
-    }
-    return line;
-  }
-
-  LineRegionInfo getLineRegionInfoFromCmLine(int cmLine) {
-    int res =
-        Collections.binarySearch(
-            chunks,
-            new UnifiedDiffChunkInfo(DisplaySide.A, 0, 0, cmLine, false), // Dummy DiffChunkInfo
-            getDiffChunkComparatorCmLine());
-    if (res >= 0) { // The line is right at the start of a diff chunk.
-      UnifiedDiffChunkInfo info = chunks.get(res);
-      return new LineRegionInfo(info.getStart(), displaySideToRegionType(info.getSide()));
-    }
-    // The line might be within or after a diff chunk.
-    res = -res - 1;
-    if (res > 0) {
-      UnifiedDiffChunkInfo info = chunks.get(res - 1);
-      int lineOnInfoSide = info.getStart() + cmLine - info.getCmLine();
-      if (lineOnInfoSide > info.getEnd()) { // After a diff chunk
-        if (info.getSide() == DisplaySide.A) {
-          // For the common region after a deletion chunk, associate the line
-          // on side B with a common region.
-          return new LineRegionInfo(
-              lineMapper.lineOnOther(DisplaySide.A, lineOnInfoSide).getLine(), RegionType.COMMON);
-        }
-        return new LineRegionInfo(lineOnInfoSide, RegionType.COMMON);
-      }
-      // Within a diff chunk
-      return new LineRegionInfo(lineOnInfoSide, displaySideToRegionType(info.getSide()));
-    }
-    // The line is before any diff chunk, so it always equals cmLine and
-    // belongs to a common region.
-    return new LineRegionInfo(cmLine, RegionType.COMMON);
-  }
-
-  enum RegionType {
-    INSERT,
-    DELETE,
-    COMMON,
-  }
-
-  private static RegionType displaySideToRegionType(DisplaySide side) {
-    return side == DisplaySide.A ? RegionType.DELETE : RegionType.INSERT;
-  }
-
-  /**
-   * Helper class to associate a line in the original file with the type of the region it belongs
-   * to.
-   *
-   * @field line The 0-based line number in the original file. Note that this might be different
-   *     from the line number shown in CodeMirror.
-   * @field type The type of the region the line belongs to. Can be INSERT, DELETE or COMMON.
-   */
-  static class LineRegionInfo {
-    final int line;
-    final RegionType type;
-
-    LineRegionInfo(int line, RegionType type) {
-      this.line = line;
-      this.type = type;
-    }
-
-    DisplaySide getSide() {
-      // Always return DisplaySide.B for INSERT or COMMON
-      return type == RegionType.DELETE ? DisplaySide.A : DisplaySide.B;
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedCommentGroup.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedCommentGroup.java
deleted file mode 100644
index 6d5fba3..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedCommentGroup.java
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gwt.user.client.Timer;
-import net.codemirror.lib.CodeMirror;
-
-/**
- * LineWidget attached to a CodeMirror container.
- *
- * <p>When a comment is placed on a line a CommentWidget is created. The group tracks all comment
- * boxes on a line in unified diff view.
- */
-class UnifiedCommentGroup extends CommentGroup {
-  UnifiedCommentGroup(UnifiedCommentManager manager, CodeMirror cm, DisplaySide side, int line) {
-    super(manager, cm, side, line);
-  }
-
-  @Override
-  void remove(DraftBox box) {
-    super.remove(box);
-
-    if (0 < getBoxCount()) {
-      resize();
-    } else {
-      detach();
-    }
-  }
-
-  @Override
-  void init(DiffTable parent) {
-    if (getLineWidget() == null) {
-      attach(parent);
-    }
-  }
-
-  @Override
-  void handleRedraw() {
-    getLineWidget()
-        .onRedraw(
-            () -> {
-              if (canComputeHeight()) {
-                if (getResizeTimer() != null) {
-                  getResizeTimer().cancel();
-                  setResizeTimer(null);
-                }
-                reportHeightChange();
-              } else if (getResizeTimer() == null) {
-                setResizeTimer(
-                    new Timer() {
-                      @Override
-                      public void run() {
-                        if (canComputeHeight()) {
-                          cancel();
-                          setResizeTimer(null);
-                          reportHeightChange();
-                        }
-                      }
-                    });
-                getResizeTimer().scheduleRepeating(5);
-              }
-            });
-  }
-
-  @Override
-  void resize() {
-    if (getLineWidget() != null) {
-      reportHeightChange();
-    }
-  }
-
-  private void reportHeightChange() {
-    getLineWidget().changed();
-    updateSelection();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedCommentManager.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedCommentManager.java
deleted file mode 100644
index c92075f..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedCommentManager.java
+++ /dev/null
@@ -1,203 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gerrit.client.DiffObject;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.CommentInfo;
-import com.google.gerrit.client.diff.LineMapper.LineOnOtherInfo;
-import com.google.gerrit.client.diff.UnifiedChunkManager.LineRegionInfo;
-import com.google.gerrit.client.diff.UnifiedChunkManager.RegionType;
-import com.google.gerrit.client.ui.CommentLinkProcessor;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import net.codemirror.lib.CodeMirror;
-import net.codemirror.lib.Pos;
-import net.codemirror.lib.TextMarker.FromTo;
-
-/** Tracks comment widgets for {@link Unified}. */
-class UnifiedCommentManager extends CommentManager {
-
-  private final SortedMap<Integer, CommentGroup> mergedMap;
-
-  // In Unified, a CodeMirror line can have up to two CommentGroups - one for
-  // the base side and one for the revision, so we need to keep track of the
-  // duplicates and replace the entries in mergedMap on draft removal.
-  private final Map<Integer, CommentGroup> duplicates;
-
-  UnifiedCommentManager(
-      Unified host,
-      @Nullable Project.NameKey project,
-      DiffObject base,
-      PatchSet.Id revision,
-      String path,
-      CommentLinkProcessor clp,
-      boolean open) {
-    super(host, project, base, revision, path, clp, open);
-    mergedMap = new TreeMap<>();
-    duplicates = new HashMap<>();
-  }
-
-  @Override
-  SortedMap<Integer, CommentGroup> getMapForNav(DisplaySide side) {
-    return mergedMap;
-  }
-
-  @Override
-  void clearLine(DisplaySide side, int line, CommentGroup group) {
-    super.clearLine(side, line, group);
-
-    if (mergedMap.get(line) == group) {
-      mergedMap.remove(line);
-      if (duplicates.containsKey(line)) {
-        mergedMap.put(line, duplicates.remove(line));
-      }
-    }
-  }
-
-  @Override
-  void newDraftOnGutterClick(CodeMirror cm, String gutterClass, int cmLinePlusOne) {
-    if (!Gerrit.isSignedIn()) {
-      signInCallback(cm).run();
-    } else {
-      LineRegionInfo info = ((Unified) host).getLineRegionInfoFromCmLine(cmLinePlusOne - 1);
-      DisplaySide side =
-          gutterClass.equals(UnifiedTable.style.lineNumbersLeft()) ? DisplaySide.A : DisplaySide.B;
-      int line = info.line;
-      if (info.getSide() != side) {
-        line = host.lineOnOther(info.getSide(), line).getLine();
-      }
-      insertNewDraft(side, line + 1);
-    }
-  }
-
-  @Override
-  CommentGroup getCommentGroupOnActiveLine(CodeMirror cm) {
-    CommentGroup group = null;
-    if (cm.extras().hasActiveLine()) {
-      int cmLinePlusOne = cm.getLineNumber(cm.extras().activeLine()) + 1;
-      LineRegionInfo info = ((Unified) host).getLineRegionInfoFromCmLine(cmLinePlusOne - 1);
-      CommentGroup forSide = map(info.getSide()).get(cmLinePlusOne);
-      group = forSide == null ? map(info.getSide().otherSide()).get(cmLinePlusOne) : forSide;
-    }
-    return group;
-  }
-
-  @Override
-  Collection<Integer> getLinesWithCommentGroups() {
-    return mergedMap.tailMap(1).keySet();
-  }
-
-  @Override
-  String getTokenSuffixForActiveLine(CodeMirror cm) {
-    int cmLinePlusOne = cm.getLineNumber(cm.extras().activeLine()) + 1;
-    LineRegionInfo info = ((Unified) host).getLineRegionInfoFromCmLine(cmLinePlusOne - 1);
-    return (info.getSide() == DisplaySide.A ? "a" : "") + cmLinePlusOne;
-  }
-
-  @Override
-  void newDraft(CodeMirror cm) {
-    if (cm.somethingSelected()) {
-      FromTo fromTo = adjustSelection(cm);
-      Pos from = fromTo.from();
-      Pos to = fromTo.to();
-      Unified unified = (Unified) host;
-      UnifiedChunkManager manager = unified.getChunkManager();
-      LineRegionInfo fromInfo = unified.getLineRegionInfoFromCmLine(from.line());
-      LineRegionInfo toInfo = unified.getLineRegionInfoFromCmLine(to.line());
-      DisplaySide side = toInfo.getSide();
-
-      // Handle special cases in selections that span multiple regions. Force
-      // start line to be on the same side as the end line.
-      if ((fromInfo.type == RegionType.INSERT || fromInfo.type == RegionType.COMMON)
-          && toInfo.type == RegionType.DELETE) {
-        LineOnOtherInfo infoOnSideA = manager.lineMapper.lineOnOther(DisplaySide.B, fromInfo.line);
-        int startLineOnSideA = infoOnSideA.getLine();
-        if (infoOnSideA.isAligned()) {
-          from.line(startLineOnSideA);
-        } else {
-          from.line(startLineOnSideA + 1);
-        }
-        from.ch(0);
-        to.line(toInfo.line);
-      } else if (fromInfo.type == RegionType.DELETE && toInfo.type == RegionType.INSERT) {
-        LineOnOtherInfo infoOnSideB = manager.lineMapper.lineOnOther(DisplaySide.A, fromInfo.line);
-        int startLineOnSideB = infoOnSideB.getLine();
-        if (infoOnSideB.isAligned()) {
-          from.line(startLineOnSideB);
-        } else {
-          from.line(startLineOnSideB + 1);
-        }
-        from.ch(0);
-        to.line(toInfo.line);
-      } else if (fromInfo.type == RegionType.DELETE && toInfo.type == RegionType.COMMON) {
-        int toLineOnSideA = manager.lineMapper.lineOnOther(DisplaySide.B, toInfo.line).getLine();
-        from.line(fromInfo.line);
-        // Force the end line to be on the same side as the start line.
-        to.line(toLineOnSideA);
-        side = DisplaySide.A;
-      } else { // Common case
-        from.line(fromInfo.line);
-        to.line(toInfo.line);
-      }
-
-      addDraftBox(
-              side,
-              CommentInfo.create(
-                  getPath(),
-                  getStoredSideFromDisplaySide(side),
-                  to.line() + 1,
-                  CommentRange.create(fromTo),
-                  false))
-          .setEdit(true);
-      cm.setCursor(Pos.create(host.getCmLine(to.line(), side), to.ch()));
-      cm.setSelection(cm.getCursor());
-    } else {
-      int cmLine = cm.getLineNumber(cm.extras().activeLine());
-      LineRegionInfo info = ((Unified) host).getLineRegionInfoFromCmLine(cmLine);
-      insertNewDraft(info.getSide(), cmLine + 1);
-    }
-  }
-
-  @Override
-  CommentGroup group(DisplaySide side, int cmLinePlusOne) {
-    Map<Integer, CommentGroup> map = map(side);
-    CommentGroup existing = map.get(cmLinePlusOne);
-    if (existing != null) {
-      return existing;
-    }
-
-    UnifiedCommentGroup g =
-        new UnifiedCommentGroup(this, host.getCmFromSide(side), side, cmLinePlusOne);
-    map.put(cmLinePlusOne, g);
-    if (mergedMap.containsKey(cmLinePlusOne)) {
-      duplicates.put(cmLinePlusOne, mergedMap.remove(cmLinePlusOne));
-    }
-    mergedMap.put(cmLinePlusOne, g);
-
-    if (isAttached()) {
-      g.init(host.getDiffTable());
-      g.handleRedraw();
-    }
-
-    return g;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedDiffChunkInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedDiffChunkInfo.java
deleted file mode 100644
index dc827cb..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedDiffChunkInfo.java
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-public class UnifiedDiffChunkInfo extends DiffChunkInfo {
-
-  private int cmLine;
-
-  UnifiedDiffChunkInfo(DisplaySide side, int start, int end, int cmLine, boolean edit) {
-    super(side, start, end, edit);
-    this.cmLine = cmLine;
-  }
-
-  int getCmLine() {
-    return cmLine;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedTable.java
deleted file mode 100644
index 2d5df63..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedTable.java
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gerrit.client.DiffObject;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.user.client.ui.HTMLPanel;
-
-/**
- * A table with one row and one column to hold a unified CodeMirror displaying the files to be
- * compared.
- */
-class UnifiedTable extends DiffTable {
-  interface Binder extends UiBinder<HTMLPanel, UnifiedTable> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  interface DiffTableStyle extends CssResource {
-    String intralineInsert();
-
-    String intralineDelete();
-
-    String diffInsert();
-
-    String diffDelete();
-
-    String unifiedLineNumber();
-
-    String unifiedLineNumberEmpty();
-
-    String lineNumbersLeft();
-
-    String lineNumbersRight();
-  }
-
-  private Unified parent;
-  @UiField Element cm;
-  @UiField static DiffTableStyle style;
-
-  UnifiedTable(Unified parent, DiffObject base, DiffObject revision, String path) {
-    super(parent, base, revision, path);
-
-    initWidget(uiBinder.createAndBindUi(this));
-    this.parent = parent;
-  }
-
-  @Override
-  void setHideEmptyPane(boolean hide) {}
-
-  @Override
-  boolean isVisibleA() {
-    return true;
-  }
-
-  @Override
-  Unified getDiffScreen() {
-    return parent;
-  }
-
-  @Override
-  int getHeaderHeight() {
-    int h = patchSetSelectBoxA.getOffsetHeight() + patchSetSelectBoxB.getOffsetHeight();
-    if (hasHeader()) {
-      h += diffHeaderRow.getOffsetHeight();
-    }
-    return h;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedTable.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedTable.ui.xml
deleted file mode 100644
index c2cefe4..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedTable.ui.xml
+++ /dev/null
@@ -1,152 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2013 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'
-    xmlns:d='urn:import:com.google.gerrit.client.diff'>
-  <ui:with field='res' type='com.google.gerrit.client.diff.Resources'/>
-  <ui:style gss='false' type='com.google.gerrit.client.diff.UnifiedTable.DiffTableStyle'>
-    @external .CodeMirror, .CodeMirror-selectedtext;
-    @external .CodeMirror-vscrollbar .CodeMirror-scroll;
-    @external .CodeMirror-dialog-bottom;
-    @external .CodeMirror-cursor;
-
-    @external .dark, .unifiedLineNumber, .noIntraline, .showLineNumbers;
-
-    .difftable .patchSetNav,
-    .difftable .CodeMirror {
-      -webkit-touch-callout: none;
-      -webkit-user-select: none;
-      -khtml-user-select: none;
-      -moz-user-select: none;
-      -ms-user-select: none;
-    }
-
-    .difftable .CodeMirror pre {
-      overflow: visible;
-      border-right: 0;
-      width: auto;
-    }
-
-    /* Preserve space for underscores. If this changes
-     * see ChunkManager.addPadding() and adjust there.
-     */
-    .difftable .CodeMirror pre,
-    .difftable .CodeMirror pre span {
-      padding-bottom: 1px;
-    }
-    .table {
-      width: 100%;
-      table-layout: fixed;
-      border-spacing: 0;
-    }
-    .table td { padding: 0 }
-
-    /* Hide scrollbars. */
-    .difftable .CodeMirror-scroll { padding-right: 0; }
-    .difftable .CodeMirror-vscrollbar { display: none !important; }
-
-    .diffDelete { background-color: #faa; }
-    .diffInsert { background-color: #9f9; }
-    .intralineDelete { background-color: #fee; }
-    .intralineInsert { background-color: #dfd; }
-    .noIntraline .intralineDelete { background-color: #faa; }
-    .noIntraline .intralineInsert { background-color: #9f9; }
-
-    .dark .diffDelete { background-color: #400; }
-    .dark .diffInsert { background-color: #444; }
-    .dark .intralineDelete { background-color: #888; }
-    .dark .intralineInsert { background-color: #bbb; }
-    .dark .noIntraline .intralineDelete { background-color: #400; }
-    .dark .noIntraline .intralineInsert { background-color: #444; }
-
-    .patchSetNav, .diff_header {
-      background-color: #f7f7f7;
-      line-height: 1;
-    }
-
-    .difftable .CodeMirror-selectedtext {
-      background-color: inherit !important;
-    }
-    .difftable .CodeMirror div.CodeMirror-cursor {
-      border-left: 2px solid black;
-    }
-    .difftable .CodeMirror-dialog-bottom {
-      border-top: 0;
-      border-left: 1px solid #000;
-      border-bottom: 1px solid #000;
-      background-color: #f7f7f7;
-      top: 0;
-      right: 0;
-      bottom: auto;
-      left: auto;
-    }
-    .showLineNumbers .lineNumbersLeft, .showLineNumbers .lineNumbersRight {
-      min-width: 20px;
-      width: 3em; /* TODO: This needs to be set based on number of lines */
-    }
-    .showLineNumbers .lineNumbersLeft {
-      border-right: 1px solid #ddd;
-    }
-    .unifiedLineNumber {
-      display: none;
-    }
-    .showLineNumbers .unifiedLineNumber {
-      display: block;
-      cursor: pointer;
-      padding: 0 3px 0 5px;
-      min-width: 20px;
-      text-align: right;
-      color: #999;
-    }
-    .unifiedLineNumberEmpty {
-      display: none;
-    }
-    .showLineNumbers .unifiedLineNumberEmpty {
-      display: block;
-      margin-left: 28px;
-      border-left: 2px solid #d64040;
-      padding-bottom: 1px;
-    }
-  </ui:style>
-  <g:HTMLPanel styleName='{style.difftable}'>
-    <table class='{style.table}'>
-      <tr ui:field='patchSetNavRow' class='{style.patchSetNav}'>
-        <td>
-          <table class='{style.table}'>
-            <tr>
-              <td ui:field='patchSetNavCellA'>
-                <d:PatchSetSelectBox ui:field='patchSetSelectBoxA' />
-              </td>
-            </tr>
-            <tr>
-              <td ui:field='patchSetNavCellB'>
-                <d:PatchSetSelectBox ui:field='patchSetSelectBoxB' />
-              </td>
-            </tr>
-          </table>
-        </td>
-      </tr>
-      <tr ui:field='diffHeaderRow' class='{res.diffTableStyle.diffHeader}'>
-        <td><pre ui:field='diffHeaderText' /></td>
-      </tr>
-      <tr>
-        <td ui:field='cm'/>
-      </tr>
-    </table>
-    <g:FlowPanel ui:field='widgets' visible='false'/>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UpToChangeCommand.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UpToChangeCommand.java
deleted file mode 100644
index 50ef0d7..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UpToChangeCommand.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.patches.PatchUtil;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwtexpui.globalkey.client.KeyCommand;
-
-class UpToChangeCommand extends KeyCommand {
-  private final PatchSet.Id revision;
-  @Nullable private final Project.NameKey project;
-
-  UpToChangeCommand(@Nullable Project.NameKey project, PatchSet.Id revision, int mask, int key) {
-    super(mask, key, PatchUtil.C.upToChange());
-    this.revision = revision;
-    this.project = project;
-  }
-
-  @Override
-  public void onKeyPress(KeyPressEvent event) {
-    Gerrit.display(PageLinks.toChange(project, revision.getParentKey(), revision.getId()));
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/goNext.png b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/goNext.png
deleted file mode 100644
index 872c197..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/goNext.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/goPrev.png b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/goPrev.png
deleted file mode 100644
index d68f29b..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/goPrev.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/goUp.png b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/goUp.png
deleted file mode 100644
index f75bed4..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/goUp.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/DocConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/DocConstants.java
deleted file mode 100644
index 2958783..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/DocConstants.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.documentation;
-
-import com.google.gwt.i18n.client.Constants;
-
-public interface DocConstants extends Constants {
-  String keyReloadSearch();
-
-  String docItemHelp();
-
-  String docTableColumnTitle();
-
-  String docTableNone();
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/DocConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/DocConstants.properties
deleted file mode 100644
index b48c507..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/DocConstants.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-keyReloadSearch = Reload documentation list
-
-docItemHelp = documentation
-docTableColumnTitle = Title
-docTableNone = (None)
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/DocInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/DocInfo.java
deleted file mode 100644
index 5fcb6b0..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/DocInfo.java
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.documentation;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class DocInfo extends JavaScriptObject {
-
-  public final native String title() /*-{ return this.title; }-*/;
-
-  public final native String url() /*-{ return this.url; }-*/;
-
-  public static DocInfo create() {
-    return (DocInfo) createObject();
-  }
-
-  protected DocInfo() {}
-
-  public final String getFullUrl() {
-    return GWT.getHostPageBaseURL() + url();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/DocMessages.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/DocMessages.java
deleted file mode 100644
index 7d76f7b..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/DocMessages.java
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.documentation;
-
-import com.google.gwt.i18n.client.Messages;
-
-public interface DocMessages extends Messages {
-  String docQueryWindowTitle(String query);
-
-  String docQueryPageTitle(String query);
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/DocMessages.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/DocMessages.properties
deleted file mode 100644
index 8810a4a..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/DocMessages.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-docQueryWindowTitle = {0}
-docQueryPageTitle = Search for {0} in documentation
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/DocScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/DocScreen.java
deleted file mode 100644
index 0a87d29..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/DocScreen.java
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.documentation;
-
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.client.ui.Screen;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtorm.client.KeyUtil;
-
-public class DocScreen extends Screen {
-  private static final String URI = "/Documentation/";
-
-  private DocTable table;
-  private final String query;
-
-  public DocScreen(String query) {
-    this.query = KeyUtil.decode(query);
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-
-    table = new DocTable();
-    table.setSavePointerId(query);
-    add(table);
-
-    setWindowTitle(Util.M.docQueryWindowTitle(query));
-    setPageTitle(Util.M.docQueryPageTitle(query));
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    doQuery();
-  }
-
-  @Override
-  public void registerKeys() {
-    super.registerKeys();
-    table.setRegisterKeys(true);
-  }
-
-  private AsyncCallback<JsArray<DocInfo>> loadCallback() {
-    return new GerritCallback<JsArray<DocInfo>>() {
-      @Override
-      public void onSuccess(JsArray<DocInfo> result) {
-        displayResults(result);
-        display();
-      }
-    };
-  }
-
-  private void displayResults(JsArray<DocInfo> result) {
-    table.display(result);
-    table.finishDisplay();
-  }
-
-  private void doQuery() {
-    RestApi call = new RestApi(URI);
-    call.addParameterRaw("q", KeyUtil.encode(query));
-    call.get(loadCallback());
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/DocTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/DocTable.java
deleted file mode 100644
index 677c2bf..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/DocTable.java
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.documentation;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.ui.NavigationTable;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
-import com.google.gwt.user.client.ui.HTMLTable.Cell;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
-
-class DocTable extends NavigationTable<DocInfo> {
-  private static final int C_TITLE = 1;
-
-  private int rows;
-  private int dataBeginRow;
-
-  DocTable() {
-    super(Util.C.docItemHelp());
-
-    table.setText(0, C_TITLE, Util.C.docTableColumnTitle());
-
-    FlexCellFormatter fmt = table.getFlexCellFormatter();
-    fmt.addStyleName(0, C_TITLE, Gerrit.RESOURCES.css().dataHeader());
-
-    table.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            Cell cell = table.getCellForEvent(event);
-            if (cell == null) {
-              return;
-            }
-            if (getRowItem(cell.getRowIndex()) != null) {
-              movePointerTo(cell.getRowIndex());
-            }
-          }
-        });
-  }
-
-  @Override
-  protected Object getRowItemKey(DocInfo item) {
-    return item.url();
-  }
-
-  @Override
-  protected void onOpenRow(int row) {
-    DocInfo d = getRowItem(row);
-    Window.Location.assign(d.getFullUrl());
-  }
-
-  private void insertNoneRow(int row) {
-    table.insertRow(row);
-    table.setText(row, 0, Util.C.docTableNone());
-    FlexCellFormatter fmt = table.getFlexCellFormatter();
-    fmt.setStyleName(row, 0, Gerrit.RESOURCES.css().emptySection());
-  }
-
-  private void insertDocRow(int row) {
-    table.insertRow(row);
-    applyDataRowStyle(row);
-  }
-
-  @Override
-  protected void applyDataRowStyle(int row) {
-    super.applyDataRowStyle(row);
-    CellFormatter fmt = table.getCellFormatter();
-    fmt.addStyleName(row, C_TITLE, Gerrit.RESOURCES.css().dataCell());
-    fmt.addStyleName(row, C_TITLE, Gerrit.RESOURCES.css().cSUBJECT());
-  }
-
-  private void populateDocRow(int row, DocInfo d) {
-    table.setWidget(row, C_TITLE, new DocLink(d));
-    setRowItem(row, d);
-  }
-
-  public void display(JsArray<DocInfo> docList) {
-    int sz = docList != null ? docList.length() : 0;
-    boolean hadData = rows > 0;
-
-    if (hadData) {
-      while (sz < rows) {
-        table.removeRow(dataBeginRow);
-        rows--;
-      }
-    } else {
-      table.removeRow(dataBeginRow);
-    }
-
-    if (sz == 0) {
-      insertNoneRow(dataBeginRow);
-      return;
-    }
-
-    while (rows < sz) {
-      insertDocRow(dataBeginRow + rows);
-      rows++;
-    }
-    for (int i = 0; i < sz; i++) {
-      populateDocRow(dataBeginRow + i, docList.get(i));
-    }
-  }
-
-  public static class DocLink extends Anchor {
-    DocLink(DocInfo d) {
-      super(com.google.gerrit.client.changes.Util.cropSubject(d.title()));
-      setHref(d.getFullUrl());
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/Util.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/Util.java
deleted file mode 100644
index 273ead8..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/documentation/Util.java
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.documentation;
-
-import com.google.gwt.core.client.GWT;
-
-public class Util {
-  public static final DocConstants C = GWT.create(DocConstants.class);
-  public static final DocMessages M = GWT.create(DocMessages.class);
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/download/DownloadCommandLink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/download/DownloadCommandLink.java
deleted file mode 100644
index 2b09175..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/download/DownloadCommandLink.java
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.download;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.info.DownloadInfo.DownloadCommandInfo;
-import com.google.gwt.aria.client.Roles;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.clippy.client.CopyableLabel;
-
-public class DownloadCommandLink extends Anchor implements ClickHandler {
-  private final CopyableLabel copyLabel;
-  private final String command;
-
-  public DownloadCommandLink(CopyableLabel copyLabel, DownloadCommandInfo commandInfo) {
-    super(commandInfo.name());
-    this.copyLabel = copyLabel;
-    this.command = commandInfo.command();
-
-    setStyleName(Gerrit.RESOURCES.css().downloadLink());
-    Roles.getTabRole().set(getElement());
-    addClickHandler(this);
-  }
-
-  @Override
-  public void onClick(ClickEvent event) {
-    event.preventDefault();
-    event.stopPropagation();
-
-    select();
-  }
-
-  void select() {
-    copyLabel.setText(command);
-
-    DownloadCommandPanel parent = (DownloadCommandPanel) getParent();
-    for (Widget w : parent) {
-      if (w != this && w instanceof DownloadCommandLink) {
-        w.removeStyleName(Gerrit.RESOURCES.css().downloadLink_Active());
-      }
-    }
-    parent.setCurrentCommand(this);
-    addStyleName(Gerrit.RESOURCES.css().downloadLink_Active());
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/download/DownloadCommandPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/download/DownloadCommandPanel.java
deleted file mode 100644
index 20cf3f3..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/download/DownloadCommandPanel.java
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.download;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gwt.aria.client.Roles;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Widget;
-
-public class DownloadCommandPanel extends FlowPanel {
-  private DownloadCommandLink currentCommand;
-
-  public DownloadCommandPanel() {
-    setStyleName(Gerrit.RESOURCES.css().downloadLinkList());
-    Roles.getTablistRole().set(getElement());
-  }
-
-  public boolean isEmpty() {
-    return getWidgetCount() == 0;
-  }
-
-  public void select() {
-    DownloadCommandLink first = null;
-
-    for (Widget w : this) {
-      if (w instanceof DownloadCommandLink) {
-        DownloadCommandLink d = (DownloadCommandLink) w;
-        if (currentCommand != null && d.getText().equals(currentCommand.getText())) {
-          d.select();
-          return;
-        }
-        if (first == null) {
-          first = d;
-        }
-      }
-    }
-
-    // If none matched the requested type, select the first in the
-    // group as that will at least give us an initial baseline.
-    if (first != null) {
-      first.select();
-    }
-  }
-
-  void setCurrentCommand(DownloadCommandLink cmd) {
-    currentCommand = cmd;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/download/DownloadPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/download/DownloadPanel.java
deleted file mode 100644
index b881505..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/download/DownloadPanel.java
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.download;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.info.DownloadInfo.DownloadCommandInfo;
-import com.google.gerrit.client.info.DownloadInfo.DownloadSchemeInfo;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.InlineLabel;
-import com.google.gwtexpui.clippy.client.CopyableLabel;
-import java.util.List;
-
-public abstract class DownloadPanel extends FlowPanel {
-  protected final String project;
-
-  private final DownloadCommandPanel commands = new DownloadCommandPanel();
-  private final DownloadUrlPanel urls = new DownloadUrlPanel();
-  private final CopyableLabel copyLabel = new CopyableLabel("");
-
-  public DownloadPanel(String project, boolean allowAnonymous) {
-    this.project = project;
-    copyLabel.setStyleName(Gerrit.RESOURCES.css().downloadLinkCopyLabel());
-    urls.add(DownloadUrlLink.createDownloadUrlLinks(allowAnonymous, this));
-
-    setupWidgets();
-  }
-
-  private void setupWidgets() {
-    if (!urls.isEmpty()) {
-      urls.select(Gerrit.getUserPreferences().downloadScheme());
-
-      FlowPanel p = new FlowPanel();
-      p.setStyleName(Gerrit.RESOURCES.css().downloadLinkHeader());
-      p.add(commands);
-      final InlineLabel glue = new InlineLabel();
-      glue.setStyleName(Gerrit.RESOURCES.css().downloadLinkHeaderGap());
-      p.add(glue);
-      p.add(urls);
-
-      add(p);
-      add(copyLabel);
-    }
-  }
-
-  void populateDownloadCommandLinks(DownloadSchemeInfo schemeInfo) {
-    commands.clear();
-    for (DownloadCommandInfo cmd : getCommands(schemeInfo)) {
-      commands.add(new DownloadCommandLink(copyLabel, cmd));
-    }
-    commands.select();
-  }
-
-  protected abstract List<DownloadCommandInfo> getCommands(DownloadSchemeInfo schemeInfo);
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/download/DownloadUrlLink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/download/DownloadUrlLink.java
deleted file mode 100644
index 76e7d7c..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/download/DownloadUrlLink.java
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.download;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.account.AccountApi;
-import com.google.gerrit.client.info.DownloadInfo.DownloadSchemeInfo;
-import com.google.gerrit.client.info.GeneralPreferences;
-import com.google.gwt.aria.client.Roles;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Widget;
-import java.util.ArrayList;
-import java.util.List;
-
-public class DownloadUrlLink extends Anchor implements ClickHandler {
-  public static List<DownloadUrlLink> createDownloadUrlLinks(
-      boolean allowAnonymous, DownloadPanel downloadPanel) {
-    List<DownloadUrlLink> urls = new ArrayList<>();
-    for (String s : Gerrit.info().download().schemes()) {
-      DownloadSchemeInfo scheme = Gerrit.info().download().scheme(s);
-      if (scheme.isAuthRequired() && !allowAnonymous) {
-        continue;
-      }
-      urls.add(new DownloadUrlLink(downloadPanel, scheme, s));
-    }
-    return urls;
-  }
-
-  private final DownloadPanel downloadPanel;
-  private final DownloadSchemeInfo schemeInfo;
-  private final String schemeName;
-
-  public DownloadUrlLink(
-      DownloadPanel downloadPanel, DownloadSchemeInfo schemeInfo, String schemeName) {
-    super(schemeName);
-    setStyleName(Gerrit.RESOURCES.css().downloadLink());
-    Roles.getTabRole().set(getElement());
-    addClickHandler(this);
-
-    this.downloadPanel = downloadPanel;
-    this.schemeInfo = schemeInfo;
-    this.schemeName = schemeName;
-  }
-
-  public String getSchemeName() {
-    return schemeName;
-  }
-
-  @Override
-  public void onClick(ClickEvent event) {
-    event.preventDefault();
-    event.stopPropagation();
-
-    select();
-
-    GeneralPreferences prefs = Gerrit.getUserPreferences();
-    if (Gerrit.isSignedIn() && !schemeName.equals(prefs.downloadScheme())) {
-      prefs.downloadScheme(schemeName);
-      GeneralPreferences in = GeneralPreferences.create();
-      in.downloadScheme(schemeName);
-      AccountApi.self()
-          .view("preferences")
-          .put(
-              in,
-              new AsyncCallback<JavaScriptObject>() {
-                @Override
-                public void onSuccess(JavaScriptObject result) {}
-
-                @Override
-                public void onFailure(Throwable caught) {}
-              });
-    }
-  }
-
-  void select() {
-    downloadPanel.populateDownloadCommandLinks(schemeInfo);
-
-    DownloadUrlPanel parent = (DownloadUrlPanel) getParent();
-    for (Widget w : parent) {
-      if (w != this && w instanceof DownloadUrlLink) {
-        w.removeStyleName(Gerrit.RESOURCES.css().downloadLink_Active());
-      }
-    }
-    addStyleName(Gerrit.RESOURCES.css().downloadLink_Active());
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/download/DownloadUrlPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/download/DownloadUrlPanel.java
deleted file mode 100644
index 6a5fbe4..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/download/DownloadUrlPanel.java
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.download;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gwt.aria.client.Roles;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Widget;
-import java.util.Collection;
-
-public class DownloadUrlPanel extends FlowPanel {
-
-  public DownloadUrlPanel() {
-    setStyleName(Gerrit.RESOURCES.css().downloadLinkList());
-    Roles.getTablistRole().set(getElement());
-  }
-
-  public boolean isEmpty() {
-    return getWidgetCount() == 0;
-  }
-
-  public void select(String schemeName) {
-    DownloadUrlLink first = null;
-
-    for (Widget w : this) {
-      if (w instanceof DownloadUrlLink) {
-        final DownloadUrlLink d = (DownloadUrlLink) w;
-        if (first == null) {
-          first = d;
-        }
-        if (d.getSchemeName().equals(schemeName)) {
-          d.select();
-          return;
-        }
-      }
-    }
-
-    // If none matched the requested type, select the first in the
-    // group as that will at least give us an initial baseline.
-    if (first != null) {
-      first.select();
-    }
-  }
-
-  public void add(Collection<DownloadUrlLink> links) {
-    for (Widget link : links) {
-      add(link);
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditConstants.java
deleted file mode 100644
index b70c209..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditConstants.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.editor;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.i18n.client.Constants;
-
-interface EditConstants extends Constants {
-  EditConstants I = GWT.create(EditConstants.class);
-
-  String closeUnsavedChanges();
-
-  String cancelUnsavedChanges();
-
-  String gotoLineNumber();
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditConstants.properties
deleted file mode 100644
index 2e8a087..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditConstants.properties
+++ /dev/null
@@ -1,7 +0,0 @@
-closeUnsavedChanges = Unsaved changes were made to this file.
-
-cancelUnsavedChanges = Unsaved changes were made to this file.\n\
-  \n\
-  Discard unsaved changes?
-
-gotoLineNumber = Go to Line:
\ No newline at end of file
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditFileInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditFileInfo.java
deleted file mode 100644
index 3f9d732..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditFileInfo.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.editor;
-
-import com.google.gerrit.client.DiffWebLinkInfo;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-
-public class EditFileInfo extends JavaScriptObject {
-  public final native JsArray<DiffWebLinkInfo> webLinks() /*-{ return this.web_links; }-*/;
-
-  protected EditFileInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditPreferencesAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditPreferencesAction.java
deleted file mode 100644
index e11ded0..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditPreferencesAction.java
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.editor;
-
-import com.google.gerrit.client.account.EditPreferences;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.PopupPanel.PositionCallback;
-
-class EditPreferencesAction {
-  private final EditScreen view;
-  private final EditPreferences prefs;
-  private PopupPanel popup;
-  private EditPreferencesBox current;
-
-  EditPreferencesAction(EditScreen view, EditPreferences prefs) {
-    this.view = view;
-    this.prefs = prefs;
-  }
-
-  void show() {
-    if (popup != null) {
-      hide();
-      return;
-    }
-
-    current = new EditPreferencesBox(view);
-    current.set(prefs);
-
-    popup = new PopupPanel(true, false);
-    popup.setStyleName(current.style.dialog());
-    popup.add(current);
-    popup.addCloseHandler(
-        new CloseHandler<PopupPanel>() {
-          @Override
-          public void onClose(CloseEvent<PopupPanel> event) {
-            view.getEditor().focus();
-            popup = null;
-            current = null;
-          }
-        });
-    popup.setPopupPositionAndShow(
-        new PositionCallback() {
-          @Override
-          public void setPosition(int offsetWidth, int offsetHeight) {
-            popup.setPopupPosition(300, 120);
-          }
-        });
-  }
-
-  void hide() {
-    if (popup != null) {
-      popup.hide();
-      popup = null;
-      current = null;
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditPreferencesBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditPreferencesBox.java
deleted file mode 100644
index 5157123..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditPreferencesBox.java
+++ /dev/null
@@ -1,333 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.editor;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.account.AccountApi;
-import com.google.gerrit.client.account.EditPreferences;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.ui.NpIntTextBox;
-import com.google.gerrit.extensions.client.EditPreferencesInfo;
-import com.google.gerrit.extensions.client.KeyMapType;
-import com.google.gerrit.extensions.client.Theme;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.Style.Visibility;
-import com.google.gwt.event.dom.client.ChangeEvent;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.ListBox;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.ToggleButton;
-import com.google.gwt.user.client.ui.UIObject;
-import net.codemirror.theme.ThemeLoader;
-
-/** Displays current edit preferences. */
-public class EditPreferencesBox extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, EditPreferencesBox> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  public interface Style extends CssResource {
-    String dialog();
-  }
-
-  private final EditScreen view;
-  private EditPreferences prefs;
-
-  @UiField Style style;
-  @UiField Element header;
-  @UiField Anchor close;
-  @UiField NpIntTextBox tabWidth;
-  @UiField NpIntTextBox lineLength;
-  @UiField NpIntTextBox indentUnit;
-  @UiField NpIntTextBox cursorBlinkRate;
-  @UiField ToggleButton topMenu;
-  @UiField ToggleButton syntaxHighlighting;
-  @UiField ToggleButton showTabs;
-  @UiField ToggleButton whitespaceErrors;
-  @UiField ToggleButton lineNumbers;
-  @UiField ToggleButton matchBrackets;
-  @UiField ToggleButton lineWrapping;
-  @UiField ToggleButton indentWithTabs;
-  @UiField ToggleButton autoCloseBrackets;
-  @UiField ToggleButton showBase;
-  @UiField ListBox theme;
-  @UiField ListBox keyMap;
-  @UiField Button apply;
-  @UiField Button save;
-
-  public EditPreferencesBox(EditScreen view) {
-    this.view = view;
-    initWidget(uiBinder.createAndBindUi(this));
-    initTheme();
-    initKeyMapType();
-
-    if (view == null) {
-      UIObject.setVisible(header, false);
-      apply.getElement().getStyle().setVisibility(Visibility.HIDDEN);
-    }
-  }
-
-  public Style getStyle() {
-    return style;
-  }
-
-  public void set(EditPreferences prefs) {
-    this.prefs = prefs;
-
-    tabWidth.setIntValue(prefs.tabSize());
-    lineLength.setIntValue(prefs.lineLength());
-    indentUnit.setIntValue(prefs.indentUnit());
-    cursorBlinkRate.setIntValue(prefs.cursorBlinkRate());
-    topMenu.setValue(!prefs.hideTopMenu());
-    syntaxHighlighting.setValue(prefs.syntaxHighlighting());
-    showTabs.setValue(prefs.showTabs());
-    whitespaceErrors.setValue(prefs.showWhitespaceErrors());
-    lineNumbers.setValue(prefs.hideLineNumbers());
-    matchBrackets.setValue(prefs.matchBrackets());
-    lineWrapping.setValue(prefs.lineWrapping());
-    indentWithTabs.setValue(prefs.indentWithTabs());
-    autoCloseBrackets.setValue(prefs.autoCloseBrackets());
-    showBase.setValue(prefs.showBase());
-    setTheme(prefs.theme());
-    setKeyMapType(prefs.keyMapType());
-  }
-
-  @UiHandler("tabWidth")
-  void onTabWidth(ValueChangeEvent<String> e) {
-    String v = e.getValue();
-    if (v != null && v.length() > 0) {
-      prefs.tabSize(Math.max(1, Integer.parseInt(v)));
-      if (view != null) {
-        view.setOption("tabSize", v);
-      }
-    }
-  }
-
-  @UiHandler("lineLength")
-  void onLineLength(ValueChangeEvent<String> e) {
-    String v = e.getValue();
-    if (v != null && v.length() > 0) {
-      prefs.lineLength(Math.max(1, Integer.parseInt(v)));
-      if (view != null) {
-        view.setLineLength(prefs.lineLength());
-      }
-    }
-  }
-
-  @UiHandler("indentUnit")
-  void onIndentUnit(ValueChangeEvent<String> e) {
-    String v = e.getValue();
-    if (v != null && v.length() > 0) {
-      prefs.indentUnit(Math.max(0, Integer.parseInt(v)));
-      if (view != null) {
-        view.setIndentUnit(prefs.indentUnit());
-      }
-    }
-  }
-
-  @UiHandler("cursorBlinkRate")
-  void onCursoBlinkRate(ValueChangeEvent<String> e) {
-    String v = e.getValue();
-    if (v != null && v.length() > 0) {
-      // A negative value hides the cursor entirely:
-      // don't let user shoot himself in the foot.
-      prefs.cursorBlinkRate(Math.max(0, Integer.parseInt(v)));
-      if (view != null) {
-        view.setOption("cursorBlinkRate", prefs.cursorBlinkRate());
-      }
-    }
-  }
-
-  @UiHandler("topMenu")
-  void onTopMenu(ValueChangeEvent<Boolean> e) {
-    prefs.hideTopMenu(!e.getValue());
-    if (view != null) {
-      Gerrit.setHeaderVisible(!prefs.hideTopMenu());
-      view.adjustHeight();
-    }
-  }
-
-  @UiHandler("showTabs")
-  void onShowTabs(ValueChangeEvent<Boolean> e) {
-    prefs.showTabs(e.getValue());
-    if (view != null) {
-      view.setShowTabs(prefs.showTabs());
-    }
-  }
-
-  @UiHandler("whitespaceErrors")
-  void onshowTrailingSpace(ValueChangeEvent<Boolean> e) {
-    prefs.showWhitespaceErrors(e.getValue());
-    if (view != null) {
-      view.setShowWhitespaceErrors(prefs.showWhitespaceErrors());
-    }
-  }
-
-  @UiHandler("lineNumbers")
-  void onLineNumbers(ValueChangeEvent<Boolean> e) {
-    prefs.hideLineNumbers(e.getValue());
-    if (view != null) {
-      view.setShowLineNumbers(prefs.hideLineNumbers());
-    }
-  }
-
-  @UiHandler("syntaxHighlighting")
-  void onSyntaxHighlighting(ValueChangeEvent<Boolean> e) {
-    prefs.syntaxHighlighting(e.getValue());
-    if (view != null) {
-      view.setSyntaxHighlighting(prefs.syntaxHighlighting());
-    }
-  }
-
-  @UiHandler("matchBrackets")
-  void onMatchBrackets(ValueChangeEvent<Boolean> e) {
-    prefs.matchBrackets(e.getValue());
-    if (view != null) {
-      view.setOption("matchBrackets", prefs.matchBrackets());
-    }
-  }
-
-  @UiHandler("lineWrapping")
-  void onLineWrapping(ValueChangeEvent<Boolean> e) {
-    prefs.lineWrapping(e.getValue());
-    if (view != null) {
-      view.getEditor().setOption("lineWrapping", prefs.lineWrapping());
-    }
-  }
-
-  @UiHandler("indentWithTabs")
-  void onIndentWithTabs(ValueChangeEvent<Boolean> e) {
-    prefs.indentWithTabs(e.getValue());
-    if (view != null) {
-      view.getEditor().setOption("indentWithTabs", prefs.indentWithTabs());
-    }
-  }
-
-  @UiHandler("autoCloseBrackets")
-  void onCloseBrackets(ValueChangeEvent<Boolean> e) {
-    prefs.autoCloseBrackets(e.getValue());
-    if (view != null) {
-      view.getEditor().setOption("autoCloseBrackets", prefs.autoCloseBrackets());
-    }
-  }
-
-  @UiHandler("showBase")
-  void onShowBase(ValueChangeEvent<Boolean> e) {
-    Boolean value = e.getValue();
-    prefs.showBase(value);
-    if (view != null) {
-      view.showBase.setValue(value, true);
-    }
-  }
-
-  @UiHandler("theme")
-  void onTheme(@SuppressWarnings("unused") ChangeEvent e) {
-    final Theme newTheme = Theme.valueOf(theme.getValue(theme.getSelectedIndex()));
-    prefs.theme(newTheme);
-    if (view != null) {
-      ThemeLoader.loadTheme(
-          newTheme,
-          new GerritCallback<Void>() {
-            @Override
-            public void onSuccess(Void result) {
-              view.setTheme(newTheme);
-            }
-          });
-    }
-  }
-
-  @UiHandler("keyMap")
-  void onKeyMap(@SuppressWarnings("unused") ChangeEvent e) {
-    KeyMapType keyMapType = KeyMapType.valueOf(keyMap.getValue(keyMap.getSelectedIndex()));
-    prefs.keyMapType(keyMapType);
-    if (view != null) {
-      view.setOption("keyMap", keyMapType.name().toLowerCase());
-    }
-  }
-
-  @UiHandler("apply")
-  void onApply(@SuppressWarnings("unused") ClickEvent e) {
-    close();
-  }
-
-  @UiHandler("save")
-  void onSave(@SuppressWarnings("unused") ClickEvent e) {
-    AccountApi.putEditPreferences(
-        prefs,
-        new GerritCallback<EditPreferences>() {
-          @Override
-          public void onSuccess(EditPreferences p) {
-            Gerrit.setEditPreferences(p.copyTo(new EditPreferencesInfo()));
-          }
-        });
-    if (view != null) {
-      close();
-    }
-  }
-
-  @UiHandler("close")
-  void onClose(ClickEvent e) {
-    e.preventDefault();
-    close();
-  }
-
-  private void close() {
-    ((PopupPanel) getParent()).hide();
-  }
-
-  private void setTheme(Theme v) {
-    String name = v != null ? v.name() : Theme.DEFAULT.name();
-    for (int i = 0; i < theme.getItemCount(); i++) {
-      if (theme.getValue(i).equals(name)) {
-        theme.setSelectedIndex(i);
-        return;
-      }
-    }
-    theme.setSelectedIndex(0);
-  }
-
-  private void initTheme() {
-    for (Theme t : Theme.values()) {
-      theme.addItem(t.name().toLowerCase(), t.name());
-    }
-  }
-
-  private void setKeyMapType(KeyMapType v) {
-    String name = v != null ? v.name() : KeyMapType.DEFAULT.name();
-    for (int i = 0; i < keyMap.getItemCount(); i++) {
-      if (keyMap.getValue(i).equals(name)) {
-        keyMap.setSelectedIndex(i);
-        return;
-      }
-    }
-    keyMap.setSelectedIndex(0);
-  }
-
-  private void initKeyMapType() {
-    for (KeyMapType t : KeyMapType.values()) {
-      keyMap.addItem(t.name().toLowerCase(), t.name());
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditPreferencesBox.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditPreferencesBox.ui.xml
deleted file mode 100644
index f5ec71e..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditPreferencesBox.ui.xml
+++ /dev/null
@@ -1,282 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'
-    xmlns:x='urn:import:com.google.gerrit.client.ui'>
-  <ui:style type='com.google.gerrit.client.editor.EditPreferencesBox.Style'>
-    @external .gwt-TextBox;
-    @external .gwt-ToggleButton .html-face;
-    @external .gwt-ToggleButton-up;
-    @external .gwt-ToggleButton-up-hovering;
-    @external .gwt-ToggleButton-up-disabled;
-    @external .gwt-ToggleButton-down;
-    @external .gwt-ToggleButton-down-hovering;
-    @external .gwt-ToggleButton-down-disabled;
-
-    .dialog {
-      background: rgba(0, 0, 0, 0.85) none repeat scroll 0 50%;
-      color: #ffffff;
-      font-family: arial,sans-serif;
-      font-weight: bold;
-      overflow: auto !important;
-      bottom: 0;
-      text-align: left;
-      text-shadow: 1px 1px 7px #000000;
-      min-width: 300px;
-      z-index: 200;
-      border-radius: 10px;
-    }
-
-    @if user.agent safari {
-      .dialog {
-        \-webkit-border-radius: 10px;
-      }
-    }
-
-    @if user.agent gecko1_8 {
-      .dialog {
-        \-moz-border-radius: 10px;
-      }
-    }
-
-    .box { margin: 10px; }
-    .box .gwt-TextBox { padding: 0; }
-    .context { vertical-align: bottom; }
-
-    .table tr { min-height: 23px; }
-    .table th,
-    .table td {
-      white-space: nowrap;
-      color: #ffffff;
-    }
-    .table th {
-      padding-right: 8px;
-      text-align: right;
-    }
-
-    .box a,
-    .box a:visited,
-    .box a:hover {
-      color: #dddd00;
-    }
-
-    .box .gwt-ToggleButton {
-      position: relative;
-      height: 19px;
-      width: 140px;
-      background: #fff;
-      color: #000;
-      text-shadow: none;
-    }
-    .box .gwt-ToggleButton .html-face {
-      position: absolute;
-      top: 0;
-      width: 68px;
-      height: 17px;
-      line-height: 17px;
-      text-align: center;
-      border-width: 1px;
-    }
-
-    .box .gwt-ToggleButton-up,
-    .box .gwt-ToggleButton-up-hovering,
-    .box .gwt-ToggleButton-up-disabled,
-    .box .gwt-ToggleButton-down,
-    .box .gwt-ToggleButton-down-hovering,
-    .box .gwt-ToggleButton-down-disabled {
-      padding: 0;
-      border: 0;
-    }
-    .box .gwt-ToggleButton-up .html-face,
-    .box .gwt-ToggleButton-up-hovering .html-face {
-      left: 0;
-      background: #cacaca;
-      border-style: outset;
-    }
-    .box .gwt-ToggleButton-down .html-face,
-    .box .gwt-ToggleButton-down-hovering .html-face {
-      right: 0;
-      background: #bcf;
-      border-style: inset;
-    }
-
-    .box button {
-      margin: 6px 3px 0 0;
-      border-color: rgba(0, 0, 0, 0.1);
-      text-align: center;
-      font-size: 8pt;
-      font-weight: bold;
-      border: 1px solid;
-      cursor: pointer;
-      color: #444;
-      background-color: #f5f5f5;
-      background-image: -webkit-linear-gradient(top, #f5f5f5, #f1f1f1);
-      -webkit-border-radius: 2px;
-      -webkit-box-sizing: content-box;
-    }
-    .box button div {
-      color: #444;
-      height: 10px;
-      min-width: 54px;
-      line-height: 10px;
-      white-space: nowrap;
-    }
-
-    button.apply {
-      background-color: #4d90fe;
-      background-image: -webkit-linear-gradient(top, #4d90fe, #4d90fe);
-    }
-    button.apply div { color: #fff; }
-
-    button.save {
-      margin-left: 10px;
-      color: #d14836;
-      background-color: #d14836;
-      background-image: -webkit-linear-gradient(top, #d14836, #d14836);
-    }
-    button.save div { color: #fff; }
-  </ui:style>
-
-  <g:HTMLPanel styleName='{style.box}'>
-    <div ui:field='header'>
-      <table style='width: 100%'>
-        <tr>
-          <td><ui:msg>Edit Preferences</ui:msg></td>
-          <td style='text-align: right'>
-            <g:Anchor ui:field='close' href='javascript:;'><ui:msg>Close</ui:msg></g:Anchor>
-          </td>
-        </tr>
-      </table>
-      <hr/>
-    </div>
-    <table class='{style.table}'>
-      <tr>
-        <th><ui:msg>Theme</ui:msg></th>
-        <td><g:ListBox ui:field='theme'/></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Key Map</ui:msg></th>
-        <td><g:ListBox ui:field='keyMap'/></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Tab Width</ui:msg></th>
-        <td><x:NpIntTextBox ui:field='tabWidth'
-            visibleLength='4'
-            alignment='RIGHT'/></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Columns</ui:msg></th>
-        <td><x:NpIntTextBox ui:field='lineLength'
-            visibleLength='4'
-            alignment='RIGHT'/></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Indent Unit</ui:msg></th>
-        <td><x:NpIntTextBox ui:field='indentUnit'
-            visibleLength='4'
-            alignment='RIGHT'/></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Cursor Blink Rate</ui:msg></th>
-        <td><x:NpIntTextBox ui:field='cursorBlinkRate'
-            visibleLength='4'
-            alignment='RIGHT'/></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Top Menu</ui:msg></th>
-        <td><g:ToggleButton ui:field='topMenu'>
-          <g:upFace><ui:msg>Hide</ui:msg></g:upFace>
-          <g:downFace><ui:msg>Show</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Syntax Highlighting</ui:msg></th>
-        <td><g:ToggleButton ui:field='syntaxHighlighting'>
-          <g:upFace><ui:msg>Hide</ui:msg></g:upFace>
-          <g:downFace><ui:msg>Show</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Show Tabs</ui:msg></th>
-        <td><g:ToggleButton ui:field='showTabs'>
-          <g:upFace><ui:msg>Hide</ui:msg></g:upFace>
-          <g:downFace><ui:msg>Show</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-      <th><ui:msg>Whitespace Errors</ui:msg></th>
-        <td><g:ToggleButton ui:field='whitespaceErrors'>
-          <g:upFace><ui:msg>Hide</ui:msg></g:upFace>
-          <g:downFace><ui:msg>Show</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Line Numbers</ui:msg></th>
-        <td><g:ToggleButton ui:field='lineNumbers'>
-          <g:upFace><ui:msg>Hide</ui:msg></g:upFace>
-          <g:downFace><ui:msg>Show</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Match Brackets</ui:msg></th>
-        <td><g:ToggleButton ui:field='matchBrackets'>
-          <g:upFace><ui:msg>Off</ui:msg></g:upFace>
-          <g:downFace><ui:msg>On</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Line Wrapping</ui:msg></th>
-        <td><g:ToggleButton ui:field='lineWrapping'>
-          <g:upFace><ui:msg>Off</ui:msg></g:upFace>
-          <g:downFace><ui:msg>On</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Indent With Tabs</ui:msg></th>
-        <td><g:ToggleButton ui:field='indentWithTabs'>
-          <g:upFace><ui:msg>Off</ui:msg></g:upFace>
-          <g:downFace><ui:msg>On</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Auto Close Brackets</ui:msg></th>
-        <td><g:ToggleButton ui:field='autoCloseBrackets'>
-          <g:upFace><ui:msg>Off</ui:msg></g:upFace>
-          <g:downFace><ui:msg>On</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <th><ui:msg>Show Base Version</ui:msg></th>
-        <td><g:ToggleButton ui:field='showBase'>
-          <g:upFace><ui:msg>Hide</ui:msg></g:upFace>
-          <g:downFace><ui:msg>Show</ui:msg></g:downFace>
-        </g:ToggleButton></td>
-      </tr>
-      <tr>
-        <td></td>
-        <td>
-          <g:Button ui:field='apply' styleName='{style.apply}'>
-            <div><ui:msg>Apply</ui:msg></div>
-          </g:Button>
-          <g:Button ui:field='save' styleName='{style.save}'>
-            <div><ui:msg>Save</ui:msg></div>
-          </g:Button>
-        </td>
-      </tr>
-    </table>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java
deleted file mode 100644
index cbf12a3..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java
+++ /dev/null
@@ -1,699 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.editor;
-
-import static com.google.gwt.dom.client.Style.Visibility.HIDDEN;
-import static com.google.gwt.dom.client.Style.Visibility.VISIBLE;
-
-import com.google.gerrit.client.DiffWebLinkInfo;
-import com.google.gerrit.client.Dispatcher;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.JumpKeys;
-import com.google.gerrit.client.VoidResult;
-import com.google.gerrit.client.account.EditPreferences;
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.changes.ChangeEditApi;
-import com.google.gerrit.client.diff.DiffApi;
-import com.google.gerrit.client.diff.DiffInfo;
-import com.google.gerrit.client.diff.Header;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.info.FileInfo;
-import com.google.gerrit.client.patches.PatchUtil;
-import com.google.gerrit.client.rpc.CallbackGroup;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.HttpCallback;
-import com.google.gerrit.client.rpc.HttpResponse;
-import com.google.gerrit.client.rpc.NativeString;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gerrit.client.ui.InlineHyperlink;
-import com.google.gerrit.client.ui.Screen;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.extensions.client.KeyMapType;
-import com.google.gerrit.extensions.client.Theme;
-import com.google.gerrit.reviewdb.client.Patch;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.Style.Unit;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.logical.shared.ResizeEvent;
-import com.google.gwt.event.logical.shared.ResizeHandler;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.Window.ClosingEvent;
-import com.google.gwt.user.client.Window.ClosingHandler;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.ImageResourceRenderer;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-import com.google.gwtexpui.safehtml.client.SafeHtml;
-import java.util.List;
-import net.codemirror.addon.AddonInjector;
-import net.codemirror.addon.Addons;
-import net.codemirror.lib.CodeMirror;
-import net.codemirror.lib.CodeMirror.ChangesHandler;
-import net.codemirror.lib.CodeMirror.CommandRunner;
-import net.codemirror.lib.Configuration;
-import net.codemirror.lib.KeyMap;
-import net.codemirror.lib.MergeView;
-import net.codemirror.lib.Pos;
-import net.codemirror.mode.ModeInfo;
-import net.codemirror.mode.ModeInjector;
-import net.codemirror.theme.ThemeLoader;
-
-public class EditScreen extends Screen {
-  interface Binder extends UiBinder<HTMLPanel, EditScreen> {}
-
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  interface Style extends CssResource {
-    String fullWidth();
-
-    String base();
-
-    String hideBase();
-  }
-
-  @Nullable private Project.NameKey projectKey;
-  private final PatchSet.Id revision;
-  private final String path;
-  private final int startLine;
-  private EditPreferences prefs;
-  private EditPreferencesAction editPrefsAction;
-  private MergeView mv;
-  private CodeMirror cmBase;
-  private CodeMirror cmEdit;
-  private HttpResponse<NativeString> content;
-  private HttpResponse<NativeString> baseContent;
-  private EditFileInfo editFileInfo;
-  private JsArray<DiffWebLinkInfo> diffLinks;
-
-  @UiField Element header;
-  @UiField Element project;
-  @UiField Element filePath;
-  @UiField FlowPanel linkPanel;
-  @UiField Element cursLine;
-  @UiField Element cursCol;
-  @UiField Element dirty;
-  @UiField CheckBox showBase;
-  @UiField Button close;
-  @UiField Button save;
-  @UiField Element editor;
-  @UiField Style style;
-
-  private HandlerRegistration resizeHandler;
-  private HandlerRegistration closeHandler;
-  private int generation;
-
-  public EditScreen(@Nullable Project.NameKey projectKey, Patch.Key patch, int startLine) {
-    this.projectKey = projectKey;
-    this.revision = patch.getParentKey();
-    this.path = patch.get();
-    this.startLine = startLine - 1;
-    setRequiresSignIn(true);
-    add(uiBinder.createAndBindUi(this));
-    addDomHandler(GlobalKey.STOP_PROPAGATION, KeyPressEvent.getType());
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-    setHeaderVisible(false);
-    setWindowTitle(FileInfo.getFileName(path));
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-
-    prefs = EditPreferences.create(Gerrit.getEditPreferences());
-
-    CallbackGroup group1 = new CallbackGroup();
-    final CallbackGroup group2 = new CallbackGroup();
-    final CallbackGroup group3 = new CallbackGroup();
-
-    CodeMirror.initLibrary(
-        group1.add(
-            new AsyncCallback<Void>() {
-              final AsyncCallback<Void> themeCallback = group3.addEmpty();
-
-              @Override
-              public void onSuccess(Void result) {
-                // Load theme after CM library to ensure theme can override CSS.
-                ThemeLoader.loadTheme(prefs.theme(), themeCallback);
-                group2.done();
-
-                new AddonInjector()
-                    .add(Addons.I.merge_bundled().getName())
-                    .inject(
-                        new AsyncCallback<Void>() {
-                          @Override
-                          public void onFailure(Throwable caught) {}
-
-                          @Override
-                          public void onSuccess(Void result) {
-                            if (!prefs.showBase() || revision.get() > 0) {
-                              group3.done();
-                            }
-                          }
-                        });
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {}
-            }));
-
-    ChangeApi.detail(
-        Project.NameKey.asStringOrNull(projectKey),
-        revision.getParentKey().get(),
-        group1.add(
-            new AsyncCallback<ChangeInfo>() {
-              @Override
-              public void onSuccess(ChangeInfo c) {
-                projectKey = c.projectNameKey();
-                project.setInnerText(c.project());
-                SafeHtml.setInnerHTML(filePath, Header.formatPath(path));
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {}
-            }));
-
-    if (revision.get() == 0) {
-      ChangeEditApi.getMeta(
-          Project.NameKey.asStringOrNull(projectKey),
-          revision,
-          path,
-          group1.add(
-              new AsyncCallback<EditFileInfo>() {
-                @Override
-                public void onSuccess(EditFileInfo editInfo) {
-                  editFileInfo = editInfo;
-                }
-
-                @Override
-                public void onFailure(Throwable e) {}
-              }));
-
-      if (prefs.showBase()) {
-        ChangeEditApi.get(
-            projectKey,
-            revision,
-            path,
-            true /* base */,
-            group1.addFinal(
-                new HttpCallback<NativeString>() {
-                  @Override
-                  public void onSuccess(HttpResponse<NativeString> fc) {
-                    baseContent = fc;
-                    group3.done();
-                  }
-
-                  @Override
-                  public void onFailure(Throwable e) {}
-                }));
-      } else {
-        group1.done();
-      }
-    } else {
-      // TODO(davido): We probably want to create dedicated GET EditScreenMeta
-      // REST endpoint. Abuse GET diff for now, as it retrieves links we need.
-      DiffApi.diff(Project.NameKey.asStringOrNull(projectKey), revision, path)
-          .webLinksOnly()
-          .get(
-              group1.addFinal(
-                  new AsyncCallback<DiffInfo>() {
-                    @Override
-                    public void onSuccess(DiffInfo diffInfo) {
-                      diffLinks = diffInfo.webLinks();
-                    }
-
-                    @Override
-                    public void onFailure(Throwable e) {}
-                  }));
-    }
-
-    ChangeEditApi.get(
-        projectKey,
-        revision,
-        path,
-        group2.add(
-            new HttpCallback<NativeString>() {
-              final AsyncCallback<Void> modeCallback = group3.addEmpty();
-
-              @Override
-              public void onSuccess(HttpResponse<NativeString> fc) {
-                content = fc;
-                if (revision.get() > 0) {
-                  baseContent = fc;
-                }
-
-                if (prefs.syntaxHighlighting()) {
-                  injectMode(fc.getContentType(), modeCallback);
-                } else {
-                  modeCallback.onSuccess(null);
-                }
-              }
-
-              @Override
-              public void onFailure(Throwable e) {
-                // "Not Found" means it's a new file.
-                if (RestApi.isNotFound(e)) {
-                  content = null;
-                  modeCallback.onSuccess(null);
-                } else {
-                  GerritCallback.showFailure(e);
-                }
-              }
-            }));
-
-    group3.addListener(
-        new ScreenLoadCallback<Void>(this) {
-          @Override
-          protected void preDisplay(Void result) {
-            initEditor();
-
-            renderLinks(editFileInfo, diffLinks);
-            editFileInfo = null;
-            diffLinks = null;
-
-            showBase.setValue(prefs.showBase(), true);
-            cmBase.refresh();
-          }
-        });
-  }
-
-  @Override
-  public void registerKeys() {
-    super.registerKeys();
-    KeyMap localKeyMap = KeyMap.create();
-    localKeyMap.on("Ctrl-L", gotoLine()).on("Cmd-L", gotoLine()).on("Cmd-S", save());
-
-    // TODO(davido): Find a better way to prevent key maps collisions
-    if (prefs.keyMapType() != KeyMapType.EMACS) {
-      localKeyMap.on("Ctrl-S", save());
-    }
-
-    cmBase.addKeyMap(localKeyMap);
-    cmEdit.addKeyMap(localKeyMap);
-  }
-
-  private Runnable gotoLine() {
-    return () -> cmEdit.execCommand("jumpToLine");
-  }
-
-  @Override
-  public void onShowView() {
-    super.onShowView();
-    Window.enableScrolling(false);
-    JumpKeys.enable(false);
-    if (prefs.hideTopMenu()) {
-      Gerrit.setHeaderVisible(false);
-    }
-    resizeHandler =
-        Window.addResizeHandler(
-            new ResizeHandler() {
-              @Override
-              public void onResize(ResizeEvent event) {
-                adjustHeight();
-              }
-            });
-    closeHandler =
-        Window.addWindowClosingHandler(
-            new ClosingHandler() {
-              @Override
-              public void onWindowClosing(ClosingEvent event) {
-                if (!cmEdit.isClean(generation)) {
-                  event.setMessage(EditConstants.I.closeUnsavedChanges());
-                }
-              }
-            });
-
-    generation = cmEdit.changeGeneration(true);
-    setClean(true);
-    cmEdit.on(
-        new ChangesHandler() {
-          @Override
-          public void handle(CodeMirror cm) {
-            setClean(cm.isClean(generation));
-          }
-        });
-
-    adjustHeight();
-    cmEdit.on("cursorActivity", updateCursorPosition());
-    setShowTabs(prefs.showTabs());
-    setLineLength(prefs.lineLength());
-    cmEdit.refresh();
-    cmEdit.focus();
-
-    if (startLine > 0) {
-      cmEdit.scrollToLine(startLine);
-    }
-    updateActiveLine();
-    editPrefsAction = new EditPreferencesAction(this, prefs);
-  }
-
-  @Override
-  protected void onUnload() {
-    super.onUnload();
-    if (cmBase != null) {
-      cmBase.getWrapperElement().removeFromParent();
-    }
-    if (cmEdit != null) {
-      cmEdit.getWrapperElement().removeFromParent();
-    }
-    if (resizeHandler != null) {
-      resizeHandler.removeHandler();
-    }
-    if (closeHandler != null) {
-      closeHandler.removeHandler();
-    }
-    Window.enableScrolling(true);
-    Gerrit.setHeaderVisible(true);
-    JumpKeys.enable(true);
-  }
-
-  CodeMirror getEditor() {
-    return cmEdit;
-  }
-
-  @UiHandler("editSettings")
-  void onEditSetting(@SuppressWarnings("unused") ClickEvent e) {
-    editPrefsAction.show();
-  }
-
-  @UiHandler("save")
-  void onSave(@SuppressWarnings("unused") ClickEvent e) {
-    save().run();
-  }
-
-  @UiHandler("close")
-  void onClose(@SuppressWarnings("unused") ClickEvent e) {
-    if (cmEdit.isClean(generation) || Window.confirm(EditConstants.I.cancelUnsavedChanges())) {
-      upToChange();
-    }
-  }
-
-  private void displayBase() {
-    cmBase.getWrapperElement().getParentElement().removeClassName(style.hideBase());
-    cmEdit.getWrapperElement().getParentElement().removeClassName(style.fullWidth());
-    mv.getGapElement().removeClassName(style.hideBase());
-    setCmBaseValue();
-    setLineLength(prefs.lineLength());
-    cmBase.refresh();
-  }
-
-  @UiHandler("showBase")
-  void onShowBase(ValueChangeEvent<Boolean> e) {
-    boolean shouldShow = e.getValue();
-    if (shouldShow) {
-      if (baseContent == null) {
-        ChangeEditApi.get(
-            projectKey,
-            revision,
-            path,
-            true /* base */,
-            new HttpCallback<NativeString>() {
-              @Override
-              public void onSuccess(HttpResponse<NativeString> fc) {
-                baseContent = fc;
-                displayBase();
-              }
-
-              @Override
-              public void onFailure(Throwable e) {}
-            });
-      } else {
-        displayBase();
-      }
-    } else {
-      cmBase.getWrapperElement().getParentElement().addClassName(style.hideBase());
-      cmEdit.getWrapperElement().getParentElement().addClassName(style.fullWidth());
-      mv.getGapElement().addClassName(style.hideBase());
-    }
-    mv.setShowDifferences(shouldShow);
-  }
-
-  void setOption(String option, String value) {
-    cmBase.setOption(option, value);
-    cmEdit.setOption(option, value);
-  }
-
-  void setOption(String option, boolean value) {
-    cmBase.setOption(option, value);
-    cmEdit.setOption(option, value);
-  }
-
-  void setOption(String option, double value) {
-    cmBase.setOption(option, value);
-    cmEdit.setOption(option, value);
-  }
-
-  void setTheme(Theme newTheme) {
-    cmBase.operation(() -> cmBase.setOption("theme", newTheme.name().toLowerCase()));
-    cmEdit.operation(() -> cmEdit.setOption("theme", newTheme.name().toLowerCase()));
-  }
-
-  void setLineLength(int length) {
-    int adjustedLength = Patch.COMMIT_MSG.equals(path) ? 72 : length;
-    cmBase.extras().lineLength(adjustedLength);
-    cmEdit.extras().lineLength(adjustedLength);
-  }
-
-  void setIndentUnit(int indent) {
-    cmEdit.setOption("indentUnit", Patch.COMMIT_MSG.equals(path) ? 2 : indent);
-  }
-
-  void setShowLineNumbers(boolean show) {
-    cmBase.setOption("lineNumbers", show);
-    cmEdit.setOption("lineNumbers", show);
-  }
-
-  void setShowWhitespaceErrors(boolean show) {
-    cmBase.operation(() -> cmBase.setOption("showTrailingSpace", show));
-    cmEdit.operation(() -> cmEdit.setOption("showTrailingSpace", show));
-  }
-
-  void setShowTabs(boolean show) {
-    cmBase.extras().showTabs(show);
-    cmEdit.extras().showTabs(show);
-  }
-
-  void adjustHeight() {
-    int height = header.getOffsetHeight();
-    int rest = Gerrit.getHeaderFooterHeight() + height + 5; // Estimate
-    mv.getGapElement().getStyle().setHeight(Window.getClientHeight() - rest, Unit.PX);
-    cmBase.adjustHeight(height);
-    cmEdit.adjustHeight(height);
-  }
-
-  void setSyntaxHighlighting(boolean b) {
-    ModeInfo modeInfo = ModeInfo.findMode(content.getContentType(), path);
-    final String mode = modeInfo != null ? modeInfo.mime() : null;
-    if (b && mode != null && !mode.isEmpty()) {
-      injectMode(
-          mode,
-          new AsyncCallback<Void>() {
-            @Override
-            public void onSuccess(Void result) {
-              cmBase.setOption("mode", mode);
-              cmEdit.setOption("mode", mode);
-            }
-
-            @Override
-            public void onFailure(Throwable caught) {
-              prefs.syntaxHighlighting(false);
-            }
-          });
-    } else {
-      cmBase.setOption("mode", (String) null);
-      cmEdit.setOption("mode", (String) null);
-    }
-  }
-
-  private void upToChange() {
-    Gerrit.display(PageLinks.toChangeInEditMode(projectKey, revision.getParentKey()));
-  }
-
-  private void initEditor() {
-    ModeInfo mode = null;
-    String editContent = "";
-    if (content != null && content.getResult() != null) {
-      editContent = content.getResult().asString();
-      if (prefs.syntaxHighlighting()) {
-        mode = ModeInfo.findMode(content.getContentType(), path);
-      }
-    }
-
-    Configuration cfg =
-        Configuration.create()
-            .set("autoCloseBrackets", prefs.autoCloseBrackets())
-            .set("cursorBlinkRate", prefs.cursorBlinkRate())
-            .set("cursorHeight", 0.85)
-            .set("indentUnit", prefs.indentUnit())
-            .set("keyMap", prefs.keyMapType().name().toLowerCase())
-            .set("lineNumbers", prefs.hideLineNumbers())
-            .set("lineWrapping", prefs.lineWrapping())
-            .set("indentWithTabs", prefs.indentWithTabs())
-            .set("matchBrackets", prefs.matchBrackets())
-            .set("mode", mode != null ? mode.mime() : null)
-            .set("origLeft", editContent)
-            .set("scrollbarStyle", "overlay")
-            .set("showTrailingSpace", prefs.showWhitespaceErrors())
-            .set("styleSelectedText", true)
-            .set("tabSize", prefs.tabSize())
-            .set("theme", prefs.theme().name().toLowerCase())
-            .set("value", "");
-
-    if (editContent.contains("\r\n")) {
-      cfg.set("lineSeparator", "\r\n");
-    }
-
-    mv = MergeView.create(editor, cfg);
-
-    cmBase = mv.leftOriginal();
-    cmBase.getWrapperElement().addClassName(style.base());
-    cmEdit = mv.editor();
-    setCmBaseValue();
-    cmEdit.setValue(editContent);
-
-    CodeMirror.addCommand(
-        "save",
-        new CommandRunner() {
-          @Override
-          public void run(CodeMirror instance) {
-            save().run();
-          }
-        });
-  }
-
-  private void renderLinks(EditFileInfo editInfo, JsArray<DiffWebLinkInfo> diffLinks) {
-    renderLinksToDiff();
-
-    if (editInfo != null) {
-      renderLinks(Natives.asList(editInfo.webLinks()));
-    } else if (diffLinks != null) {
-      renderLinks(Natives.asList(diffLinks));
-    }
-  }
-
-  private void renderLinks(List<DiffWebLinkInfo> links) {
-    if (links != null) {
-      for (DiffWebLinkInfo webLink : links) {
-        linkPanel.add(webLink.toAnchor());
-      }
-    }
-  }
-
-  private void renderLinksToDiff() {
-    InlineHyperlink sbs = new InlineHyperlink();
-    sbs.setHTML(new ImageResourceRenderer().render(Gerrit.RESOURCES.sideBySideDiff()));
-    sbs.setTargetHistoryToken(
-        Dispatcher.toPatch(projectKey, "sidebyside", null, new Patch.Key(revision, path)));
-    sbs.setTitle(PatchUtil.C.sideBySideDiff());
-    linkPanel.add(sbs);
-
-    InlineHyperlink unified = new InlineHyperlink();
-    unified.setHTML(new ImageResourceRenderer().render(Gerrit.RESOURCES.unifiedDiff()));
-    unified.setTargetHistoryToken(
-        Dispatcher.toPatch(projectKey, "unified", null, new Patch.Key(revision, path)));
-    unified.setTitle(PatchUtil.C.unifiedDiff());
-    linkPanel.add(unified);
-  }
-
-  private Runnable updateCursorPosition() {
-    return () -> {
-      // The rendering of active lines has to be deferred. Reflow
-      // caused by adding and removing styles chokes Firefox when arrow
-      // key (or j/k) is held down. Performance on Chrome is fine
-      // without the deferral.
-      //
-      Scheduler.get().scheduleDeferred(() -> cmEdit.operation(this::updateActiveLine));
-    };
-  }
-
-  private void updateActiveLine() {
-    Pos p = cmEdit.getCursor("end");
-    cursLine.setInnerText(Integer.toString(p.line() + 1));
-    cursCol.setInnerText(Integer.toString(p.ch() + 1));
-    cmEdit.extras().activeLine(cmEdit.getLineHandleVisualStart(p.line()));
-  }
-
-  private void setClean(boolean clean) {
-    save.setEnabled(!clean);
-    close.setEnabled(true);
-    dirty.getStyle().setVisibility(!clean ? VISIBLE : HIDDEN);
-  }
-
-  private Runnable save() {
-    return () -> {
-      if (!cmEdit.isClean(generation)) {
-        close.setEnabled(false);
-        String text = cmEdit.getValue();
-        if (Patch.COMMIT_MSG.equals(path)) {
-          String trimmed = text.trim() + "\r";
-          if (!trimmed.equals(text)) {
-            text = trimmed;
-            cmEdit.setValue(text);
-          }
-        }
-        final int g = cmEdit.changeGeneration(false);
-        ChangeEditApi.put(
-            Project.NameKey.asStringOrNull(projectKey),
-            revision.getParentKey().get(),
-            path,
-            text,
-            new GerritCallback<VoidResult>() {
-              @Override
-              public void onSuccess(VoidResult result) {
-                generation = g;
-                setClean(cmEdit.isClean(g));
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {
-                close.setEnabled(true);
-              }
-            });
-      }
-    };
-  }
-
-  private void injectMode(String type, AsyncCallback<Void> cb) {
-    new ModeInjector().add(type).inject(cb);
-  }
-
-  private void setCmBaseValue() {
-    cmBase.setValue(
-        baseContent != null && baseContent.getResult() != null
-            ? baseContent.getResult().asString()
-            : "");
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.ui.xml
deleted file mode 100644
index 34282c8..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.ui.xml
+++ /dev/null
@@ -1,185 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-  <ui:with field='ico' type='com.google.gerrit.client.GerritResources'/>
-  <ui:style gss='false' type='com.google.gerrit.client.editor.EditScreen.Style'>
-    @external .CodeMirror, .CodeMirror-cursor;
-    @external .CodeMirror-merge-2pane, .CodeMirror-merge-pane;
-    @external .CodeMirror-merge-gap;
-    @external .CodeMirror-scroll, .CodeMirror-overlayscroll-vertical;
-
-    .header {
-      position: relative;
-      height: 16px;
-      line-height: 16px;
-    }
-
-    .header .CodeMirror div.CodeMirror-cursor {
-      border-left: 2px solid black;
-    }
-
-    .headerLine {
-      background-color: #f7f7f7;
-      border-bottom: 1px solid #ddd;
-      padding-left: 30px;
-    }
-
-    .headerButtons {
-      display: inline-block;
-      padding-right: 5px;
-      border-right: 1px inset #ddd;
-      margin-right: 5px;
-    }
-
-    .headerButtons button:disabled {
-      background-color: #ddd;
-      font-weight: normal;
-      cursor: default;
-    }
-
-    .headerButtons button {
-      margin: 2px 0 2px 0;
-      text-align: center;
-      font-size: 8pt;
-      cursor: pointer;
-      border: 1px solid;
-      color: rgba(0, 0, 0, 0.15);
-      background-color: #f5f5f5;
-      -webkit-border-radius: 1px;
-      -webkit-box-sizing: content-box;
-    }
-
-    .headerButtons button div {
-      color: #444;
-      min-width: 54px;
-      white-space: nowrap;
-      line-height: 8pt;
-    }
-
-    .save {
-      font-weight: bold;
-    }
-
-    .path {
-      white-space: nowrap;
-    }
-
-    .statusLine {
-      position: fixed;
-      bottom: 0;
-      left: 0;
-      width: 175px;
-      height: 19px;
-      background-color: #f7f7f7;
-      border-top: 1px solid #ddd;
-      border-right: 1px solid #ddd;
-    }
-    .statusLine div {
-      height: inherit;
-    }
-
-    .cursorPosition {
-      display: inline-block;
-      margin: 0 5px 0 35px;
-      white-space: nowrap;
-    }
-
-    .dirty {
-      display: inline-block;
-      margin: 0 5px 0 5px;
-      padding: 0 0 0 5px;
-      border-left: 1px solid #ddd;
-      font-weight: bold;
-    }
-
-    .navigation {
-      position: absolute;
-      top: 0;
-      right: 10px;
-    }
-    .linkPanel {
-      float: left;
-    }
-    .linkPanel img {
-      padding-top: 2px;
-      padding-right: 3px;
-    }
-
-    .preferences {
-      position: relative;
-      top: 2px;
-      cursor: pointer;
-      outline: none;
-    }
-
-    .hideBase.CodeMirror-merge-pane {
-      display: none;
-    }
-
-    .hideBase.CodeMirror-merge-gap {
-      display: none;
-    }
-
-    .CodeMirror-merge-2pane .fullWidth.CodeMirror-merge-pane {
-      width: 100%;
-    }
-
-    /* Hide the vertical scrollbar on the base side. The edit side controls
-       both views */
-    .base .CodeMirror-scroll { margin-right: -42px; }
-    .base .CodeMirror-overlayscroll-vertical { display: none !important; }
-  </ui:style>
-  <g:HTMLPanel styleName='{style.header}'>
-    <div class='{style.headerLine}' ui:field='header'>
-       <div class='{style.headerButtons}'>
-         <g:Button ui:field='close'
-             title='Close file and return to change'>
-           <ui:attribute name='title'/>
-           <div><ui:msg>Close</ui:msg></div>
-         </g:Button>
-         <g:Button ui:field='save'
-             styleName='{style.save}'
-             title='Save'>
-           <ui:attribute name='title'/>
-           <div><ui:msg>Save</ui:msg></div>
-         </g:Button>
-       </div>
-       <span class='{style.path}'><span ui:field='project'/> / <span ui:field='filePath'/></span>
-       <div class='{style.navigation}'>
-         <g:Label text='Show Base' styleName='{style.linkPanel}'></g:Label>
-         <g:CheckBox ui:field='showBase' checked='true' styleName='{style.linkPanel}'
-             title='Show Base Version'>
-           <ui:attribute name='title'/>
-         </g:CheckBox>
-         <g:FlowPanel ui:field='linkPanel' styleName='{style.linkPanel}'/>
-         <g:Image
-             ui:field='editSettings'
-             styleName='{style.preferences}'
-             resource='{ico.gear}'
-             title='Edit screen preferences'>
-            <ui:attribute name='title'/>
-         </g:Image>
-       </div>
-    </div>
-    <div ui:field='editor' />
-    <div class='{style.statusLine}'>
-      <div class='{style.cursorPosition}'><span ui:field='cursLine'/> : <span ui:field='cursCol'/></div>
-      <div class='{style.dirty}' ui:field='dirty'>Unsaved</div>
-    </div>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
deleted file mode 100644
index 4076296..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
+++ /dev/null
@@ -1,1060 +0,0 @@
-/* Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Make every single class external so users can rely on their names
- */
-@external .*;
-
-@def black #000000;
-@def white #ffffff;
-@def norm-font  sans-serif;
-@def mono-font  monospace;
-
-@eval backgroundColor com.google.gerrit.client.Gerrit.getTheme().backgroundColor;
-@eval topMenuColor com.google.gerrit.client.Gerrit.getTheme().topMenuColor;
-@eval textColor com.google.gerrit.client.Gerrit.getTheme().textColor;
-@eval trimColor com.google.gerrit.client.Gerrit.getTheme().trimColor;
-@eval selectionColor com.google.gerrit.client.Gerrit.getTheme().selectionColor;
-@eval changeTableOutdatedColor com.google.gerrit.client.Gerrit.getTheme().changeTableOutdatedColor;
-@eval tableOddRowColor com.google.gerrit.client.Gerrit.getTheme().tableOddRowColor;
-@eval tableEvenRowColor com.google.gerrit.client.Gerrit.getTheme().tableEvenRowColor;
-
-@sprite .greenCheckClass {
-  gwt-image: "greenCheck";
-}
-
-/** Override various GWT defaults */
-.gerritTopMenu {
-  font-size: 9pt;
-  padding-left: 5px;
-  padding-right: 5px;
-  background: transparent;
-}
-
-body, table td, select {
-  font-family: norm-font;
-}
-
-button {
-  padding: 1px 6px;
-}
-
-.gerritBody {
-  font-size: small;
-  padding-left: 5px;
-  padding-right: 5px;
-}
-
-a,
-a:visited {
-  color: #0654ac;
-  text-decoration: none;
-}
-
-a:hover {
-  color: #0654ac;
-  text-decoration: underline;
-}
-
-#gerrit_btmmenu {
-  clear: both;
-  color: #a0adcc;
-  text-align: right;
-  padding-right: 10px;
-}
-
-.version a,
-.version a:visited,
-.version a:hover {
-  color: #2a5db0;
-}
-
-
-/** Widgets **/
-.gwt-Button {
-  color: black;
-}
-
-.accountLinkPanel {
-  display: inline;
-}
-
-.accountLinkPanel img {
-  margin-right: 0.2em;
-  position: relative;
-  top: 2px;
-  height: 16px !important;
-  width: 16px;
-}
-
-.accountLinkPanel a {
-  position: relative;
-  top: -1px;
-}
-
-.inputFieldTypeHint {
-  color: grey;
-}
-
-.smallHeading {
-  margin-top: 5px;
-  font-weight: bold;
-}
-
-.link {
-  cursor: pointer;
-}
-
-.extensionPanel {
-  padding-top: 10px;
-}
-
-/** MenuScreen **/
-.menuScreenMenuBar {
-  background: topMenuColor;
-  padding-top: 0.5em;
-  padding-bottom: 10em;
-  padding-left: 0.5em;
-  padding-right: 0.5em;
-  border-right: 1px solid black;
-  margin-right: 0.5em;
-}
-
-.menuScreenMenuBar .menuItem {
-  white-space: nowrap;
-  display: block;
-  border-right: none;
-  padding: 0.2em;
-}
-
-.menuScreenMenuBar .menuItem.activeRow {
-  background: selectionColor;
-}
-
-.menuItem.activeRow {
-  background: selectionColor;
-}
-
-/** Menu **/
-.linkMenuBar {
-  font-size: 9pt;
-  display: inline;
-  white-space: nowrap;
-  padding-left: 6px;
-}
-.menuItem {
-  padding-left: 5px;
-  padding-right: 5px;
-}
-.linkMenuItemNotLast {
-  border-right: 1px solid black;
-}
-
-.topmenu {
-  width: 100%;
-}
-.topmenuTDmenu {
-  vertical-align: top;
-}
-.topmenuTDglue {
-  width: 100%;
-}
-
-.topmenuMenuLeft {
-  width: 300px;
-  font-size: 9pt;
-  padding-top: 5px;
-  padding-left: 5px;
-  padding-right: 5px;
-  background: none;
-  position: relative;
-  top: 0;
-}
-.topmenuMenuLeft tbody tr td table {
-  border: 0;
-}
-.topmenuMenuLeft tbody tr td table.gwt-TabBar {
-  border-bottom: 1px solid #DDD;
-}
-.topmenuMenuLeft .gwt-TextBox {
-  width: 250px;
-}
-.topmenuMenuLeft .gwt-Button {
-  padding: 3px 6px;
-}
-.topmenuMenuLeft .gwt-TabBarFirst {
-  display: none;
-}
-.topmenuMenuLeft .gwt-TabBarItem {
-  margin: 0px;
-  background: transparent;
-  padding-top: 0px;
-  padding-bottom: 1px;
-  padding-left: 1em;
-  padding-right: 1em;
-}
-.topmenuMenuLeft .gwt-TabBarRest {
-  background: transparent;
-  padding-top: 0px;
-}
-.topmenuMenuLeft .gwt-TabPanelBottom {
-  background: transparent;
-  border-top: none;
-  border-left: none;
-  border-right: none;
-  border-bottom: none;
-  padding: 1px;
-}
-.topmenuMenuLeft .menuItem {
-  padding-left: 1em;
-  padding-right: 1em;
-  border-right: none;
-}
-
-.topmenuMenuRight {
-  float: right;
-  text-align: right;
-}
-.menuBarUserName {
-  padding-left: 5px;
-  padding-right: 5px;
-  white-space: nowrap;
-}
-.menuBarUserNameAvatar {
-  vertical-align: middle;
-}
-.menuBarUserNameFocusPanel {
-  display: inline;
-}
-.menuBarUserNamePanel {
-  display: inline;
-  cursor: pointer;
-  font-weight: bold;
-}
-.userInfoPopup {
-  border: 1px solid black;
-  background: white;
-  box-shadow: 3px 3px 5px #888;
-  z-index: 200;
-}
-.searchPanel {
-  white-space: nowrap;
-  display: inline;
-}
-.searchPanel .searchTextBox {
-  font-size: 9pt;
-  margin: 8.286px 3px 0 0;
-}
-.searchPanel .searchDropdown {
-  font-size: 8pt;
-  border: 2px solid;
-  border-color: rgba(0, 0, 0, 0.15);
-  height: 16px;
-  border-radius: 2px;
-  box-sizing: content-box;
-}
-.searchPanel .searchButton {
-  text-align: center;
-  font-size: 8pt;
-  font-weight: bold;
-  cursor: pointer;
-  border: 2px solid;
-  color: #FFF;
-  border-color: rgba(0, 0, 0, 0.15);
-  height: 14px;
-  background-color: #53A93F;
-  border-radius: 2px;
-  box-sizing: content-box;
-}
-.suggestBoxPopup {
-  z-index: 200;
-}
-
-/** RPC Status **/
-.rpcStatus {
-  position: fixed;
-  top: 6px;
-  left: 50%;
-  padding-top: 4px;
-  padding-bottom: 4px;
-  padding-left: 10px;
-  padding-right: 10px;
-  text-align: center;
-  font-weight: bold;
-  background: #FFF1A8;
-  z-index: 200;
-}
-
-
-/** Error Dialog **/
-.errorDialog {
-  background: none;
-  border: none;
-  padding: 10px;
-  width: 600px;
-  color: backgroundColor;
-  font-size: 15px;
-  font-family: verdana;
-  z-index: 200;
-}
-.errorDialogGlass {
-  opacity: 0.75;
-  z-index: 200;
-}
-@if user.agent safari {
-  .errorDialogGlass {
-    opacity: 0.80;
-  }
-}
-@if user.agent ie8 {
-  /* IE just doesn't do opacity the way we want, make our dialog
-   * stand out in a way that it can't be missed against the page
-   */
-  .errorDialog {
-    color: black;
-    background: darkgray;
-    border: 10px groove lightgrey;
-  }
-}
-.errorDialogTitle {
-  font-size: 30px;
-  font-weight: bold;
-  margin-bottom: 15px;
-}
-.errorDialogErrorType {
-  font-weight: bold;
-  white-space: nowrap;
-  margin-bottom: 15px;
-}
-.errorDialogButtons {
-  width: 100%;
-  margin-top: 15px;
-}
-.errorDialog a,
-.errorDialog a:visited,
-.errorDialog a:hover {
-  color: white;
-  font-weight: bold;
-  font-size: 15px;
-  font-family: verdana;
-}
-.loadingPluginsDialog {
-  background: #fff;
-  color: #000;
-  width: auto;
-}
-
-
-/** Screen **/
-.screen {
-}
-
-.screenHeader {
-  white-space: nowrap;
-  font-size: 16pt;
-  margin: 3px 0 8px;
-  text-overflow: ellipsis;
-  overflow: hidden;
-}
-
-/** ChangeTable **/
-.changeTable {
-  border-collapse: separate;
-  border-spacing: 0;
-}
-
-.changeTable tr:nth-child\(even\) {
-  background: tableEvenRowColor;
-}
-
-.changeTable tr:nth-child\(odd\) {
-  background: tableOddRowColor;
-}
-
-.changeTable .iconCell {
-  width: 1px;
-  padding: 0px;
-  vertical-align: middle;
-  border-bottom: 1px solid trimColor;
-}
-
-.changeTable .leftMostCell {
-  border-left: 1px solid trimColor;
-}
-
-.changeTable .dataCell {
-  padding-left: 5px;
-  padding-right: 5px;
-  border-right: 1px solid trimColor;
-  border-bottom: 1px solid trimColor;
-  vertical-align: middle;
-  height: 20px;
-}
-
-.changeTable .dataCellHidden {
-  display: none;
-}
-
-.changeTable a.gwt-InlineHyperlink,
-.changeTable a.gwt-Anchor {
-  color: #222 !important;
-}
-
-.changeTable .changeSize {
-  height: 10px;
-  display: inline-block;
-  opacity: 0.6;
-}
-
-.accountDashboard.changeTable tr {
-  color: #444444;
-}
-.accountDashboard.changeTable tr a {
-  color: #444444;
-  text-decoration: none;
-}
-.accountDashboard.changeTable .needsReview,
-.accountDashboard.changeTable .needsReview a {
-  font-weight: bold;
-  color: textColor;
-}
-
-.changeTable .activeRow,
-.accountDashboard.changeTable .activeRow,
-.accountDashboard.changeTable .activeRow a {
-  background: selectionColor !important;
-}
-
-.changeTable .cSIZE {
-  width: 70px;
-  text-align: right;
-}
-
-.changeTable .cSUBJECT div {
-  text-overflow: ellipsis;
-  overflow: hidden;
-  white-space: nowrap;
-}
-
-.changeTable .cASSIGNEDTOME {
-  background: #ffe9d6 !important;
-}
-
-.changeTable .cASSIGNEE,
-.changeTable .cOWNER,
-.changeTable .cSTATUS {
-  white-space: nowrap;
-}
-
-.changeTable .cLastUpdate {
-  white-space: nowrap;
-  text-align: right;
-  width: 1em;
-}
-
-.changeTable .groupName {
-  white-space: nowrap;
-}
-
-.changeTable .cAPPROVAL {
-  width: 0.5em;
-  text-align: center;
-}
-.changeTable .dataCell.negscore {
-  color: red;
-}
-.changeTable .dataCell.posscore {
-  color: #08a400;
-}
-.changeTable .dataCell.singleLine {
-  white-space: nowrap;
-}
-.changeTable .dataCell.labelNotApplicable {
- background: #F5F5F5;
-}
-.changeTable .iconHeader {
-  border-top: 1px solid backgroundColor;
-  border-bottom: 1px solid backgroundColor;
-  background-color: trimColor;
-}
-
-.changeTable .dataHeader {
-  border: 1px solid backgroundColor;
-  padding: 2px 6px 1px;
-  background-color: trimColor;
-  font-style: italic;
-  white-space: nowrap;
-  color: textColor;
-}
-
-.changeTable .dataHeaderHidden {
-  display: none;
-}
-
-.changeTable .sectionHeader {
-  border-top: 8px solid backgroundColor;
-  padding: 2px 6px 1px;
-  background-color: trimColor;
-  white-space: nowrap;
-  font-weight: bold;
-  color: textColor;
-}
-
-.changeTable .emptySection {
-  border-left: 1px solid trimColor;
-  border-right: 1px solid trimColor;
-  border-bottom: 1px solid trimColor;
-  font-style: italic;
-  padding-left: 25px;
-}
-
-.changeTablePrevNextLinks {
-  float: right;
-  padding-right: 5px;
-}
-.changeTablePrevNextLinks td {
-  width: 5em;
-  text-align: right;
-}
-.changeTablePrevNextLinks .gwt-Hyperlink {
-  font-size: 9pt;
-  color: #2a5db0;
-}
-
-/** Change **/
-.avatarInfoPanel {
-  margin-right: 10px;
-}
-.avatarInfoPanel td {
-  text-align: center;
-}
-
-.infoBlock {
-  border-collapse: collapse;
-  border-spacing: 0;
-}
-
-.infoBlock td {
-  padding: 2px 4px 2px 6px;
-  border-right: 1px solid trimColor;
-  border-bottom: 1px solid trimColor;
-  text-align: left;
-  white-space: nowrap;
-}
-
-.infoBlock td td {
-  padding-left: 0px;
-  border-right: 0px;
-}
-
-.infoBlock td.topmost {
-  border-top: 1px solid trimColor;
-}
-
-.infoBlock td.header {
-  background-color: trimColor;
-  font-style: italic;
-  text-align: right;
-}
-
-.infoBlock td.bottomheader {
-  border-bottom: 1px solid trimColor;
-}
-
-
-.patchSetActions {
-  margin-bottom: 10px;
-}
-.patchSetActions .gwt-Button {
-  margin-right: 30px;
-  font-size: 8pt;
-}
-
-.downloadBox {
-  min-width: 580px;
-  margin: 5px;
-  margin-right: 15px;
-}
-.downloadBoxTable {
-  border-spacing: 0;
-  width: 100%;
-}
-.downloadBoxTableCommandColumn {
-  text-align: left;
-  font-weight: normal;
-  white-space: nowrap;
-  max-height: 18px;
-  width: 80px;
-  padding-right: 5px;
-}
-.downloadBoxSpacer {
-  margin-left: 5px;
-  margin-right: 5px;
-}
-.downloadBoxScheme {
-  float: right;
-}
-.downloadBoxCopyLabel {
-  font-size: smaller;
-  font-family: monospace;
-}
-.downloadBoxCopyLabel span {
-  width: 500px;
-  white-space: nowrap;
-  display: inline-block;
-  overflow: hidden;
-  text-overflow: ellipsis;
-}
-.downloadBoxCopyLabel .gwt-TextBox {
-  padding: 0;
-  margin: 0;
-  border: 0;
-  max-height: 18px;
-  width: 500px;
-}
-.downloadBoxCopyLabel div {
-  float: right;
-}
-.downloadLinkHeader {
-  background: trimColor;
-  white-space: nowrap;
-  border-bottom: 1px solid black;
-}
-.downloadLinkHeaderGap {
-  margin-left: 5em;
-}
-.downloadLinkList {
-  display: inline;
-  white-space: nowrap;
-}
-.downloadLink {
-  color: black;
-  text-decoration: none;
-  white-space: nowrap;
-  background: trimColor;
-  border-right: 1px solid black;
-  padding-left: 0.5em;
-  padding-right: 0.5em;
-}
-a:hover.downloadLink {
-  color: black;
-}
-.downloadLink_Active {
-  background: selectionColor;
-}
-.downloadLinkCopyLabel {
-  white-space: pre;
-  font-family: mono-font;
-  font-size: 12px;
-  margin-left: 0.5em;
-  margin-right: 0.5em;
-}
-.downloadLinkCopyLabel .gwt-TextBox {
-  width: 40em;
-}
-.downloadLinkCopyLabel span {
-  width: 40em;
-  white-space: nowrap;
-  display: inline-block;
-  overflow: hidden;
-  text-overflow: ellipsis;
-}
-
-/** AccountSettings  **/
-.usernameField {
-  white-space: nowrap;
-}
-.accountUsername {
-  font-family: mono-font;
-  font-size: small;
-}
-.accountPassword {
-  font-family: mono-font;
-  font-size: small;
-}
-.sshKeyPanelEncodedKey {
-  white-space: nowrap;
-  text-overflow: ellipsis;
-  overflow: hidden;
-  font-family: mono-font;
-  font-size: small;
-}
-.sshKeyPanelInvalid {
-  white-space: nowrap;
-  color: red;
-  font-weight: bold;
-}
-.identityUntrustedExternalId {
-  white-space: nowrap;
-  color: red;
-  font-weight: bold;
-}
-
-.accountInfoBlock {
-  margin-bottom: 10px;
-}
-.accountInfoBlock .gwt-Button {
-  margin-left: 10px;
-}
-
-.addWatchPanel {
-  margin-top: 10px;
-  padding: 5px 5px 5px 5px;
-}
-.watchedProjectFilter {
-  margin-left: 1em;
-  color: grey;
-}
-
-.addBranch {
-  margin-top: 10px;
-  background-color: trimColor;
-  padding: 5px 5px 5px 5px;
-}
-
-.addSshKeyPanel {
-  margin-top: 10px;
-  background-color: trimColor;
-  padding: 5px 5px 5px 5px;
-}
-
-.addSshKeyPanel ol {
-  margin-top: 0px;
-  margin-bottom: 5px;
-}
-
-.addSshKeyPanel td {
-  width: 100%;
-}
-
-.sshKeyTable td.dataCell, .sshKeyTable td.iconCell {
-  vertical-align: top;
-}
-
-.createProjectPanel {
-  margin-bottom: 10px;
-  background-color: trimColor;
-  padding: 5px 5px 5px 5px;
-}
-
-.sshHostKeyPanel {
-  margin-top: 10px;
-  border: 1px solid trimColor;
-  padding: 5px 5px 5px 5px;
-}
-.sshHostKeyPanelHeading {
-  white-space: nowrap;
-  margin-top: 5px;
-  margin-left: 1em;
-}
-.sshHostKeyPanelFingerprintData {
-  margin-left: 2em;
-  white-space: nowrap;
-  font-family: mono-font;
-  font-size: small;
-}
-.sshHostKeyPanelKnownHostEntry {
-  margin-left: 2em;
-  white-space: nowrap;
-  font-family: mono-font;
-  font-size: small;
-  width: 80em;
-}
-
-.contributorAgreementButton {
-  font-weight: bold;
-}
-
-.contributorAgreementShortDescription {
-  margin-left: 20px;
-  margin-right: 20px;
-  margin-bottom: 10px;
-  padding: 5px 5px 5px 5px;
-  border: 1px solid #b0bdcc;
-}
-
-.contributorAgreementAlreadySubmitted {
-  margin-left: 20px;
-  margin-right: 20px;
-  padding: 5px 5px 5px 5px;
-  color: red;
-}
-
-.contributorAgreementLegal {
-  margin-left: 20px;
-  margin-right: 20px;
-  padding: 5px 5px 5px 5px;
-  border: 1px solid #b0bdcc;
-}
-
-.registerScreenSection {
-  margin-top: 2em;
-}
-.registerScreenExplain {
-  margin-left: 10px;
-  margin-top: 5px;
-  margin-bottom: 5px;
-  width: 45em;
-}
-.registerScreenNextLinks {
-  margin-top: 2em;
-}
-.registerScreenNextLinks .gwt-InlineHyperlink {
-  margin-left: 2em;
-  white-space: nowrap;
-}
-.registerScreenSection .changeTable {
-  width: 45em;
-}
-.registerScreenSection .addSshKeyPanel {
-  background: none;
-}
-.registerScreenSection .sshHostKeyPanel {
-  border: none;
-}
-.registerScreenSection .sshHostKeyPanel .sshHostKeyPanelKnownHostEntry {
-  width: 45em;
-}
-
-.projectActions {
-  margin-bottom: 10px;
-}
-
-.oauthInfoBlock {
-  margin-bottom: 10px;
-}
-.oauthToken {
-  font-family: monospace;
-  font-size: small;
-  width: 40em;
-}
-.oauthToken span {
-  white-space: nowrap;
-  display: inline-block;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  width: 38em;
-}
-.oauthExpires {
-  font-family: monospace;
-  font-size: small;
-  width: 40em;
-}
-.oauthPanel {
-  margin-top: 10px;
-  border: 1px solid trimColor;
-  padding: 5px 5px 5px 5px;
-}
-.oauthPanelNetRCHeading {
-  margin-top: 5px;
-  margin-left: 1em;
-  white-space: nowrap;
-}
-.oauthPanelNetRCEntry {
-  margin-top: 5px;
-  margin-left: 2em;
-  font-family: monospace;
-  font-size: small;
-  width: 80em;
-}
-.oauthPanelNetRCEntry span {
-  white-space: nowrap;
-  display: inline-block;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  width: 78em;
-}
-.oauthPanelCookieHeading {
-  margin-top: 15px;
-  margin-left: 1em;
-  white-space: nowrap;
-}
-.oauthPanelCookieEntry {
-  margin-top: 5px;
-  margin-left: 2em;
-  font-family: monospace;
-  font-size: small;
-  width: 80em;
-}
-.oauthPanelCookieEntry span {
-  white-space: nowrap;
-  display: inline-block;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  width: 78em;
-}
-
-
-/** CommentedActionDialog **/
-.commentedActionDialog .gwt-DisclosurePanel .header td {
-  font-weight: bold;
-  white-space: nowrap;
-}
-.commentedActionDialog .smallHeading {
-  font-size: small;
-  font-weight: bold;
-  white-space: nowrap;
-}
-.commentedActionDialog .commentedActionMessage {
-  margin-left: 10px;
-  background: trimColor;
-  padding: 5px 5px 5px 5px;
-}
-.commentedActionDialog .commentedActionMessage textarea {
-  font-size: small;
-}
-.commentedActionDialog .gwt-Hyperlink {
-  white-space: nowrap;
-  font-size: small;
-}
-.commentedActionDialog .rebaseContentPanel {
-  margin-left: 10px;
-  background: trimColor;
-  padding: 5px 5px 5px 5px;
-  width: 300px;
-}
-.commentedActionDialog .rebaseContentPanel .rebaseSuggestBox {
-  font-size: small;
-  width: 100%;
-}
-
-/** AccountGroupInfoScreen **/
-.groupUUIDPanel {
-  margin-bottom: 10px;
-}
-.groupDescriptionPanel {
-  margin-bottom: 3px;
-}
-.groupNamePanel {
-  margin-bottom: 3px;
-}
-.groupNameTextBox {
-  margin-bottom: 2px;
-}
-.groupOptionsPanel {
-  margin-bottom: 5px;
-}
-.groupOwnerPanel {
-  margin-bottom: 3px;
-}
-.groupOwnerTextBox {
-  margin-bottom: 2px;
-}
-
-
-/** AccountGroupMembersScreen **/
-.groupMembersTable {
-  margin-bottom: 2px;
-}
-.groupIncludesTable {
-  margin-bottom: 2px;
-}
-
-
-/** AddMemberBox **/
-.addMemberTextBox {
-  margin-right: 2px;
-  margin-bottom: 2px;
-}
-
-
-/** ProjectBranchesScreen **/
-.specialBranchIconCell {
-  background: #ECECEC;
-  border-bottom: 1px solid #FFFFFF;
-  border-top: 1px solid #FFFFFF;
-}
-.specialBranchDataCell {
-  background: #ECECEC;
-  border: 1px solid white;
-  font-style: italic;
-  padding: 2px 6px 1px;
-}
-
-.editHeadButton {
-  float: right;
-  cursor: pointer;
-}
-
-.branchTableDeleteButton {
-  margin-top: 5px;
-}
-
-.branchTablePrevNextLinks {
-  position: relative;
-}
-.branchTablePrevNextLinks td {
-  float: left;
-  width: 5em;
-  text-align: left;
-  padding-right: 10px;
-}
-.branchTablePrevNextLinks .gwt-Hyperlink {
-  font-size: 9pt;
-  color: #2a5db0;
-}
-
-/** PluginListScreen **/
-.pluginsTable {
-}
-
-/** ProjectListScreen **/
-.projectFilterPanel {
-  margin-bottom: 10px;
-}
-.projectFilterPanel input {
-  width: 200px;
-}
-.projectFilterLabel {
-  margin-right: 5px;
-}
-.projectNameColumn {
-  min-width: 300px;
-}
-
-.queryIcon {
-  position: relative;
-  top: 2px;
-  margin-right: 3px;
-}
-
-/** ProjectSettings */
-.maxObjectSizeLimitEffectiveLabel {
-  padding-top: 5px;
-  padding-left: 5px;
-}
-
-.pluginProjectConfigInheritedValue {
-  padding-top: 5px;
-  padding-left: 5px;
-}
-
-/* StringListPanel */
-.stringListPanelButtons {
-  margin-left: 0.5em;
-}
-.stringListPanelButtons .gwt-Button {
-  margin-right: 2em;
-  font-size: 7pt;
-  padding: 1px;
-}
-
-/* List Screens */
-.pagingLink {
-  font-size: 18px;
-  margin-top: 5px;
-  margin-bottom: 15px;
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/groups/GroupApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/groups/GroupApi.java
deleted file mode 100644
index 01c4d26..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/groups/GroupApi.java
+++ /dev/null
@@ -1,270 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.groups;
-
-import com.google.gerrit.client.VoidResult;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.info.GroupInfo;
-import com.google.gerrit.client.rpc.NativeString;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import java.util.Set;
-
-/** A collection of static methods which work on the Gerrit REST API for specific groups. */
-public class GroupApi {
-  /** Create a new group */
-  public static void createGroup(String groupName, AsyncCallback<GroupInfo> cb) {
-    JavaScriptObject in = JavaScriptObject.createObject();
-    new RestApi("/groups/").id(groupName).ifNoneMatch().put(in, cb);
-  }
-
-  public static void getGroupDetail(String group, AsyncCallback<GroupInfo> cb) {
-    group(group).view("detail").get(cb);
-  }
-
-  /** Get the name of a group */
-  public static void getGroupName(AccountGroup.UUID group, AsyncCallback<NativeString> cb) {
-    group(group).view("name").get(cb);
-  }
-
-  /** Check if the current user is owner of a group */
-  public static void isGroupOwner(String groupName, AsyncCallback<Boolean> cb) {
-    GroupMap.myOwned(
-        groupName,
-        new AsyncCallback<GroupMap>() {
-          @Override
-          public void onSuccess(GroupMap result) {
-            cb.onSuccess(!result.isEmpty());
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            cb.onFailure(caught);
-          }
-        });
-  }
-
-  /** Rename a group */
-  public static void renameGroup(
-      AccountGroup.UUID group, String newName, AsyncCallback<VoidResult> cb) {
-    GroupInput in = GroupInput.create();
-    in.name(newName);
-    group(group).view("name").put(in, cb);
-  }
-
-  /** Set description for a group */
-  public static void setGroupDescription(
-      AccountGroup.UUID group, String description, AsyncCallback<VoidResult> cb) {
-    RestApi call = group(group).view("description");
-    if (description != null && !description.isEmpty()) {
-      GroupInput in = GroupInput.create();
-      in.description(description);
-      call.put(in, cb);
-    } else {
-      call.delete(cb);
-    }
-  }
-
-  /** Set owner for a group */
-  public static void setGroupOwner(
-      AccountGroup.UUID group, String owner, AsyncCallback<GroupInfo> cb) {
-    GroupInput in = GroupInput.create();
-    in.owner(owner);
-    group(group).view("owner").put(in, cb);
-  }
-
-  /** Set the options for a group */
-  public static void setGroupOptions(
-      AccountGroup.UUID group, boolean isVisibleToAll, AsyncCallback<VoidResult> cb) {
-    GroupOptionsInput in = GroupOptionsInput.create();
-    in.visibleToAll(isVisibleToAll);
-    group(group).view("options").put(in, cb);
-  }
-
-  /** Add member to a group. */
-  public static void addMember(
-      AccountGroup.UUID group, String member, AsyncCallback<AccountInfo> cb) {
-    members(group).id(member).put(cb);
-  }
-
-  /** Add members to a group. */
-  public static void addMembers(
-      AccountGroup.UUID group, Set<String> members, AsyncCallback<JsArray<AccountInfo>> cb) {
-    if (members.size() == 1) {
-      addMember(
-          group,
-          members.iterator().next(),
-          new AsyncCallback<AccountInfo>() {
-            @Override
-            public void onSuccess(AccountInfo result) {
-              cb.onSuccess(Natives.arrayOf(result));
-            }
-
-            @Override
-            public void onFailure(Throwable caught) {
-              cb.onFailure(caught);
-            }
-          });
-    } else {
-      MemberInput input = MemberInput.create();
-      for (String member : members) {
-        input.addMember(member);
-      }
-      members(group).post(input, cb);
-    }
-  }
-
-  /** Remove members from a group. */
-  public static void removeMembers(
-      AccountGroup.UUID group, Set<Integer> ids, AsyncCallback<VoidResult> cb) {
-    if (ids.size() == 1) {
-      members(group).id(ids.iterator().next().toString()).delete(cb);
-    } else {
-      MemberInput in = MemberInput.create();
-      for (Integer id : ids) {
-        in.addMember(id.toString());
-      }
-      group(group).view("members.delete").post(in, cb);
-    }
-  }
-
-  /** Include a group into a group. */
-  public static void addIncludedGroup(
-      AccountGroup.UUID group, String include, AsyncCallback<GroupInfo> cb) {
-    groups(group).id(include).put(cb);
-  }
-
-  /** Include groups into a group. */
-  public static void addIncludedGroups(
-      AccountGroup.UUID group,
-      Set<String> includedGroups,
-      final AsyncCallback<JsArray<GroupInfo>> cb) {
-    if (includedGroups.size() == 1) {
-      addIncludedGroup(
-          group,
-          includedGroups.iterator().next(),
-          new AsyncCallback<GroupInfo>() {
-            @Override
-            public void onSuccess(GroupInfo result) {
-              cb.onSuccess(Natives.arrayOf(result));
-            }
-
-            @Override
-            public void onFailure(Throwable caught) {
-              cb.onFailure(caught);
-            }
-          });
-    } else {
-      IncludedGroupInput input = IncludedGroupInput.create();
-      for (String includedGroup : includedGroups) {
-        input.addGroup(includedGroup);
-      }
-      groups(group).post(input, cb);
-    }
-  }
-
-  /** Remove included groups from a group. */
-  public static void removeIncludedGroups(
-      AccountGroup.UUID group, Set<AccountGroup.UUID> ids, AsyncCallback<VoidResult> cb) {
-    if (ids.size() == 1) {
-      AccountGroup.UUID g = ids.iterator().next();
-      groups(group).id(g.get()).delete(cb);
-    } else {
-      IncludedGroupInput in = IncludedGroupInput.create();
-      for (AccountGroup.UUID g : ids) {
-        in.addGroup(g.get());
-      }
-      group(group).view("groups.delete").post(in, cb);
-    }
-  }
-
-  /** Get audit log of a group. */
-  public static void getAuditLog(
-      AccountGroup.UUID group, AsyncCallback<JsArray<GroupAuditEventInfo>> cb) {
-    group(group).view("log.audit").get(cb);
-  }
-
-  private static RestApi members(AccountGroup.UUID group) {
-    return group(group).view("members");
-  }
-
-  private static RestApi groups(AccountGroup.UUID group) {
-    return group(group).view("groups");
-  }
-
-  private static RestApi group(AccountGroup.UUID group) {
-    return group(group.get());
-  }
-
-  private static RestApi group(String group) {
-    return new RestApi("/groups/").id(group);
-  }
-
-  private static class GroupInput extends JavaScriptObject {
-    final native void description(String d) /*-{ if(d)this.description=d; }-*/;
-
-    final native void name(String n) /*-{ if(n)this.name=n; }-*/;
-
-    final native void owner(String o) /*-{ if(o)this.owner=o; }-*/;
-
-    static GroupInput create() {
-      return (GroupInput) createObject();
-    }
-
-    protected GroupInput() {}
-  }
-
-  private static class GroupOptionsInput extends JavaScriptObject {
-    final native void visibleToAll(boolean v) /*-{ if(v)this.visible_to_all=v; }-*/;
-
-    static GroupOptionsInput create() {
-      return (GroupOptionsInput) createObject();
-    }
-
-    protected GroupOptionsInput() {}
-  }
-
-  private static class MemberInput extends JavaScriptObject {
-    final native void init() /*-{ this.members = []; }-*/;
-
-    final native void addMember(String n) /*-{ this.members.push(n); }-*/;
-
-    static MemberInput create() {
-      MemberInput m = (MemberInput) createObject();
-      m.init();
-      return m;
-    }
-
-    protected MemberInput() {}
-  }
-
-  private static class IncludedGroupInput extends JavaScriptObject {
-    final native void init() /*-{ this.groups = []; }-*/;
-
-    final native void addGroup(String n) /*-{ this.groups.push(n); }-*/;
-
-    static IncludedGroupInput create() {
-      IncludedGroupInput g = (IncludedGroupInput) createObject();
-      g.init();
-      return g;
-    }
-
-    protected IncludedGroupInput() {}
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/groups/GroupAuditEventInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/groups/GroupAuditEventInfo.java
deleted file mode 100644
index 255c6e8..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/groups/GroupAuditEventInfo.java
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.groups;
-
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.info.GroupInfo;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwtjsonrpc.client.impl.ser.JavaSqlTimestamp_JsonSerializer;
-import java.sql.Timestamp;
-
-public class GroupAuditEventInfo extends JavaScriptObject {
-  public enum Type {
-    ADD_USER,
-    REMOVE_USER,
-    ADD_GROUP,
-    REMOVE_GROUP
-  }
-
-  public final Timestamp date() {
-    return JavaSqlTimestamp_JsonSerializer.parseTimestamp(dateRaw());
-  }
-
-  public final Type type() {
-    return Type.valueOf(typeRaw());
-  }
-
-  public final native AccountInfo user() /*-{ return this.user; }-*/;
-
-  public final native AccountInfo memberAsUser() /*-{ return this.member; }-*/;
-
-  public final native GroupInfo memberAsGroup() /*-{ return this.member; }-*/;
-
-  private native String dateRaw() /*-{ return this.date; }-*/;
-
-  private native String typeRaw() /*-{ return this.type; }-*/;
-
-  protected GroupAuditEventInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/groups/GroupList.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/groups/GroupList.java
deleted file mode 100644
index db966b1..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/groups/GroupList.java
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.groups;
-
-import com.google.gerrit.client.info.GroupInfo;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-/** Groups available from {@code /groups/} or {@code /accounts/[id]/groups}. */
-public class GroupList extends JsArray<GroupInfo> {
-  public static void my(AsyncCallback<GroupList> callback) {
-    new RestApi("/accounts/self/groups").get(callback);
-  }
-
-  public static void included(AccountGroup.UUID group, AsyncCallback<GroupList> callback) {
-    new RestApi("/groups/").id(group.get()).view("groups").get(callback);
-  }
-
-  protected GroupList() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/groups/GroupMap.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/groups/GroupMap.java
deleted file mode 100644
index 73ac183..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/groups/GroupMap.java
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.groups;
-
-import com.google.gerrit.client.info.GroupInfo;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-/** Groups available from {@code /groups/}. */
-public class GroupMap extends NativeMap<GroupInfo> {
-  public static void all(AsyncCallback<GroupMap> callback) {
-    groups().get(NativeMap.copyKeysIntoChildren(callback));
-  }
-
-  public static void match(String match, int limit, int start, AsyncCallback<GroupMap> cb) {
-    RestApi call = groups();
-    if (match != null) {
-      if (match.startsWith("^")) {
-        call.addParameter("r", match);
-      } else {
-        call.addParameter("m", match);
-      }
-    }
-    if (limit > 0) {
-      call.addParameter("n", limit);
-    }
-    if (start > 0) {
-      call.addParameter("S", start);
-    }
-    call.get(NativeMap.copyKeysIntoChildren(cb));
-  }
-
-  public static void suggestAccountGroupForProject(
-      String project, String query, int limit, AsyncCallback<GroupMap> cb) {
-    RestApi call = groups();
-    if (project != null) {
-      call.addParameter("p", project);
-    }
-    if (query != null) {
-      call.addParameter("s", query);
-    }
-    if (limit > 0) {
-      call.addParameter("n", limit);
-    }
-    call.get(NativeMap.copyKeysIntoChildren(cb));
-  }
-
-  public static void myOwned(AsyncCallback<GroupMap> cb) {
-    myOwnedGroups().get(NativeMap.copyKeysIntoChildren(cb));
-  }
-
-  public static void myOwned(String groupName, AsyncCallback<GroupMap> cb) {
-    myOwnedGroups().addParameter("g", groupName).get(NativeMap.copyKeysIntoChildren(cb));
-  }
-
-  private static RestApi myOwnedGroups() {
-    return groups().addParameterTrue("owned");
-  }
-
-  private static RestApi groups() {
-    return new RestApi("/groups/");
-  }
-
-  protected GroupMap() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gwt_override.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gwt_override.css
deleted file mode 100644
index c92117c..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gwt_override.css
+++ /dev/null
@@ -1,88 +0,0 @@
-/* Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@external .gwt-Button;
-@external .gwt-DialogBox .dialogMiddleCenter;
-@external .gwt-TabBar;
-@external .gwt-TabBarFirst;
-@external .gwt-TabBarItem;
-@external .gwt-TabBarItem-selected;
-@external .gwt-TabBarRest;
-@external .gwt-TabPanel;
-@external .gwt-TabPanelBottom;
-
-@eval backgroundColor com.google.gerrit.client.Gerrit.getTheme().backgroundColor;
-@eval textColor com.google.gerrit.client.Gerrit.getTheme().textColor;
-@eval trimColor com.google.gerrit.client.Gerrit.getTheme().trimColor;
-@eval selectionColor com.google.gerrit.client.Gerrit.getTheme().selectionColor;
-
-body {
-  background: backgroundColor;
-  color: textColor;
-}
-
-.gwt-DialogBox .dialogMiddleCenter {
-  background: backgroundColor;
-  color: textColor;
-}
-
-.gwt-Button {
-  white-space: nowrap;
-}
-
-.gwt-TabBar .gwt-TabBarItem,
-.gwt-TabBar .gwt-TabBarRest,
-.gwt-TabPanelBottom {
-  background: transparent;
-}
-
-.gwt-TabBar {
-  border-bottom: 1px solid black;
-}
-.gwt-TabBar .gwt-TabBarFirst {
-  display: none;
-}
-.gwt-TabBar .gwt-TabBarItem {
-  color: #353535;
-  margin: 0;
-  background: trimColor;
-  padding-top: 0.5em;
-  padding-bottom: 1px;
-  padding-left: 1em;
-  padding-right: 1em;
-  border-bottom: 3px solid transparent;
-  border-right: 0;
-}
-.gwt-TabBar .gwt-TabBarItem-selected {
-  color: #990000;
-  background: selectionColor;
-  border-bottom-color: #990000;
-}
-.gwt-TabBar .gwt-TabBarRest {
-  background: trimColor;
-  padding-top: 0.5em;
-  padding-bottom: 1px;
-}
-.gwt-TabBar .gwt-TabPanelBottom {
-  background: trimColor;
-  border-top: 1px solid black;
-  border-left: none;
-  border-right: none;
-  border-bottom: none;
-  padding: 1px;
-}
-.gwt-TabPanel .gwt-TabPanelBottom {
-  border: none;
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.java
deleted file mode 100644
index 4c4c8da..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.java
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.patches;
-
-import com.google.gwt.i18n.client.Constants;
-
-public interface PatchConstants extends Constants {
-  String patchBase();
-
-  String patchSet();
-
-  String upToChange();
-
-  String openReply();
-
-  String linePrev();
-
-  String lineNext();
-
-  String chunkPrev();
-
-  String chunkNext();
-
-  String commentPrev();
-
-  String commentNext();
-
-  String focusSideA();
-
-  String focusSideB();
-
-  String expandComment();
-
-  String expandAllCommentsOnCurrentLine();
-
-  String toggleSideA();
-
-  String toggleIntraline();
-
-  String showPreferences();
-
-  String toggleReviewed();
-
-  String markAsReviewedAndGoToNext();
-
-  String commentEditorSet();
-
-  String commentInsert();
-
-  String commentSaveDraft();
-
-  String commentCancelEdit();
-
-  String whitespaceIGNORE_NONE();
-
-  String whitespaceIGNORE_TRAILING();
-
-  String whitespaceIGNORE_LEADING_AND_TRAILING();
-
-  String whitespaceIGNORE_ALL();
-
-  String previousFileHelp();
-
-  String nextFileHelp();
-
-  String download();
-
-  String edit();
-
-  String blame();
-
-  String addFileCommentToolTip();
-
-  String cannedReplyDone();
-
-  String sideBySideDiff();
-
-  String unifiedDiff();
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.properties
deleted file mode 100644
index 13f0afa..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.properties
+++ /dev/null
@@ -1,44 +0,0 @@
-cannedReplyDone = Done
-
-patchBase = Base
-patchSet = Patch Set
-
-upToChange = Up to change
-openReply = Reply and score
-linePrev = Previous line
-lineNext = Next line
-chunkPrev = Previous diff chunk
-chunkNext = Next diff chunk or search result
-commentPrev = Previous comment
-commentNext = Next comment
-focusSideA = Focus left side
-focusSideB = Focus right side
-expandComment = Expand or collapse comment
-expandAllCommentsOnCurrentLine = Expand or collapse all comments on current line
-toggleSideA = Toggle left side
-toggleIntraline = Toggle intraline difference
-showPreferences = Show diff preferences
-
-toggleReviewed = Toggle the reviewed flag
-markAsReviewedAndGoToNext = Mark patch as reviewed and go to next unreviewed patch
-
-commentEditorSet = Comment Editing
-commentInsert = Create a new inline comment
-commentSaveDraft = Save draft comment
-commentCancelEdit = Cancel comment edit
-
-whitespaceIGNORE_NONE=None
-whitespaceIGNORE_TRAILING=At Line End
-whitespaceIGNORE_LEADING_AND_TRAILING=Leading, At Line End
-whitespaceIGNORE_ALL=All
-
-previousFileHelp = Previous file
-nextFileHelp = Next file
-
-download = Download
-edit = Edit
-blame = Blame
-addFileCommentToolTip = Click to add file comment
-
-sideBySideDiff = Side-by-side diff
-unifiedDiff = Unified diff
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchMessages.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchMessages.java
deleted file mode 100644
index 358ccd3..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchMessages.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.patches;
-
-import com.google.gwt.i18n.client.Messages;
-
-public interface PatchMessages extends Messages {
-  String expandBefore(int cnt);
-
-  String expandAfter(int cnt);
-
-  String patchSkipRegion(String lineNumber);
-
-  String fileNameWithShortcutKey(String file, String key);
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchMessages.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchMessages.properties
deleted file mode 100644
index 8dcebdc..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchMessages.properties
+++ /dev/null
@@ -1,4 +0,0 @@
-expandBefore = +{0}&#x21e7;
-expandAfter = +{0}&#x21e9;
-patchSkipRegion = ... skipped {0} common lines ...
-fileNameWithShortcutKey = {0} (Shortcut: {1})
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchMessages_en.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchMessages_en.properties
deleted file mode 100644
index 8dcebdc..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchMessages_en.properties
+++ /dev/null
@@ -1,4 +0,0 @@
-expandBefore = +{0}&#x21e7;
-expandAfter = +{0}&#x21e9;
-patchSkipRegion = ... skipped {0} common lines ...
-fileNameWithShortcutKey = {0} (Shortcut: {1})
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchUtil.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchUtil.java
deleted file mode 100644
index d599756..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchUtil.java
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.patches;
-
-import com.google.gwt.core.client.GWT;
-
-public class PatchUtil {
-  public static final PatchConstants C = GWT.create(PatchConstants.class);
-  public static final PatchMessages M = GWT.create(PatchMessages.class);
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/SkippedLine.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/SkippedLine.java
deleted file mode 100644
index 486e7b8..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/SkippedLine.java
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2011 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.patches;
-
-public class SkippedLine {
-
-  private int a;
-  private int b;
-  private int sz;
-
-  public SkippedLine(int startA, int startB, int size) {
-    a = startA;
-    b = startB;
-    sz = size;
-  }
-
-  public int getStartA() {
-    return a;
-  }
-
-  public int getStartB() {
-    return b;
-  }
-
-  public int getSize() {
-    return sz;
-  }
-
-  public void incrementStart(int n) {
-    a += n;
-    b += n;
-    reduceSize(n);
-  }
-
-  public void reduceSize(int n) {
-    sz -= n;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/plugins/PluginInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/plugins/PluginInfo.java
deleted file mode 100644
index ac073de..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/plugins/PluginInfo.java
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.plugins;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class PluginInfo extends JavaScriptObject {
-  public final native String name() /*-{ return this.name }-*/;
-
-  public final native String version() /*-{ return this.version }-*/;
-
-  public final native String indexUrl() /*-{ return this.index_url }-*/;
-
-  public final native boolean disabled() /*-{ return this.disabled || false }-*/;
-
-  protected PluginInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/plugins/PluginMap.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/plugins/PluginMap.java
deleted file mode 100644
index cea27b9..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/plugins/PluginMap.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.plugins;
-
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-/** Plugins available from {@code /plugins/}. */
-public class PluginMap extends NativeMap<PluginInfo> {
-  public static void all(AsyncCallback<PluginMap> callback) {
-    new RestApi("/plugins/").addParameterTrue("all").get(NativeMap.copyKeysIntoChildren(callback));
-  }
-
-  protected PluginMap() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/BranchInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/BranchInfo.java
deleted file mode 100644
index 097f26a..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/BranchInfo.java
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.projects;
-
-import com.google.gerrit.client.info.ActionInfo;
-import com.google.gerrit.client.info.WebLinkInfo;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gwt.core.client.JsArray;
-
-public class BranchInfo extends RefInfo {
-  public final native boolean canDelete() /*-{ return this['can_delete'] ? true : false; }-*/;
-
-  public final native NativeMap<ActionInfo> actions() /*-{ return this.actions }-*/;
-
-  public final native JsArray<WebLinkInfo> webLinks() /*-{ return this.web_links; }-*/;
-
-  protected BranchInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java
deleted file mode 100644
index 684f8e6..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java
+++ /dev/null
@@ -1,262 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.projects;
-
-import com.google.gerrit.client.ErrorDialog;
-import com.google.gerrit.client.info.ActionInfo;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.extensions.client.InheritableBoolean;
-import com.google.gerrit.extensions.client.ProjectState;
-import com.google.gerrit.extensions.client.SubmitType;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwtexpui.safehtml.client.FindReplace;
-import com.google.gwtexpui.safehtml.client.LinkFindReplace;
-import com.google.gwtexpui.safehtml.client.RawFindReplace;
-import java.util.ArrayList;
-import java.util.List;
-
-public class ConfigInfo extends JavaScriptObject {
-
-  public final native String description() /*-{ return this.description }-*/;
-
-  public final native InheritedBooleanInfo requireChangeId()
-      /*-{ return this.require_change_id; }-*/ ;
-
-  public final native InheritedBooleanInfo useContentMerge()
-      /*-{ return this.use_content_merge; }-*/ ;
-
-  public final native InheritedBooleanInfo useContributorAgreements()
-      /*-{ return this.use_contributor_agreements; }-*/ ;
-
-  public final native InheritedBooleanInfo createNewChangeForAllNotInTarget()
-      /*-{ return this.create_new_change_for_all_not_in_target; }-*/ ;
-
-  public final native InheritedBooleanInfo useSignedOffBy()
-      /*-{ return this.use_signed_off_by; }-*/ ;
-
-  public final native InheritedBooleanInfo enableSignedPush()
-      /*-{ return this.enable_signed_push; }-*/ ;
-
-  public final native InheritedBooleanInfo requireSignedPush()
-      /*-{ return this.require_signed_push; }-*/ ;
-
-  public final native InheritedBooleanInfo rejectImplicitMerges()
-      /*-{ return this.reject_implicit_merges; }-*/ ;
-
-  public final native InheritedBooleanInfo privateByDefault()
-      /*-{ return this.private_by_default; }-*/ ;
-
-  public final native InheritedBooleanInfo workInProgressByDefault()
-      /*-{ return this.work_in_progress_by_default; }-*/ ;
-
-  public final native InheritedBooleanInfo enableReviewerByEmail()
-      /*-{ return this.enable_reviewer_by_email; }-*/ ;
-
-  public final native InheritedBooleanInfo matchAuthorToCommitterDate()
-      /*-{ return this.match_author_to_committer_date; }-*/ ;
-
-  public final SubmitType submitType() {
-    return SubmitType.valueOf(submitTypeRaw());
-  }
-
-  public final native SubmitTypeInfo defaultSubmitType() /*-{ return this.default_submit_type; }-*/;
-
-  public final native NativeMap<NativeMap<ConfigParameterInfo>> pluginConfig()
-      /*-{ return this.plugin_config || {}; }-*/ ;
-
-  public final native NativeMap<ConfigParameterInfo> pluginConfig(String p)
-      /*-{ return this.plugin_config[p]; }-*/ ;
-
-  public final native NativeMap<ActionInfo> actions() /*-{ return this.actions; }-*/;
-
-  private native String submitTypeRaw() /*-{ return this.submit_type }-*/;
-
-  public final ProjectState state() {
-    if (stateRaw() == null) {
-      return ProjectState.ACTIVE;
-    }
-    return ProjectState.valueOf(stateRaw());
-  }
-
-  private native String stateRaw() /*-{ return this.state }-*/;
-
-  public final native MaxObjectSizeLimitInfo maxObjectSizeLimit()
-      /*-{ return this.max_object_size_limit; }-*/ ;
-
-  private native NativeMap<CommentLinkInfo> commentlinks0() /*-{ return this.commentlinks; }-*/;
-
-  final List<FindReplace> commentlinks() {
-    JsArray<CommentLinkInfo> cls = commentlinks0().values();
-    List<FindReplace> commentLinks = new ArrayList<>(cls.length());
-    for (int i = 0; i < cls.length(); i++) {
-      CommentLinkInfo cl = cls.get(i);
-      if (!cl.enabled()) {
-        continue;
-      }
-      if (cl.link() != null) {
-        commentLinks.add(new LinkFindReplace(cl.match(), cl.link()));
-      } else {
-        try {
-          FindReplace fr = new RawFindReplace(cl.match(), cl.html());
-          commentLinks.add(fr);
-        } catch (RuntimeException e) {
-          int index = e.getMessage().indexOf("at Object");
-          new ErrorDialog(
-                  "Invalid commentlink configuration: "
-                      + (index == -1 ? e.getMessage() : e.getMessage().substring(0, index)))
-              .center();
-        }
-      }
-    }
-    return commentLinks;
-  }
-
-  final native ThemeInfo theme() /*-{ return this.theme; }-*/;
-
-  final native NativeMap<JsArrayString>
-      extensionPanelNames() /*-{ return this.extension_panel_names; }-*/;
-
-  protected ConfigInfo() {}
-
-  static class CommentLinkInfo extends JavaScriptObject {
-    final native String match() /*-{ return this.match; }-*/;
-
-    final native String link() /*-{ return this.link; }-*/;
-
-    final native String html() /*-{ return this.html; }-*/;
-
-    final native boolean enabled() /*-{
-      return !this.hasOwnProperty('enabled') || this.enabled;
-    }-*/;
-
-    protected CommentLinkInfo() {}
-  }
-
-  public static class InheritedBooleanInfo extends JavaScriptObject {
-    public static InheritedBooleanInfo create() {
-      return (InheritedBooleanInfo) createObject();
-    }
-
-    public final native boolean value() /*-{ return this.value ? true : false; }-*/;
-
-    public final native boolean inheritedValue()
-        /*-{ return this.inherited_value ? true : false; }-*/ ;
-
-    public final InheritableBoolean configuredValue() {
-      return InheritableBoolean.valueOf(configuredValueRaw());
-    }
-
-    private native String configuredValueRaw() /*-{ return this.configured_value }-*/;
-
-    public final void setConfiguredValue(InheritableBoolean v) {
-      setConfiguredValueRaw(v.name());
-    }
-
-    public final native void setConfiguredValueRaw(String v)
-        /*-{ if(v)this.configured_value=v; }-*/ ;
-
-    protected InheritedBooleanInfo() {}
-  }
-
-  public static class MaxObjectSizeLimitInfo extends JavaScriptObject {
-    public final native String value() /*-{ return this.value; }-*/;
-
-    public final native String configuredValue() /*-{ return this.configured_value }-*/;
-
-    public final native String summary() /*-{ return this.summary; }-*/;
-
-    protected MaxObjectSizeLimitInfo() {}
-  }
-
-  public static class ConfigParameterInfo extends JavaScriptObject {
-    public final native String name() /*-{ return this.name; }-*/;
-
-    public final native String displayName() /*-{ return this.display_name; }-*/;
-
-    public final native String description() /*-{ return this.description; }-*/;
-
-    public final native String warning() /*-{ return this.warning; }-*/;
-
-    public final native String type() /*-{ return this.type; }-*/;
-
-    public final native String value() /*-{ return this.value; }-*/;
-
-    public final native boolean editable() /*-{ return this.editable ? true : false; }-*/;
-
-    public final native boolean inheritable() /*-{ return this.inheritable ? true : false; }-*/;
-
-    public final native String configuredValue() /*-{ return this.configured_value; }-*/;
-
-    public final native String inheritedValue() /*-{ return this.inherited_value; }-*/;
-
-    public final native JsArrayString permittedValues() /*-{ return this.permitted_values; }-*/;
-
-    public final native JsArrayString values() /*-{ return this.values; }-*/;
-
-    protected ConfigParameterInfo() {}
-  }
-
-  public static class ConfigParameterValue extends JavaScriptObject {
-    final native void init() /*-{ this.values = []; }-*/;
-
-    final native void addValue(String v) /*-{ this.values.push(v); }-*/;
-
-    final native void setValue(String v) /*-{ if(v)this.value = v; }-*/;
-
-    public static ConfigParameterValue create() {
-      ConfigParameterValue v = createObject().cast();
-      return v;
-    }
-
-    public final ConfigParameterValue values(String[] values) {
-      init();
-      for (String v : values) {
-        addValue(v);
-      }
-      return this;
-    }
-
-    public final ConfigParameterValue value(String v) {
-      setValue(v);
-      return this;
-    }
-
-    protected ConfigParameterValue() {}
-  }
-
-  public static class SubmitTypeInfo extends JavaScriptObject {
-    public final SubmitType value() {
-      return SubmitType.valueOf(valueRaw());
-    }
-
-    public final SubmitType configuredValue() {
-      return SubmitType.valueOf(configuredValueRaw());
-    }
-
-    public final SubmitType inheritedValue() {
-      return SubmitType.valueOf(inheritedValueRaw());
-    }
-
-    private final native String valueRaw() /*-{ return this.value; }-*/;
-
-    private final native String configuredValueRaw() /*-{ return this.configured_value; }-*/;
-
-    private final native String inheritedValueRaw() /*-{ return this.inherited_value; }-*/;
-
-    protected SubmitTypeInfo() {}
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfoCache.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfoCache.java
deleted file mode 100644
index 7262b3a..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfoCache.java
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.projects;
-
-import com.google.gerrit.client.changes.ChangeApi;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.client.ui.CommentLinkProcessor;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-/** Cache of {@link ConfigInfo} objects by project name. */
-public class ConfigInfoCache {
-  private static final int PROJECT_LIMIT = 25;
-  private static final int CHANGE_LIMIT = 100;
-  private static final ConfigInfoCache instance = GWT.create(ConfigInfoCache.class);
-
-  public static class Entry {
-    private final ConfigInfo info;
-    private CommentLinkProcessor commentLinkProcessor;
-
-    private Entry(ConfigInfo info) {
-      this.info = info;
-    }
-
-    public CommentLinkProcessor getCommentLinkProcessor() {
-      if (commentLinkProcessor == null) {
-        commentLinkProcessor = new CommentLinkProcessor(info.commentlinks());
-      }
-      return commentLinkProcessor;
-    }
-
-    public ThemeInfo getTheme() {
-      return info.theme();
-    }
-
-    public List<String> getExtensionPanelNames(String extensionPoint) {
-      return Natives.asList(info.extensionPanelNames().get(extensionPoint));
-    }
-  }
-
-  public static void get(Project.NameKey name, AsyncCallback<Entry> cb) {
-    instance.getImpl(name.get(), cb);
-  }
-
-  public static void get(Change.Id changeId, AsyncCallback<Entry> cb) {
-    instance.getImpl(changeId.get(), cb);
-  }
-
-  public static void add(ChangeInfo info) {
-    instance.changeToProject.put(info.legacyId().get(), info.project());
-  }
-
-  private final LinkedHashMap<String, Entry> cache;
-  private final LinkedHashMap<Integer, String> changeToProject;
-
-  protected ConfigInfoCache() {
-    cache =
-        new LinkedHashMap<String, Entry>(PROJECT_LIMIT) {
-          private static final long serialVersionUID = 1L;
-
-          @Override
-          protected boolean removeEldestEntry(Map.Entry<String, ConfigInfoCache.Entry> e) {
-            return size() > PROJECT_LIMIT;
-          }
-        };
-
-    changeToProject =
-        new LinkedHashMap<Integer, String>(CHANGE_LIMIT) {
-          private static final long serialVersionUID = 1L;
-
-          @Override
-          protected boolean removeEldestEntry(Map.Entry<Integer, String> e) {
-            return size() > CHANGE_LIMIT;
-          }
-        };
-  }
-
-  private void getImpl(String name, AsyncCallback<Entry> cb) {
-    Entry e = cache.get(name);
-    if (e != null) {
-      cb.onSuccess(e);
-      return;
-    }
-    ProjectApi.getConfig(
-        new Project.NameKey(name),
-        new AsyncCallback<ConfigInfo>() {
-          @Override
-          public void onSuccess(ConfigInfo result) {
-            Entry e = new Entry(result);
-            cache.put(name, e);
-            cb.onSuccess(e);
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            cb.onFailure(caught);
-          }
-        });
-  }
-
-  private void getImpl(Integer id, AsyncCallback<Entry> cb) {
-    String name = changeToProject.get(id);
-    if (name != null) {
-      getImpl(name, cb);
-      return;
-    }
-    // TODO(hiesel) Make a preflight request to get project before we deprecate the numeric changeId
-    ChangeApi.change(null, id)
-        .get(
-            new AsyncCallback<ChangeInfo>() {
-              @Override
-              public void onSuccess(ChangeInfo result) {
-                changeToProject.put(id, result.project());
-                getImpl(result.project(), cb);
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {
-                cb.onFailure(caught);
-              }
-            });
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectApi.java
deleted file mode 100644
index 3be52e6..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectApi.java
+++ /dev/null
@@ -1,461 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package com.google.gerrit.client.projects;
-
-import com.google.gerrit.client.VoidResult;
-import com.google.gerrit.client.projects.ConfigInfo.ConfigParameterValue;
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.NativeString;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gerrit.extensions.client.InheritableBoolean;
-import com.google.gerrit.extensions.client.ProjectState;
-import com.google.gerrit.extensions.client.SubmitType;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-public class ProjectApi {
-  /** Create a new project */
-  public static void createProject(
-      String projectName,
-      String parent,
-      Boolean createEmptyCcommit,
-      Boolean permissionsOnly,
-      AsyncCallback<VoidResult> cb) {
-    ProjectInput input = ProjectInput.create();
-    input.setName(projectName);
-    input.setParent(parent);
-    input.setPermissionsOnly(permissionsOnly);
-    input.setCreateEmptyCommit(createEmptyCcommit);
-    new RestApi("/projects/").id(projectName).ifNoneMatch().put(input, cb);
-  }
-
-  private static RestApi getRestApi(
-      Project.NameKey name, String viewName, int limit, int start, String match) {
-    RestApi call = project(name).view(viewName);
-    call.addParameter("n", limit);
-    call.addParameter("S", start);
-    if (match != null) {
-      if (match.startsWith("^")) {
-        call.addParameter("r", match);
-      } else {
-        call.addParameter("m", match);
-      }
-    }
-    return call;
-  }
-
-  /** Create a new tag */
-  public static void createTag(
-      Project.NameKey name,
-      String ref,
-      String revision,
-      String annotation,
-      AsyncCallback<TagInfo> cb) {
-    TagInput input = TagInput.create();
-    input.setRevision(revision);
-    input.setMessage(annotation);
-    project(name).view("tags").id(ref).ifNoneMatch().put(input, cb);
-  }
-
-  /** Retrieve all visible tags of the project */
-  public static void getTags(Project.NameKey name, AsyncCallback<JsArray<TagInfo>> cb) {
-    project(name).view("tags").get(cb);
-  }
-
-  public static void getTags(
-      Project.NameKey name,
-      int limit,
-      int start,
-      String match,
-      AsyncCallback<JsArray<TagInfo>> cb) {
-    getRestApi(name, "tags", limit, start, match).get(cb);
-  }
-
-  /** Delete tags. One call is fired to the server to delete all the tags. */
-  public static void deleteTags(
-      Project.NameKey name, Set<String> refs, AsyncCallback<VoidResult> cb) {
-    if (refs.size() == 1) {
-      project(name).view("tags").id(refs.iterator().next()).delete(cb);
-    } else {
-      DeleteTagsInput d = DeleteTagsInput.create();
-      for (String ref : refs) {
-        d.addTag(ref);
-      }
-      project(name).view("tags:delete").post(d, cb);
-    }
-  }
-
-  /** Create a new branch */
-  public static void createBranch(
-      Project.NameKey name, String ref, String revision, AsyncCallback<BranchInfo> cb) {
-    BranchInput input = BranchInput.create();
-    input.setRevision(revision);
-    project(name).view("branches").id(ref).ifNoneMatch().put(input, cb);
-  }
-
-  /** Retrieve all visible branches of the project */
-  public static void getBranches(Project.NameKey name, AsyncCallback<JsArray<BranchInfo>> cb) {
-    project(name).view("branches").get(cb);
-  }
-
-  public static void getBranches(
-      Project.NameKey name,
-      int limit,
-      int start,
-      String match,
-      AsyncCallback<JsArray<BranchInfo>> cb) {
-    getRestApi(name, "branches", limit, start, match).get(cb);
-  }
-
-  /** Delete branches. One call is fired to the server to delete all the branches. */
-  public static void deleteBranches(
-      Project.NameKey name, Set<String> refs, AsyncCallback<VoidResult> cb) {
-    if (refs.size() == 1) {
-      project(name).view("branches").id(refs.iterator().next()).delete(cb);
-    } else {
-      DeleteBranchesInput d = DeleteBranchesInput.create();
-      for (String ref : refs) {
-        d.addBranch(ref);
-      }
-      project(name).view("branches:delete").post(d, cb);
-    }
-  }
-
-  public static void getConfig(Project.NameKey name, AsyncCallback<ConfigInfo> cb) {
-    project(name).view("config").get(cb);
-  }
-
-  public static void setConfig(
-      Project.NameKey name,
-      String description,
-      InheritableBoolean useContributorAgreements,
-      InheritableBoolean useContentMerge,
-      InheritableBoolean useSignedOffBy,
-      InheritableBoolean createNewChangeForAllNotInTarget,
-      InheritableBoolean requireChangeId,
-      InheritableBoolean enableSignedPush,
-      InheritableBoolean requireSignedPush,
-      InheritableBoolean rejectImplicitMerges,
-      InheritableBoolean privateByDefault,
-      InheritableBoolean workInProgressByDefault,
-      InheritableBoolean enableReviewerByEmail,
-      InheritableBoolean matchAuthorToCommitterDate,
-      String maxObjectSizeLimit,
-      SubmitType submitType,
-      ProjectState state,
-      Map<String, Map<String, ConfigParameterValue>> pluginConfigValues,
-      AsyncCallback<ConfigInfo> cb) {
-    ConfigInput in = ConfigInput.create();
-    in.setDescription(description);
-    in.setUseContributorAgreements(useContributorAgreements);
-    in.setUseContentMerge(useContentMerge);
-    in.setUseSignedOffBy(useSignedOffBy);
-    in.setRequireChangeId(requireChangeId);
-    in.setCreateNewChangeForAllNotInTarget(createNewChangeForAllNotInTarget);
-    if (enableSignedPush != null) {
-      in.setEnableSignedPush(enableSignedPush);
-    }
-    if (requireSignedPush != null) {
-      in.setRequireSignedPush(requireSignedPush);
-    }
-    in.setRejectImplicitMerges(rejectImplicitMerges);
-    in.setPrivateByDefault(privateByDefault);
-    in.setWorkInProgressByDefault(workInProgressByDefault);
-    in.setMaxObjectSizeLimit(maxObjectSizeLimit);
-    if (submitType != null) {
-      in.setSubmitType(submitType);
-    }
-    in.setState(state);
-    in.setPluginConfigValues(pluginConfigValues);
-    in.setEnableReviewerByEmail(enableReviewerByEmail);
-    in.setMatchAuthorToCommitterDate(matchAuthorToCommitterDate);
-
-    project(name).view("config").put(in, cb);
-  }
-
-  public static void getParent(Project.NameKey name, AsyncCallback<Project.NameKey> cb) {
-    project(name)
-        .view("parent")
-        .get(
-            new AsyncCallback<NativeString>() {
-              @Override
-              public void onSuccess(NativeString result) {
-                cb.onSuccess(new Project.NameKey(result.asString()));
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {
-                cb.onFailure(caught);
-              }
-            });
-  }
-
-  public static void getChildren(
-      Project.NameKey name, boolean recursive, AsyncCallback<JsArray<ProjectInfo>> cb) {
-    RestApi view = project(name).view("children");
-    if (recursive) {
-      view.addParameterTrue("recursive");
-    }
-    view.get(cb);
-  }
-
-  public static void getDescription(Project.NameKey name, AsyncCallback<NativeString> cb) {
-    project(name).view("description").get(cb);
-  }
-
-  public static void setDescription(
-      Project.NameKey name, String description, AsyncCallback<NativeString> cb) {
-    RestApi call = project(name).view("description");
-    if (description != null && !description.isEmpty()) {
-      DescriptionInput input = DescriptionInput.create();
-      input.setDescription(description);
-      call.put(input, cb);
-    } else {
-      call.delete(cb);
-    }
-  }
-
-  public static void setHead(Project.NameKey name, String ref, AsyncCallback<NativeString> cb) {
-    RestApi call = project(name).view("HEAD");
-    HeadInput input = HeadInput.create();
-    input.setRef(ref);
-    call.put(input, cb);
-  }
-
-  public static RestApi project(Project.NameKey name) {
-    return new RestApi("/projects/").id(name.get());
-  }
-
-  private static class ProjectInput extends JavaScriptObject {
-    static ProjectInput create() {
-      return (ProjectInput) createObject();
-    }
-
-    protected ProjectInput() {}
-
-    final native void setName(String n) /*-{ if(n)this.name=n; }-*/;
-
-    final native void setParent(String p) /*-{ if(p)this.parent=p; }-*/;
-
-    final native void setPermissionsOnly(boolean po) /*-{ if(po)this.permissions_only=po; }-*/;
-
-    final native void setCreateEmptyCommit(boolean cc) /*-{ if(cc)this.create_empty_commit=cc; }-*/;
-  }
-
-  private static class ConfigInput extends JavaScriptObject {
-    static ConfigInput create() {
-      return (ConfigInput) createObject();
-    }
-
-    protected ConfigInput() {}
-
-    final native void setDescription(String d) /*-{ if(d)this.description=d; }-*/;
-
-    final void setUseContributorAgreements(InheritableBoolean v) {
-      setUseContributorAgreementsRaw(v.name());
-    }
-
-    private native void setUseContributorAgreementsRaw(String v)
-        /*-{ if(v)this.use_contributor_agreements=v; }-*/ ;
-
-    final void setUseContentMerge(InheritableBoolean v) {
-      setUseContentMergeRaw(v.name());
-    }
-
-    private native void setUseContentMergeRaw(String v) /*-{ if(v)this.use_content_merge=v; }-*/;
-
-    final void setUseSignedOffBy(InheritableBoolean v) {
-      setUseSignedOffByRaw(v.name());
-    }
-
-    private native void setUseSignedOffByRaw(String v) /*-{ if(v)this.use_signed_off_by=v; }-*/;
-
-    final void setRequireChangeId(InheritableBoolean v) {
-      setRequireChangeIdRaw(v.name());
-    }
-
-    private native void setRequireChangeIdRaw(String v) /*-{ if(v)this.require_change_id=v; }-*/;
-
-    final void setCreateNewChangeForAllNotInTarget(InheritableBoolean v) {
-      setCreateNewChangeForAllNotInTargetRaw(v.name());
-    }
-
-    private native void setCreateNewChangeForAllNotInTargetRaw(String v)
-        /*-{ if(v)this.create_new_change_for_all_not_in_target=v; }-*/ ;
-
-    final void setEnableSignedPush(InheritableBoolean v) {
-      setEnableSignedPushRaw(v.name());
-    }
-
-    private native void setEnableSignedPushRaw(String v) /*-{ if(v)this.enable_signed_push=v; }-*/;
-
-    final void setRequireSignedPush(InheritableBoolean v) {
-      setRequireSignedPushRaw(v.name());
-    }
-
-    final void setPrivateByDefault(InheritableBoolean v) {
-      setPrivateByDefault(v.name());
-    }
-
-    private native void setPrivateByDefault(String v) /*-{ if(v)this.private_by_default=v; }-*/;
-
-    final void setWorkInProgressByDefault(InheritableBoolean v) {
-      setWorkInProgressByDefault(v.name());
-    }
-
-    private native void setWorkInProgressByDefault(
-        String v) /*-{ if(v)this.work_in_progress_by_default=v; }-*/;
-
-    final void setEnableReviewerByEmail(InheritableBoolean v) {
-      setEnableReviewerByEmailRaw(v.name());
-    }
-
-    final void setMatchAuthorToCommitterDate(InheritableBoolean v) {
-      setMatchAuthorToCommitterDateRaw(v.name());
-    }
-
-    private native void setMatchAuthorToCommitterDateRaw(String v)
-        /*-{ if(v)this.match_author_to_committer_date=v; }-*/ ;
-
-    private native void setEnableReviewerByEmailRaw(String v)
-        /*-{ if(v)this.enable_reviewer_by_email=v; }-*/ ;
-
-    private native void setRequireSignedPushRaw(String v)
-        /*-{ if(v)this.require_signed_push=v; }-*/ ;
-
-    final void setRejectImplicitMerges(InheritableBoolean v) {
-      setRejectImplicitMergesRaw(v.name());
-    }
-
-    private native void setRejectImplicitMergesRaw(String v)
-        /*-{ if(v)this.reject_implicit_merges=v; }-*/ ;
-
-    final native void setMaxObjectSizeLimit(String l) /*-{ if(l)this.max_object_size_limit=l; }-*/;
-
-    final void setSubmitType(SubmitType t) {
-      setSubmitTypeRaw(t.name());
-    }
-
-    private native void setSubmitTypeRaw(String t) /*-{ if(t)this.submit_type=t; }-*/;
-
-    final void setState(ProjectState s) {
-      setStateRaw(s.name());
-    }
-
-    private native void setStateRaw(String s) /*-{ if(s)this.state=s; }-*/;
-
-    final void setPluginConfigValues(
-        Map<String, Map<String, ConfigParameterValue>> pluginConfigValues) {
-      if (!pluginConfigValues.isEmpty()) {
-        NativeMap<ConfigParameterValueMap> configValues = NativeMap.create().cast();
-        for (Entry<String, Map<String, ConfigParameterValue>> e : pluginConfigValues.entrySet()) {
-          ConfigParameterValueMap values = ConfigParameterValueMap.create();
-          configValues.put(e.getKey(), values);
-          for (Entry<String, ConfigParameterValue> e2 : e.getValue().entrySet()) {
-            values.put(e2.getKey(), e2.getValue());
-          }
-        }
-        setPluginConfigValuesRaw(configValues);
-      }
-    }
-
-    private native void setPluginConfigValuesRaw(NativeMap<ConfigParameterValueMap> v)
-        /*-{ this.plugin_config_values=v; }-*/ ;
-  }
-
-  private static class ConfigParameterValueMap extends JavaScriptObject {
-    static ConfigParameterValueMap create() {
-      return createObject().cast();
-    }
-
-    protected ConfigParameterValueMap() {}
-
-    public final native void put(String n, ConfigParameterValue v) /*-{ this[n] = v; }-*/;
-  }
-
-  private static class TagInput extends JavaScriptObject {
-    static TagInput create() {
-      return (TagInput) createObject();
-    }
-
-    protected TagInput() {}
-
-    final native void setRevision(String r) /*-{ if(r)this.revision=r; }-*/;
-
-    final native void setMessage(String m) /*-{ if(m)this.message=m; }-*/;
-  }
-
-  private static class BranchInput extends JavaScriptObject {
-    static BranchInput create() {
-      return (BranchInput) createObject();
-    }
-
-    protected BranchInput() {}
-
-    final native void setRevision(String r) /*-{ if(r)this.revision=r; }-*/;
-  }
-
-  private static class DescriptionInput extends JavaScriptObject {
-    static DescriptionInput create() {
-      return (DescriptionInput) createObject();
-    }
-
-    protected DescriptionInput() {}
-
-    final native void setDescription(String d) /*-{ if(d)this.description=d; }-*/;
-  }
-
-  private static class HeadInput extends JavaScriptObject {
-    static HeadInput create() {
-      return createObject().cast();
-    }
-
-    protected HeadInput() {}
-
-    final native void setRef(String r) /*-{ if(r)this.ref=r; }-*/;
-  }
-
-  private static class DeleteTagsInput extends JavaScriptObject {
-    static DeleteTagsInput create() {
-      DeleteTagsInput d = createObject().cast();
-      d.init();
-      return d;
-    }
-
-    protected DeleteTagsInput() {}
-
-    final native void init() /*-{ this.tags = []; }-*/;
-
-    final native void addTag(String b) /*-{ this.tags.push(b); }-*/;
-  }
-
-  private static class DeleteBranchesInput extends JavaScriptObject {
-    static DeleteBranchesInput create() {
-      DeleteBranchesInput d = createObject().cast();
-      d.init();
-      return d;
-    }
-
-    protected DeleteBranchesInput() {}
-
-    final native void init() /*-{ this.branches = []; }-*/;
-
-    final native void addBranch(String b) /*-{ this.branches.push(b); }-*/;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectInfo.java
deleted file mode 100644
index 1ff568f..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectInfo.java
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.projects;
-
-import com.google.gerrit.client.info.WebLinkInfo;
-import com.google.gerrit.extensions.client.ProjectState;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.user.client.ui.SuggestOracle;
-
-public class ProjectInfo extends JavaScriptObject implements SuggestOracle.Suggestion {
-  public final Project.NameKey name_key() {
-    return new Project.NameKey(name());
-  }
-
-  public final native String name() /*-{ return this.name; }-*/;
-
-  public final native String description() /*-{ return this.description; }-*/;
-
-  public final native JsArray<WebLinkInfo> webLinks() /*-{ return this.web_links; }-*/;
-
-  public final ProjectState state() {
-    return ProjectState.valueOf(getStringState());
-  }
-
-  private native String getStringState() /*-{ return this.state; }-*/;
-
-  @Override
-  public final String getDisplayString() {
-    if (description() != null) {
-      return name() + " (" + description() + ")";
-    }
-    return name();
-  }
-
-  @Override
-  public final String getReplacementString() {
-    return name();
-  }
-
-  protected ProjectInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectMap.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectMap.java
deleted file mode 100644
index 5ff300d..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectMap.java
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.projects;
-
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.RestApi;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-/** Projects available from {@code /projects/}. */
-public class ProjectMap extends NativeMap<ProjectInfo> {
-  public static void all(AsyncCallback<ProjectMap> callback) {
-    new RestApi("/projects/")
-        .addParameterRaw("type", "ALL")
-        .addParameterTrue("all")
-        .addParameterTrue("d") // description
-        .get(NativeMap.copyKeysIntoChildren(callback));
-  }
-
-  public static void permissions(AsyncCallback<ProjectMap> callback) {
-    new RestApi("/projects/")
-        .addParameterRaw("type", "PERMISSIONS")
-        .addParameterTrue("all")
-        .addParameterTrue("d") // description
-        .get(NativeMap.copyKeysIntoChildren(callback));
-  }
-
-  public static void parentCandidates(AsyncCallback<ProjectMap> callback) {
-    new RestApi("/projects/")
-        .addParameterRaw("type", "PARENT_CANDIDATES")
-        .addParameterTrue("all")
-        .addParameterTrue("d") // description
-        .get(NativeMap.copyKeysIntoChildren(callback));
-  }
-
-  public static void suggest(String match, int limit, AsyncCallback<ProjectMap> cb) {
-    new RestApi("/projects/")
-        .addParameter("m", match)
-        .addParameter("n", limit)
-        .addParameterRaw("type", "ALL")
-        .addParameterTrue("d") // description
-        .background()
-        .get(NativeMap.copyKeysIntoChildren(cb));
-  }
-
-  public static void match(String match, int limit, int start, AsyncCallback<ProjectMap> cb) {
-    RestApi call = new RestApi("/projects/");
-    if (match != null) {
-      if (match.startsWith("^")) {
-        call.addParameter("r", match);
-      } else {
-        call.addParameter("m", match);
-      }
-    }
-    if (limit > 0) {
-      call.addParameter("n", limit);
-    }
-    if (start > 0) {
-      call.addParameter("S", start);
-    }
-    call.addParameterRaw("type", "ALL");
-    call.addParameterTrue("d"); // description
-    call.get(NativeMap.copyKeysIntoChildren(cb));
-  }
-
-  public static void match(String match, AsyncCallback<ProjectMap> cb) {
-    match(match, 0, 0, cb);
-  }
-
-  protected ProjectMap() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/RefInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/RefInfo.java
deleted file mode 100644
index 90c862f..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/RefInfo.java
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.projects;
-
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class RefInfo extends JavaScriptObject {
-  public final String getShortName() {
-    return RefNames.shortName(ref());
-  }
-
-  public final native String ref() /*-{ return this.ref; }-*/;
-
-  public final native String revision() /*-{ return this.revision; }-*/;
-
-  protected RefInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/TagInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/TagInfo.java
deleted file mode 100644
index fc13fe1..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/TagInfo.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.projects;
-
-import com.google.gerrit.client.info.WebLinkInfo;
-import com.google.gwt.core.client.JsArray;
-
-public class TagInfo extends RefInfo {
-  public final native boolean canDelete() /*-{ return this['can_delete'] ? true : false; }-*/;
-
-  public final native JsArray<WebLinkInfo> webLinks() /*-{ return this.web_links; }-*/;
-
-  // TODO(dpursehouse) add extra tag-related fields (message, tagger, etc)
-  protected TagInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ThemeInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ThemeInfo.java
deleted file mode 100644
index 7584e14..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ThemeInfo.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.projects;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class ThemeInfo extends JavaScriptObject {
-  public final native String css() /*-{ return this.css; }-*/;
-
-  public final native String header() /*-{ return this.header; }-*/;
-
-  public final native String footer() /*-{ return this.footer; }-*/;
-
-  protected ThemeInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/CallbackGroup.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/CallbackGroup.java
deleted file mode 100644
index af32d01..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/CallbackGroup.java
+++ /dev/null
@@ -1,260 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.rpc;
-
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Class for grouping together callbacks and calling them in order.
- *
- * <p>Callbacks are added to the group with {@link #add(AsyncCallback)}, which returns a wrapped
- * callback suitable for passing to an asynchronous RPC call. The last callback must be added using
- * {@link #addFinal(AsyncCallback)} or {@link #done()} must be invoked.
- *
- * <p>The enclosing group buffers returned results and ensures that {@code onSuccess} is called
- * exactly once for each callback in the group, in the same order that callbacks were added. This
- * allows callers to, for example, use a {@link ScreenLoadCallback} as the last callback in the list
- * and only display the screen once all callbacks have succeeded.
- *
- * <p>In the event of a failure, the <em>first</em> caught exception is sent to <em>all</em>
- * callbacks' {@code onFailure} methods, in order; subsequent successes or failures are all ignored.
- * Note that this means {@code onFailure} may be called with an exception unrelated to the callback
- * processing it.
- */
-public class CallbackGroup {
-  private final List<CallbackGlue> callbacks;
-  private final Set<CallbackGlue> remaining;
-  private boolean finalAdded;
-
-  private boolean failed;
-  private Throwable failedThrowable;
-
-  public static <T> Callback<T> emptyCallback() {
-    return new Callback<T>() {
-      @Override
-      public void onSuccess(T result) {}
-
-      @Override
-      public void onFailure(Throwable err) {}
-    };
-  }
-
-  public CallbackGroup() {
-    callbacks = new ArrayList<>();
-    remaining = new HashSet<>();
-  }
-
-  public <T> Callback<T> addEmpty() {
-    Callback<T> cb = emptyCallback();
-    return add(cb);
-  }
-
-  public <T> Callback<T> add(AsyncCallback<T> cb) {
-    checkFinalAdded();
-    return handleAdd(cb);
-  }
-
-  public <T> HttpCallback<T> add(HttpCallback<T> cb) {
-    checkFinalAdded();
-    return handleAdd(cb);
-  }
-
-  public <T> Callback<T> addFinal(AsyncCallback<T> cb) {
-    checkFinalAdded();
-    finalAdded = true;
-    return handleAdd(cb);
-  }
-
-  public <T> HttpCallback<T> addFinal(HttpCallback<T> cb) {
-    checkFinalAdded();
-    finalAdded = true;
-    return handleAdd(cb);
-  }
-
-  public void done() {
-    finalAdded = true;
-    apply();
-  }
-
-  public void addListener(AsyncCallback<Void> cb) {
-    if (!failed && finalAdded && remaining.isEmpty()) {
-      cb.onSuccess(null);
-    } else {
-      handleAdd(cb).onSuccess(null);
-    }
-  }
-
-  public void addListener(CallbackGroup group) {
-    addListener(group.<Void>addEmpty());
-  }
-
-  private void success(CallbackGlue cb) {
-    remaining.remove(cb);
-    apply();
-  }
-
-  private <T> void failure(CallbackGlue w, Throwable caught) {
-    if (!failed) {
-      failed = true;
-      failedThrowable = caught;
-    }
-    remaining.remove(w);
-    apply();
-  }
-
-  private void apply() {
-    if (finalAdded && remaining.isEmpty()) {
-      if (failed) {
-        for (CallbackGlue cb : callbacks) {
-          cb.applyFailed();
-        }
-      } else {
-        for (CallbackGlue cb : callbacks) {
-          cb.applySuccess();
-        }
-      }
-      callbacks.clear();
-    }
-  }
-
-  private <T> Callback<T> handleAdd(AsyncCallback<T> cb) {
-    if (failed) {
-      cb.onFailure(failedThrowable);
-      return emptyCallback();
-    }
-
-    CallbackImpl<T> wrapper = new CallbackImpl<>(cb);
-    callbacks.add(wrapper);
-    remaining.add(wrapper);
-    return wrapper;
-  }
-
-  private <T> HttpCallback<T> handleAdd(HttpCallback<T> cb) {
-    if (failed) {
-      cb.onFailure(failedThrowable);
-      return new HttpCallback<T>() {
-        @Override
-        public void onSuccess(HttpResponse<T> result) {}
-
-        @Override
-        public void onFailure(Throwable caught) {}
-      };
-    }
-
-    HttpCallbackImpl<T> w = new HttpCallbackImpl<>(cb);
-    callbacks.add(w);
-    remaining.add(w);
-    return w;
-  }
-
-  private void checkFinalAdded() {
-    if (finalAdded) {
-      throw new IllegalStateException("final callback already added");
-    }
-  }
-
-  public interface Callback<T>
-      extends AsyncCallback<T>, com.google.gwtjsonrpc.common.AsyncCallback<T> {}
-
-  private interface CallbackGlue {
-    void applySuccess();
-
-    void applyFailed();
-  }
-
-  private class CallbackImpl<T> implements Callback<T>, CallbackGlue {
-    AsyncCallback<T> delegate;
-    T result;
-
-    CallbackImpl(AsyncCallback<T> delegate) {
-      this.delegate = delegate;
-    }
-
-    @Override
-    public void onSuccess(T value) {
-      this.result = value;
-      success(this);
-    }
-
-    @Override
-    public void onFailure(Throwable caught) {
-      failure(this, caught);
-    }
-
-    @Override
-    public void applySuccess() {
-      AsyncCallback<T> cb = delegate;
-      if (cb != null) {
-        delegate = null;
-        cb.onSuccess(result);
-        result = null;
-      }
-    }
-
-    @Override
-    public void applyFailed() {
-      AsyncCallback<T> cb = delegate;
-      if (cb != null) {
-        delegate = null;
-        result = null;
-        cb.onFailure(failedThrowable);
-      }
-    }
-  }
-
-  private class HttpCallbackImpl<T> implements HttpCallback<T>, CallbackGlue {
-    private HttpCallback<T> delegate;
-    private HttpResponse<T> result;
-
-    HttpCallbackImpl(HttpCallback<T> delegate) {
-      this.delegate = delegate;
-    }
-
-    @Override
-    public void onSuccess(HttpResponse<T> result) {
-      this.result = result;
-      success(this);
-    }
-
-    @Override
-    public void onFailure(Throwable caught) {
-      failure(this, caught);
-    }
-
-    @Override
-    public void applySuccess() {
-      HttpCallback<T> cb = delegate;
-      if (cb != null) {
-        delegate = null;
-        cb.onSuccess(result);
-        result = null;
-      }
-    }
-
-    @Override
-    public void applyFailed() {
-      HttpCallback<T> cb = delegate;
-      if (cb != null) {
-        delegate = null;
-        result = null;
-        cb.onFailure(failedThrowable);
-      }
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/GerritCallback.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/GerritCallback.java
deleted file mode 100644
index 2d6723a..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/GerritCallback.java
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.rpc;
-
-import com.google.gerrit.client.ErrorDialog;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.NotSignedInDialog;
-import com.google.gerrit.common.errors.NameAlreadyUsedException;
-import com.google.gerrit.common.errors.NoSuchAccountException;
-import com.google.gerrit.common.errors.NoSuchEntityException;
-import com.google.gerrit.common.errors.NoSuchGroupException;
-import com.google.gerrit.common.errors.NotSignedInException;
-import com.google.gwt.user.client.rpc.InvocationException;
-import com.google.gwtjsonrpc.client.RemoteJsonException;
-import com.google.gwtjsonrpc.client.ServerUnavailableException;
-import com.google.gwtjsonrpc.common.JsonConstants;
-
-/** Abstract callback handling generic error conditions automatically */
-public abstract class GerritCallback<T>
-    implements com.google.gwtjsonrpc.common.AsyncCallback<T>,
-        com.google.gwt.user.client.rpc.AsyncCallback<T> {
-  @Override
-  public void onFailure(Throwable caught) {
-    showFailure(caught);
-  }
-
-  public static void showFailure(Throwable caught) {
-    if (isSigninFailure(caught)) {
-      new NotSignedInDialog().center();
-    } else if (isNoSuchEntity(caught)) {
-      new ErrorDialog(Gerrit.C.notFoundBody()).center();
-    } else if (isNoSuchAccount(caught)) {
-      final String msg = caught.getMessage();
-      final String who = msg.substring(NoSuchAccountException.MESSAGE.length());
-      final ErrorDialog d = new ErrorDialog(Gerrit.M.noSuchAccountMessage(who));
-      d.setText(Gerrit.C.noSuchAccountTitle());
-      d.center();
-
-    } else if (isNameAlreadyUsed(caught)) {
-      final String msg = caught.getMessage();
-      final String alreadyUsedName = msg.substring(NameAlreadyUsedException.MESSAGE.length());
-      new ErrorDialog(Gerrit.M.nameAlreadyUsedBody(alreadyUsedName)).center();
-
-    } else if (isNoSuchGroup(caught)) {
-      final String msg = caught.getMessage();
-      final String group = msg.substring(NoSuchGroupException.MESSAGE.length());
-      final ErrorDialog d = new ErrorDialog(Gerrit.M.noSuchGroupMessage(group));
-      d.setText(Gerrit.C.noSuchGroupTitle());
-      d.center();
-
-    } else if (caught instanceof ServerUnavailableException) {
-      new ErrorDialog(RpcConstants.C.errorServerUnavailable()).center();
-
-    } else {
-      new ErrorDialog(caught).center();
-    }
-  }
-
-  public static boolean isSigninFailure(Throwable caught) {
-    if (isNotSignedIn(caught)
-        || isInvalidXSRF(caught)
-        || (isNoSuchEntity(caught) && !Gerrit.isSignedIn())) {
-      return true;
-    }
-    return false;
-  }
-
-  protected static boolean isInvalidXSRF(Throwable caught) {
-    return caught instanceof InvocationException
-        && caught.getMessage().equals(JsonConstants.ERROR_INVALID_XSRF);
-  }
-
-  protected static boolean isNotSignedIn(Throwable caught) {
-    return RestApi.isNotSignedIn(caught)
-        || (caught instanceof RemoteJsonException
-            && caught.getMessage().equals(NotSignedInException.MESSAGE));
-  }
-
-  protected static boolean isNoSuchEntity(Throwable caught) {
-    return RestApi.isNotFound(caught)
-        || (caught instanceof RemoteJsonException
-            && caught.getMessage().equals(NoSuchEntityException.MESSAGE));
-  }
-
-  protected static boolean isNoSuchAccount(Throwable caught) {
-    return caught instanceof RemoteJsonException
-        && caught.getMessage().startsWith(NoSuchAccountException.MESSAGE);
-  }
-
-  protected static boolean isNameAlreadyUsed(Throwable caught) {
-    return caught instanceof RemoteJsonException
-        && caught.getMessage().startsWith(NameAlreadyUsedException.MESSAGE);
-  }
-
-  protected static boolean isNoSuchGroup(Throwable caught) {
-    return caught instanceof RemoteJsonException
-        && caught.getMessage().startsWith(NoSuchGroupException.MESSAGE);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/HttpCallback.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/HttpCallback.java
deleted file mode 100644
index 2de2980..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/HttpCallback.java
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.rpc;
-
-/** AsyncCallback supplied with HTTP response headers. */
-public interface HttpCallback<T> {
-  void onSuccess(HttpResponse<T> result);
-
-  void onFailure(Throwable caught);
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/HttpResponse.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/HttpResponse.java
deleted file mode 100644
index 22d62fb..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/HttpResponse.java
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.rpc;
-
-import com.google.gwt.http.client.Response;
-
-/** Wraps decoded server reply with HTTP headers. */
-public class HttpResponse<T> {
-  private final Response httpResponse;
-  private final String contentType;
-  private final T result;
-
-  HttpResponse(Response httpResponse, String contentType, T result) {
-    this.httpResponse = httpResponse;
-    this.contentType = contentType;
-    this.result = result;
-  }
-
-  /** HTTP status code, always in the 2xx family. */
-  public int getStatusCode() {
-    return httpResponse.getStatusCode();
-  }
-
-  /**
-   * Content type supplied by the server.
-   *
-   * <p>This helper simplifies the common {@code getHeader("Content-Type")} case.
-   */
-  public String getContentType() {
-    return contentType;
-  }
-
-  /** Lookup an arbitrary reply header. */
-  public String getHeader(String header) {
-    if ("Content-Type".equals(header)) {
-      return contentType;
-    }
-    return httpResponse.getHeader(header);
-  }
-
-  public T getResult() {
-    return result;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RestApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RestApi.java
deleted file mode 100644
index e2a9ffb..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RestApi.java
+++ /dev/null
@@ -1,519 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.rpc;
-
-import static com.google.gwt.http.client.RequestBuilder.DELETE;
-import static com.google.gwt.http.client.RequestBuilder.GET;
-import static com.google.gwt.http.client.RequestBuilder.POST;
-import static com.google.gwt.http.client.RequestBuilder.PUT;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.RpcStatus;
-import com.google.gerrit.common.data.HostPageData;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.http.client.Request;
-import com.google.gwt.http.client.RequestBuilder;
-import com.google.gwt.http.client.RequestBuilder.Method;
-import com.google.gwt.http.client.RequestCallback;
-import com.google.gwt.http.client.RequestException;
-import com.google.gwt.http.client.Response;
-import com.google.gwt.http.client.URL;
-import com.google.gwt.json.client.JSONException;
-import com.google.gwt.json.client.JSONParser;
-import com.google.gwt.json.client.JSONValue;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.rpc.StatusCodeException;
-
-/** Makes a REST API call to the server. */
-public class RestApi {
-  private static final int SC_UNAVAILABLE = 2;
-  private static final int SC_BAD_TRANSPORT = 3;
-  private static final int SC_BAD_RESPONSE = 4;
-  private static final String JSON_TYPE = "application/json";
-  private static final String JSON_UTF8 = JSON_TYPE + "; charset=utf-8";
-  private static final String TEXT_TYPE = "text/plain";
-  private static final String TEXT_UTF8 = TEXT_TYPE + "; charset=utf-8";
-
-  /**
-   * Expected JSON content body prefix that prevents XSSI.
-   *
-   * <p>The server always includes this line as the first line of the response content body when the
-   * response body is formatted as JSON. It gets inserted by the server to prevent the resource from
-   * being imported into another domain's page using a &lt;script&gt; tag. This line must be removed
-   * before the JSON can be parsed.
-   */
-  private static final String JSON_MAGIC = ")]}'\n";
-
-  /** True if err is a StatusCodeException reporting Not Found. */
-  public static boolean isNotFound(Throwable err) {
-    return isStatus(err, Response.SC_NOT_FOUND);
-  }
-
-  /** True if err is describing a user that is currently anonymous. */
-  public static boolean isNotSignedIn(Throwable err) {
-    if (err instanceof StatusCodeException) {
-      StatusCodeException sce = (StatusCodeException) err;
-      if (sce.getStatusCode() == Response.SC_UNAUTHORIZED) {
-        return true;
-      }
-      return sce.getStatusCode() == Response.SC_FORBIDDEN
-          && (sce.getEncodedResponse().equals("Authentication required")
-              || sce.getEncodedResponse().startsWith("Must be signed-in")
-              || sce.getEncodedResponse().startsWith("Invalid authentication"));
-    }
-    return false;
-  }
-
-  /** True if err is a StatusCodeException with a specific HTTP code. */
-  public static boolean isStatus(Throwable err, int status) {
-    return err instanceof StatusCodeException
-        && ((StatusCodeException) err).getStatusCode() == status;
-  }
-
-  /** Is the Gerrit Code Review server likely to return this status? */
-  public static boolean isExpected(int statusCode) {
-    switch (statusCode) {
-      case SC_UNAVAILABLE:
-      case Response.SC_BAD_REQUEST:
-      case Response.SC_UNAUTHORIZED:
-      case Response.SC_FORBIDDEN:
-      case Response.SC_NOT_FOUND:
-      case Response.SC_METHOD_NOT_ALLOWED:
-      case Response.SC_CONFLICT:
-      case Response.SC_PRECONDITION_FAILED:
-      case 422: // Unprocessable Entity
-      case 429: // Too Many Requests (RFC 6585)
-        return true;
-
-      default:
-        // Assume any other code is not expected. These may be
-        // local proxy server errors outside of our control.
-        return false;
-    }
-  }
-
-  private static class HttpImpl<T extends JavaScriptObject> implements RequestCallback {
-    private final boolean background;
-    private final HttpCallback<T> cb;
-
-    HttpImpl(boolean bg, HttpCallback<T> cb) {
-      this.background = bg;
-      this.cb = cb;
-    }
-
-    @Override
-    public void onResponseReceived(Request req, Response res) {
-      int status = res.getStatusCode();
-      if (status == Response.SC_NO_CONTENT) {
-        cb.onSuccess(new HttpResponse<T>(res, null, null));
-        if (!background) {
-          RpcStatus.INSTANCE.onRpcComplete();
-        }
-
-      } else if (200 <= status && status < 300) {
-        long start = System.currentTimeMillis();
-        final T data;
-        final String type;
-        if (isJsonBody(res)) {
-          try {
-            JSONValue val = parseJson(res);
-            if (isJsonEncoded(res) && val.isString() != null) {
-              data = NativeString.wrap(val.isString().stringValue()).cast();
-              type = simpleType(res.getHeader("X-FYI-Content-Type"));
-            } else {
-              data = RestApi.<T>cast(val);
-              type = JSON_TYPE;
-            }
-          } catch (JSONException e) {
-            if (!background) {
-              RpcStatus.INSTANCE.onRpcComplete();
-            }
-            cb.onFailure(
-                new StatusCodeException(SC_BAD_RESPONSE, "Invalid JSON: " + e.getMessage()));
-            return;
-          }
-        } else if (isTextBody(res)) {
-          data = NativeString.wrap(res.getText()).cast();
-          type = TEXT_TYPE;
-        } else {
-          if (!background) {
-            RpcStatus.INSTANCE.onRpcComplete();
-          }
-          cb.onFailure(
-              new StatusCodeException(
-                  SC_BAD_RESPONSE,
-                  "Expected "
-                      + JSON_TYPE
-                      + " or "
-                      + TEXT_TYPE
-                      + "; received Content-Type: "
-                      + res.getHeader("Content-Type")));
-          return;
-        }
-
-        Scheduler.ScheduledCommand cmd =
-            new Scheduler.ScheduledCommand() {
-              @Override
-              public void execute() {
-                try {
-                  cb.onSuccess(new HttpResponse<>(res, type, data));
-                } finally {
-                  if (!background) {
-                    RpcStatus.INSTANCE.onRpcComplete();
-                  }
-                }
-              }
-            };
-
-        // Defer handling the response if the create took a while.
-        if ((System.currentTimeMillis() - start) > 75) {
-          Scheduler.get().scheduleDeferred(cmd);
-        } else {
-          cmd.execute();
-        }
-      } else {
-        String msg;
-        if (isTextBody(res)) {
-          msg = res.getText().trim();
-        } else if (isJsonBody(res)) {
-          JSONValue v;
-          try {
-            v = parseJson(res);
-          } catch (JSONException e) {
-            v = null;
-          }
-          if (v != null && v.isString() != null) {
-            msg = v.isString().stringValue();
-          } else {
-            msg = trimJsonMagic(res.getText()).trim();
-          }
-        } else {
-          msg = res.getStatusText();
-        }
-
-        if (!background) {
-          RpcStatus.INSTANCE.onRpcComplete();
-        }
-        cb.onFailure(new StatusCodeException(status, msg));
-      }
-    }
-
-    @Override
-    public void onError(Request req, Throwable err) {
-      if (!background) {
-        RpcStatus.INSTANCE.onRpcComplete();
-      }
-      if (err.getMessage().contains("XmlHttpRequest.status")) {
-        cb.onFailure(
-            new StatusCodeException(SC_UNAVAILABLE, RpcConstants.C.errorServerUnavailable()));
-      } else {
-        cb.onFailure(new StatusCodeException(SC_BAD_TRANSPORT, err.getMessage()));
-      }
-    }
-  }
-
-  private StringBuilder url;
-  private boolean hasQueryParams;
-  private boolean background;
-  private String ifNoneMatch;
-
-  /**
-   * Initialize a new API call.
-   *
-   * <p>By default the JSON format will be selected by including an HTTP Accept header in the
-   * request.
-   *
-   * @param name URL of the REST resource to access, e.g. {@code "/projects/"} to list accessible
-   *     projects from the server.
-   */
-  public RestApi(String name) {
-    if (name.startsWith("/")) {
-      name = name.substring(1);
-    }
-
-    url = new StringBuilder();
-    url.append(GWT.getHostPageBaseURL());
-    url.append(name);
-  }
-
-  public RestApi view(String name) {
-    return idRaw(name);
-  }
-
-  public RestApi id(String id) {
-    return idRaw(URL.encodePathSegment(id));
-  }
-
-  public RestApi id(String project, int id) {
-    return idRaw(URL.encodePathSegment(project) + "~" + id);
-  }
-
-  public RestApi id(int id) {
-    return idRaw(Integer.toString(id));
-  }
-
-  public RestApi idRaw(String name) {
-    if (hasQueryParams) {
-      throw new IllegalStateException();
-    }
-    if (url.charAt(url.length() - 1) != '/') {
-      url.append('/');
-    }
-    url.append(name);
-    return this;
-  }
-
-  public RestApi addParameter(String name, String value) {
-    return addParameterRaw(name, URL.encodeQueryString(value));
-  }
-
-  public RestApi addParameter(String name, String... value) {
-    for (String val : value) {
-      addParameter(name, val);
-    }
-    return this;
-  }
-
-  public RestApi addParameterTrue(String name) {
-    return addParameterRaw(name, null);
-  }
-
-  public RestApi addParameter(String name, boolean value) {
-    return addParameterRaw(name, value ? "t" : "f");
-  }
-
-  public RestApi addParameter(String name, int value) {
-    return addParameterRaw(name, String.valueOf(value));
-  }
-
-  public RestApi addParameter(String name, Enum<?> value) {
-    return addParameterRaw(name, value.name());
-  }
-
-  public RestApi addParameterRaw(String name, String value) {
-    if (hasQueryParams) {
-      url.append("&");
-    } else {
-      url.append("?");
-      hasQueryParams = true;
-    }
-    url.append(name);
-    if (value != null) {
-      url.append("=").append(value);
-    }
-    return this;
-  }
-
-  public RestApi ifNoneMatch() {
-    return ifNoneMatch("*");
-  }
-
-  public RestApi ifNoneMatch(String etag) {
-    ifNoneMatch = etag;
-    return this;
-  }
-
-  public RestApi background() {
-    background = true;
-    return this;
-  }
-
-  public String url() {
-    return url.toString();
-  }
-
-  public <T extends JavaScriptObject> void get(AsyncCallback<T> cb) {
-    get(wrap(cb));
-  }
-
-  public <T extends JavaScriptObject> void get(HttpCallback<T> cb) {
-    send(GET, cb);
-  }
-
-  public <T extends JavaScriptObject> void delete(AsyncCallback<T> cb) {
-    delete(wrap(cb));
-  }
-
-  public <T extends JavaScriptObject> void delete(HttpCallback<T> cb) {
-    send(DELETE, cb);
-  }
-
-  private <T extends JavaScriptObject> void send(Method method, HttpCallback<T> cb) {
-    HttpImpl<T> httpCallback = new HttpImpl<>(background, cb);
-    try {
-      if (!background) {
-        RpcStatus.INSTANCE.onRpcStart();
-      }
-      request(method).sendRequest(null, httpCallback);
-    } catch (RequestException e) {
-      httpCallback.onError(null, e);
-    }
-  }
-
-  public <T extends JavaScriptObject> void post(JavaScriptObject content, AsyncCallback<T> cb) {
-    post(content, wrap(cb));
-  }
-
-  public <T extends JavaScriptObject> void post(JavaScriptObject content, HttpCallback<T> cb) {
-    sendJSON(POST, content, cb);
-  }
-
-  public <T extends JavaScriptObject> void post(String content, AsyncCallback<T> cb) {
-    post(content, wrap(cb));
-  }
-
-  public <T extends JavaScriptObject> void post(String content, HttpCallback<T> cb) {
-    sendText(POST, content, cb);
-  }
-
-  public <T extends JavaScriptObject> void put(AsyncCallback<T> cb) {
-    put(wrap(cb));
-  }
-
-  public <T extends JavaScriptObject> void put(HttpCallback<T> cb) {
-    send(PUT, cb);
-  }
-
-  public <T extends JavaScriptObject> void put(String content, AsyncCallback<T> cb) {
-    put(content, wrap(cb));
-  }
-
-  public <T extends JavaScriptObject> void put(String content, HttpCallback<T> cb) {
-    sendText(PUT, content, cb);
-  }
-
-  public <T extends JavaScriptObject> void put(JavaScriptObject content, AsyncCallback<T> cb) {
-    put(content, wrap(cb));
-  }
-
-  public <T extends JavaScriptObject> void put(JavaScriptObject content, HttpCallback<T> cb) {
-    sendJSON(PUT, content, cb);
-  }
-
-  private <T extends JavaScriptObject> void sendJSON(
-      Method method, JavaScriptObject content, HttpCallback<T> cb) {
-    HttpImpl<T> httpCallback = new HttpImpl<>(background, cb);
-    try {
-      if (!background) {
-        RpcStatus.INSTANCE.onRpcStart();
-      }
-      RequestBuilder req = request(method);
-      req.setHeader("Content-Type", JSON_UTF8);
-      req.sendRequest(str(content), httpCallback);
-    } catch (RequestException e) {
-      httpCallback.onError(null, e);
-    }
-  }
-
-  private static native String str(JavaScriptObject jso) /*-{ return JSON.stringify(jso) }-*/;
-
-  private <T extends JavaScriptObject> void sendText(
-      Method method, String body, HttpCallback<T> cb) {
-    HttpImpl<T> httpCallback = new HttpImpl<>(background, cb);
-    try {
-      if (!background) {
-        RpcStatus.INSTANCE.onRpcStart();
-      }
-      RequestBuilder req = request(method);
-      req.setHeader("Content-Type", TEXT_UTF8);
-      req.sendRequest(body, httpCallback);
-    } catch (RequestException e) {
-      httpCallback.onError(null, e);
-    }
-  }
-
-  private RequestBuilder request(Method method) {
-    RequestBuilder req = new RequestBuilder(method, url());
-    if (ifNoneMatch != null) {
-      req.setHeader("If-None-Match", ifNoneMatch);
-    }
-    req.setHeader("Accept", JSON_TYPE);
-    if (Gerrit.getXGerritAuth() != null) {
-      req.setHeader(HostPageData.XSRF_HEADER_NAME, Gerrit.getXGerritAuth());
-    }
-    return req;
-  }
-
-  private static boolean isJsonBody(Response res) {
-    return isContentType(res, JSON_TYPE);
-  }
-
-  private static boolean isTextBody(Response res) {
-    return isContentType(res, TEXT_TYPE);
-  }
-
-  private static boolean isJsonEncoded(Response res) {
-    return "json".equals(res.getHeader("X-FYI-Content-Encoding"));
-  }
-
-  private static boolean isContentType(Response res, String want) {
-    String type = res.getHeader("Content-Type");
-    return type != null && want.equals(simpleType(type));
-  }
-
-  private static String simpleType(String type) {
-    int semi = type.indexOf(';');
-    if (semi >= 0) {
-      return type.substring(0, semi).trim();
-    }
-    return type;
-  }
-
-  private static JSONValue parseJson(Response res) throws JSONException {
-    String json = trimJsonMagic(res.getText());
-    if (json.isEmpty()) {
-      throw new JSONException("response was empty");
-    }
-    return JSONParser.parseStrict(json);
-  }
-
-  private static String trimJsonMagic(String json) {
-    if (json.startsWith(JSON_MAGIC)) {
-      json = json.substring(JSON_MAGIC.length());
-    }
-    return json;
-  }
-
-  @SuppressWarnings("unchecked")
-  private static <T extends JavaScriptObject> T cast(JSONValue val) {
-    if (val.isObject() != null) {
-      return (T) val.isObject().getJavaScriptObject();
-    } else if (val.isArray() != null) {
-      return (T) val.isArray().getJavaScriptObject();
-    } else if (val.isString() != null) {
-      return (T) NativeString.wrap(val.isString().stringValue());
-    } else if (val.isNull() != null) {
-      return null;
-    } else {
-      throw new JSONException("unsupported JSON type");
-    }
-  }
-
-  private static <T extends JavaScriptObject> HttpCallback<T> wrap(AsyncCallback<T> cb) {
-    return new HttpCallback<T>() {
-      @Override
-      public void onSuccess(HttpResponse<T> r) {
-        cb.onSuccess(r.getResult());
-      }
-
-      @Override
-      public void onFailure(Throwable e) {
-        cb.onFailure(e);
-      }
-    };
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RpcConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RpcConstants.java
deleted file mode 100644
index 56d536d..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RpcConstants.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.rpc;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.i18n.client.Constants;
-
-public interface RpcConstants extends Constants {
-  RpcConstants C = GWT.create(RpcConstants.class);
-
-  String errorServerUnavailable();
-
-  String errorRemoteJsonException();
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RpcConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RpcConstants.properties
deleted file mode 100644
index e8695b1..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RpcConstants.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-errorServerUnavailable = Server Unavailable
-errorRemoteJsonException = Server Error
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/ScreenLoadCallback.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/ScreenLoadCallback.java
deleted file mode 100644
index 3aae04a..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/ScreenLoadCallback.java
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.rpc;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.NotFoundScreen;
-import com.google.gerrit.client.NotSignedInDialog;
-import com.google.gerrit.client.ui.Screen;
-import com.google.gerrit.common.errors.NoSuchEntityException;
-
-/** Callback switching {@link NoSuchEntityException} to {@link NotFoundScreen} */
-public abstract class ScreenLoadCallback<T> extends GerritCallback<T> {
-  private final Screen screen;
-
-  public ScreenLoadCallback(Screen s) {
-    screen = s;
-  }
-
-  @Override
-  public final void onSuccess(T result) {
-    if (screen.isAttached()) {
-      preDisplay(result);
-      screen.display();
-      postDisplay();
-    }
-  }
-
-  protected abstract void preDisplay(T result);
-
-  protected void postDisplay() {}
-
-  @Override
-  public void onFailure(Throwable caught) {
-    if (isSigninFailure(caught)) {
-      new NotSignedInDialog().center();
-    } else if (isNoSuchEntity(caught)) {
-      Gerrit.display(screen.getToken(), new NotFoundScreen());
-    } else {
-      super.onFailure(caught);
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountGroupSuggestOracle.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountGroupSuggestOracle.java
deleted file mode 100644
index bdebd68..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountGroupSuggestOracle.java
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.groups.GroupMap;
-import com.google.gerrit.client.info.GroupInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.user.client.ui.SuggestOracle;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-
-/** Suggestion Oracle for AccountGroup entities. */
-public class AccountGroupSuggestOracle extends SuggestAfterTypingNCharsOracle {
-  private Map<String, AccountGroup.UUID> priorResults = new HashMap<>();
-
-  private Project.NameKey projectName;
-
-  @Override
-  public void _onRequestSuggestions(Request req, Callback callback) {
-    GroupMap.suggestAccountGroupForProject(
-        projectName == null ? null : projectName.get(),
-        req.getQuery(),
-        req.getLimit(),
-        new GerritCallback<GroupMap>() {
-          @Override
-          public void onSuccess(GroupMap result) {
-            priorResults.clear();
-            ArrayList<AccountGroupSuggestion> r = new ArrayList<>(result.size());
-            for (GroupInfo group : Natives.asList(result.values())) {
-              r.add(new AccountGroupSuggestion(group));
-              priorResults.put(group.name(), group.getGroupUUID());
-            }
-            callback.onSuggestionsReady(req, new Response(r));
-          }
-        });
-  }
-
-  public void setProject(Project.NameKey projectName) {
-    this.projectName = projectName;
-  }
-
-  private static class AccountGroupSuggestion implements SuggestOracle.Suggestion {
-    private final GroupInfo info;
-
-    AccountGroupSuggestion(GroupInfo k) {
-      info = k;
-    }
-
-    @Override
-    public String getDisplayString() {
-      return info.name();
-    }
-
-    @Override
-    public String getReplacementString() {
-      return info.name();
-    }
-  }
-
-  /** @return the group UUID, or null if it cannot be found. */
-  public AccountGroup.UUID getUUID(String name) {
-    return priorResults.get(name);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountLinkPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountLinkPanel.java
deleted file mode 100644
index c44f357..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountLinkPanel.java
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.AvatarImage;
-import com.google.gerrit.client.FormatUtil;
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gwt.user.client.ui.FlowPanel;
-import java.util.function.Function;
-
-/** Link to any user's account dashboard. */
-public class AccountLinkPanel extends FlowPanel {
-  public static AccountLinkPanel create(AccountInfo ai) {
-    return withStatus(ai, Change.Status.NEW);
-  }
-
-  public static AccountLinkPanel withStatus(AccountInfo ai, Change.Status status) {
-    return new AccountLinkPanel(ai, name -> PageLinks.toAccountQuery(name, status));
-  }
-
-  public static AccountLinkPanel forAssignee(AccountInfo ai) {
-    return new AccountLinkPanel(ai, PageLinks::toAssigneeQuery);
-  }
-
-  private AccountLinkPanel(AccountInfo ai, Function<String, String> nameToQuery) {
-    addStyleName(Gerrit.RESOURCES.css().accountLinkPanel());
-
-    InlineHyperlink l =
-        new InlineHyperlink(FormatUtil.name(ai), nameToQuery.apply(name(ai))) {
-          @Override
-          public void go() {
-            Gerrit.display(getTargetHistoryToken());
-          }
-        };
-    l.setTitle(FormatUtil.nameEmail(ai));
-
-    add(new AvatarImage(ai));
-    add(l);
-  }
-
-  private static String name(AccountInfo ai) {
-    if (ai.email() != null) {
-      return ai.email();
-    } else if (ai.name() != null) {
-      return ai.name();
-    } else if (ai._accountId() != 0) {
-      return "" + ai._accountId();
-    } else {
-      return "";
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountScreen.java
deleted file mode 100644
index 59ff9fe3..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountScreen.java
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-/** A screen that requires the user to be signed-into their account. */
-public abstract class AccountScreen extends Screen {
-  protected AccountScreen() {
-    setRequiresSignIn(true);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountSuggestOracle.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountSuggestOracle.java
deleted file mode 100644
index 5038ad9..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountSuggestOracle.java
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.FormatUtil;
-import com.google.gerrit.client.account.AccountApi;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.user.client.ui.SuggestOracle;
-import java.util.ArrayList;
-import java.util.List;
-
-/** Suggestion Oracle for Account entities. */
-public class AccountSuggestOracle extends SuggestAfterTypingNCharsOracle {
-  @Override
-  public void _onRequestSuggestions(Request req, Callback cb) {
-    AccountApi.suggest(
-        req.getQuery(),
-        req.getLimit(),
-        new GerritCallback<JsArray<AccountInfo>>() {
-          @Override
-          public void onSuccess(JsArray<AccountInfo> in) {
-            List<AccountSuggestion> r = new ArrayList<>(in.length());
-            for (AccountInfo p : Natives.asList(in)) {
-              r.add(new AccountSuggestion(p, req.getQuery()));
-            }
-            cb.onSuggestionsReady(req, new Response(r));
-          }
-        });
-  }
-
-  public static class AccountSuggestion implements SuggestOracle.Suggestion {
-    private final String suggestion;
-
-    public AccountSuggestion(AccountInfo info, String query) {
-      this.suggestion = format(info, query);
-    }
-
-    @Override
-    public String getDisplayString() {
-      return suggestion;
-    }
-
-    @Override
-    public String getReplacementString() {
-      return suggestion;
-    }
-
-    public static String format(AccountInfo info, String query) {
-      String s = FormatUtil.nameEmail(info);
-      if (query != null && !containsQuery(s, query) && info.secondaryEmails() != null) {
-        for (String email : Natives.asList(info.secondaryEmails())) {
-          AccountInfo info2 =
-              AccountInfo.create(info._accountId(), info.name(), email, info.username());
-          String s2 = FormatUtil.nameEmail(info2);
-          if (containsQuery(s2, query)) {
-            s = s2;
-            break;
-          }
-        }
-      }
-      return s;
-    }
-
-    private static boolean containsQuery(String s, String query) {
-      for (String qterm : query.split("\\s+")) {
-        if (!s.toLowerCase().contains(qterm.toLowerCase())) {
-          return false;
-        }
-      }
-      return true;
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AddMemberBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AddMemberBox.java
deleted file mode 100644
index a1d2229..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AddMemberBox.java
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.logical.shared.SelectionEvent;
-import com.google.gwt.event.logical.shared.SelectionHandler;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.SuggestOracle;
-
-public class AddMemberBox extends Composite {
-  private final FlowPanel addPanel;
-  private final Button addMember;
-  private final RemoteSuggestBox suggestBox;
-
-  public AddMemberBox(final String buttonLabel, String hint, SuggestOracle suggestOracle) {
-    addPanel = new FlowPanel();
-    addMember = new Button(buttonLabel);
-
-    suggestBox = new RemoteSuggestBox(suggestOracle);
-    suggestBox.setStyleName(Gerrit.RESOURCES.css().addMemberTextBox());
-    suggestBox.setVisibleLength(50);
-    suggestBox.setHintText(hint);
-    suggestBox.addSelectionHandler(
-        new SelectionHandler<String>() {
-          @Override
-          public void onSelection(SelectionEvent<String> event) {
-            addMember.fireEvent(new ClickEvent() {});
-          }
-        });
-
-    addPanel.add(suggestBox);
-    addPanel.add(addMember);
-
-    initWidget(addPanel);
-  }
-
-  public void addClickHandler(ClickHandler handler) {
-    addMember.addClickHandler(handler);
-  }
-
-  public String getText() {
-    return suggestBox.getText();
-  }
-
-  public void setEnabled(boolean enabled) {
-    addMember.setEnabled(enabled);
-    suggestBox.setEnabled(enabled);
-  }
-
-  public void setText(String text) {
-    suggestBox.setText(text);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/BranchLink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/BranchLink.java
deleted file mode 100644
index 6e05f83..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/BranchLink.java
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.QueryScreen;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.client.RefNames;
-
-/** Link to the open changes of a project. */
-public class BranchLink extends InlineHyperlink {
-  private final String query;
-
-  public BranchLink(Project.NameKey project, Change.Status status, String branch, String topic) {
-    this(text(branch, topic), query(project, status, branch, topic));
-  }
-
-  public BranchLink(
-      String text, Project.NameKey project, Change.Status status, String branch, String topic) {
-    this(text, query(project, status, branch, topic));
-  }
-
-  private BranchLink(String text, String query) {
-    super(text, PageLinks.toChangeQuery(query));
-    this.query = query;
-  }
-
-  @Override
-  public void go() {
-    Gerrit.display(getTargetHistoryToken(), createScreen());
-  }
-
-  private Screen createScreen() {
-    return QueryScreen.forQuery(query);
-  }
-
-  private static String text(String branch, String topic) {
-    if (topic != null && !topic.isEmpty()) {
-      return branch + " (" + topic + ")";
-    }
-    return branch;
-  }
-
-  public static String query(
-      Project.NameKey project, Change.Status status, String branch, String topic) {
-    String query = PageLinks.projectQuery(project, status);
-
-    if (branch.startsWith(RefNames.REFS)) {
-      if (branch.startsWith(RefNames.REFS_HEADS)) {
-        query +=
-            " "
-                + PageLinks.op(
-                    "branch", //
-                    branch.substring(RefNames.REFS_HEADS.length()));
-      } else {
-        query += " " + PageLinks.op("ref", branch);
-      }
-    } else {
-      // Assume it was clipped already by the caller.  This
-      // happens for example inside of the ChangeInfo object.
-      //
-      query += " " + PageLinks.op("branch", branch);
-    }
-
-    if (topic != null && !topic.isEmpty()) {
-      query += " " + PageLinks.op("topic", topic);
-    }
-
-    return query;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ChangeLink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ChangeLink.java
deleted file mode 100644
index b54d752..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ChangeLink.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.GWT;
-
-public class ChangeLink extends InlineHyperlink {
-  public static String permalink(Change.Id c) {
-    return GWT.getHostPageBaseURL() + c.get();
-  }
-
-  protected Change.Id cid;
-
-  public ChangeLink(Project.NameKey project, Change.Id c, String text) {
-    super(text, PageLinks.toChange(project, c));
-    getElement().setPropertyString("href", permalink(c));
-    cid = c;
-  }
-
-  @Override
-  public void go() {
-    Gerrit.display(getTargetHistoryToken());
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CherryPickDialog.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CherryPickDialog.java
deleted file mode 100644
index 0a0c14a..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CherryPickDialog.java
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.Util;
-import com.google.gerrit.client.projects.BranchInfo;
-import com.google.gerrit.client.projects.ProjectApi;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.SuggestBox;
-import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-import com.google.gwtexpui.safehtml.client.HighlightSuggestOracle;
-import java.util.ArrayList;
-import java.util.List;
-
-public abstract class CherryPickDialog extends TextAreaActionDialog {
-  private SuggestBox newBranch;
-  private List<BranchInfo> branches;
-
-  public CherryPickDialog(Project.NameKey project) {
-    super(Util.C.cherryPickTitle(), Util.C.cherryPickCommitMessage());
-    ProjectApi.getBranches(
-        project,
-        new GerritCallback<JsArray<BranchInfo>>() {
-          @Override
-          public void onSuccess(JsArray<BranchInfo> result) {
-            branches = Natives.asList(result);
-          }
-        });
-
-    newBranch =
-        new SuggestBox(
-            new HighlightSuggestOracle() {
-              @Override
-              protected void onRequestSuggestions(Request request, Callback done) {
-                List<BranchSuggestion> suggestions = new ArrayList<>();
-                for (BranchInfo b : branches) {
-                  if (b.ref().contains(request.getQuery())) {
-                    suggestions.add(new BranchSuggestion(b));
-                  }
-                }
-                done.onSuggestionsReady(request, new Response(suggestions));
-              }
-            });
-
-    newBranch.setWidth("100%");
-    newBranch.getElement().getStyle().setProperty("boxSizing", "border-box");
-    message.setCharacterWidth(70);
-
-    final FlowPanel mwrap = new FlowPanel();
-    mwrap.setStyleName(Gerrit.RESOURCES.css().commentedActionMessage());
-    mwrap.add(newBranch);
-
-    panel.insert(mwrap, 0);
-    panel.insert(new SmallHeading(Util.C.headingCherryPickBranch()), 0);
-  }
-
-  @Override
-  public void center() {
-    super.center();
-    GlobalKey.dialog(this);
-    newBranch.setFocus(true);
-  }
-
-  public String getDestinationBranch() {
-    return newBranch.getText();
-  }
-
-  static class BranchSuggestion implements Suggestion {
-    private BranchInfo branch;
-
-    BranchSuggestion(BranchInfo branch) {
-      this.branch = branch;
-    }
-
-    @Override
-    public String getDisplayString() {
-      final String refsHeads = "refs/heads/";
-      if (branch.ref().startsWith(refsHeads)) {
-        return branch.ref().substring(refsHeads.length());
-      }
-      return branch.ref();
-    }
-
-    @Override
-    public String getReplacementString() {
-      return branch.getShortName();
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommandMenuItem.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommandMenuItem.java
deleted file mode 100644
index c5ee34f..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommandMenuItem.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gwt.aria.client.Roles;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.ui.Anchor;
-
-public class CommandMenuItem extends Anchor implements ClickHandler {
-  private final Command command;
-
-  public CommandMenuItem(String text, Command cmd) {
-    super(text);
-    setStyleName(Gerrit.RESOURCES.css().menuItem());
-    Roles.getMenuitemRole().set(getElement());
-    addClickHandler(this);
-    command = cmd;
-  }
-
-  @Override
-  public void onClick(ClickEvent event) {
-    setFocus(false);
-    command.execute();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommentLinkProcessor.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommentLinkProcessor.java
deleted file mode 100644
index 1753ade..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommentLinkProcessor.java
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gwtexpui.safehtml.client.FindReplace;
-import com.google.gwtexpui.safehtml.client.SafeHtml;
-import com.google.gwtjsonrpc.common.AsyncCallback;
-import com.google.gwtjsonrpc.common.VoidResult;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-public class CommentLinkProcessor {
-  private List<FindReplace> commentLinks;
-
-  public CommentLinkProcessor(List<FindReplace> commentLinks) {
-    this.commentLinks = commentLinks;
-  }
-
-  public SafeHtml apply(SafeHtml buf) {
-    try {
-      return buf.replaceAll(commentLinks);
-    } catch (RuntimeException err) {
-      // One or more of the patterns isn't valid on this browser.
-      // Try to filter the list down and remove the invalid ones.
-
-      List<FindReplace> safe = new ArrayList<>(commentLinks.size());
-
-      List<PatternError> bad = new ArrayList<>();
-      for (FindReplace r : commentLinks) {
-        try {
-          buf.replaceAll(Collections.singletonList(r));
-          safe.add(r);
-        } catch (RuntimeException why) {
-          bad.add(new PatternError(r, why.getMessage()));
-        }
-      }
-
-      if (!bad.isEmpty()) {
-        StringBuilder msg = new StringBuilder();
-        msg.append("Invalid commentlink pattern(s):");
-        for (PatternError e : bad) {
-          msg.append("\n");
-          msg.append("\"");
-          msg.append(e.pattern.pattern().getSource());
-          msg.append("\": ");
-          msg.append(e.errorMessage);
-        }
-        Gerrit.SYSTEM_SVC.clientError(
-            msg.toString(),
-            new AsyncCallback<VoidResult>() {
-              @Override
-              public void onFailure(Throwable caught) {}
-
-              @Override
-              public void onSuccess(VoidResult result) {}
-            });
-      }
-
-      try {
-        commentLinks = safe;
-        return buf.replaceAll(safe);
-      } catch (RuntimeException err2) {
-        // To heck with it. The patterns passed individually above but
-        // failed as a group? Just render without.
-        //
-        commentLinks = null;
-        return buf;
-      }
-    }
-  }
-
-  private static class PatternError {
-    FindReplace pattern;
-    String errorMessage;
-
-    PatternError(FindReplace r, String w) {
-      pattern = r;
-      errorMessage = w;
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommentedActionDialog.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommentedActionDialog.java
deleted file mode 100644
index b68f329..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommentedActionDialog.java
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.FocusWidget;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-import com.google.gwtexpui.user.client.AutoCenterDialogBox;
-
-public abstract class CommentedActionDialog extends AutoCenterDialogBox
-    implements CloseHandler<PopupPanel> {
-  protected final FlowPanel panel;
-  protected final Button sendButton;
-  protected final Button cancelButton;
-  protected final FlowPanel buttonPanel;
-  protected final FlowPanel contentPanel;
-  protected FocusWidget focusOn;
-
-  protected boolean sent;
-
-  public CommentedActionDialog(String title, String heading) {
-    super(/* auto hide */ false, /* modal */ true);
-    setGlassEnabled(true);
-    setText(title);
-
-    addStyleName(Gerrit.RESOURCES.css().commentedActionDialog());
-
-    sendButton = new Button(Util.C.commentedActionButtonSend());
-    sendButton.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            enableButtons(false);
-            onSend();
-          }
-        });
-
-    cancelButton = new Button(Util.C.commentedActionButtonCancel());
-    cancelButton.getElement().getStyle().setProperty("float", "right");
-    cancelButton.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            hide();
-          }
-        });
-
-    contentPanel = new FlowPanel();
-    contentPanel.setStyleName(Gerrit.RESOURCES.css().commentedActionMessage());
-
-    buttonPanel = new FlowPanel();
-    buttonPanel.add(sendButton);
-    buttonPanel.add(cancelButton);
-    buttonPanel.getElement().getStyle().setProperty("marginTop", "4px");
-
-    panel = new FlowPanel();
-    if (heading != null) {
-      panel.add(new SmallHeading(heading));
-    }
-    panel.add(contentPanel);
-    panel.add(buttonPanel);
-    add(panel);
-
-    addCloseHandler(this);
-  }
-
-  public void setFocusOn(FocusWidget focusWidget) {
-    focusOn = focusWidget;
-  }
-
-  public void enableButtons(boolean enable) {
-    sendButton.setEnabled(enable);
-    cancelButton.setEnabled(enable);
-  }
-
-  @Override
-  public void center() {
-    super.center();
-    GlobalKey.dialog(this);
-    if (focusOn != null) {
-      focusOn.setFocus(true);
-    }
-  }
-
-  @Override
-  public void onClose(CloseEvent<PopupPanel> event) {
-    sent = false;
-  }
-
-  public abstract void onSend();
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ComplexDisclosurePanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ComplexDisclosurePanel.java
deleted file mode 100644
index c0b662a..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ComplexDisclosurePanel.java
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.event.logical.shared.HasCloseHandlers;
-import com.google.gwt.event.logical.shared.HasOpenHandlers;
-import com.google.gwt.event.logical.shared.OpenHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.ui.ComplexPanel;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.DisclosurePanel;
-import com.google.gwt.user.client.ui.Panel;
-import com.google.gwt.user.client.ui.Widget;
-
-public class ComplexDisclosurePanel extends Composite
-    implements HasOpenHandlers<DisclosurePanel>, HasCloseHandlers<DisclosurePanel> {
-  private final DisclosurePanel main;
-  private final Panel header;
-
-  public ComplexDisclosurePanel(String text, boolean isOpen) {
-    // Ick. GWT's DisclosurePanel won't let us subclass it, or do any
-    // other modification of its header. We're stuck with injecting
-    // into the DOM directly.
-    //
-    main = new DisclosurePanel(text);
-    main.setOpen(isOpen);
-    final Element headerParent;
-    {
-      final Element table = main.getElement();
-      final Element tbody = DOM.getFirstChild(table);
-      final Element tr1 = DOM.getChild(tbody, 0);
-      final Element tr2 = DOM.getChild(tbody, 1);
-
-      DOM.getChild(tr1, 0).setPropertyString("width", "20px");
-      DOM.getChild(tr2, 0).setPropertyInt("colSpan", 2);
-      headerParent = tr1;
-    }
-
-    header =
-        new ComplexPanel() {
-          {
-            setElement((Element) (DOM.createTD()));
-            getElement().setInnerHTML("&nbsp;");
-          }
-
-          @Override
-          public void add(Widget w) {
-            add(w, (Element) getElement());
-          }
-        };
-
-    initWidget(
-        new ComplexPanel() {
-          {
-            final DisclosurePanel main = ComplexDisclosurePanel.this.main;
-            setElement((Element) (main.getElement()));
-            getChildren().add(main);
-            adopt(main);
-
-            add(ComplexDisclosurePanel.this.header, headerParent);
-          }
-        });
-  }
-
-  public Panel getHeader() {
-    return header;
-  }
-
-  public void setContent(Widget w) {
-    main.setContent(w);
-  }
-
-  public Widget getContent() {
-    return main.getContent();
-  }
-
-  @Override
-  public HandlerRegistration addOpenHandler(OpenHandler<DisclosurePanel> h) {
-    return main.addOpenHandler(h);
-  }
-
-  @Override
-  public HandlerRegistration addCloseHandler(CloseHandler<DisclosurePanel> h) {
-    return main.addCloseHandler(h);
-  }
-
-  /** @return true if the panel's content is visible. */
-  public boolean isOpen() {
-    return main.isOpen();
-  }
-
-  /**
-   * Changes the visible state of this panel's content.
-   *
-   * @param isOpen {@code true} to open, {@code false} to close
-   */
-  public void setOpen(boolean isOpen) {
-    main.setOpen(isOpen);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CreateChangeDialog.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CreateChangeDialog.java
deleted file mode 100644
index 2d00281..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CreateChangeDialog.java
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.projects.BranchInfo;
-import com.google.gerrit.client.projects.ProjectApi;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.SuggestBox;
-import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
-import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-import com.google.gwtexpui.safehtml.client.HighlightSuggestOracle;
-import java.util.ArrayList;
-import java.util.List;
-
-public abstract class CreateChangeDialog extends TextAreaActionDialog {
-  private SuggestBox newChange;
-  private List<BranchInfo> branches;
-  private TextBox topic;
-
-  public CreateChangeDialog(Project.NameKey project) {
-    super(Util.C.dialogCreateChangeTitle(), Util.C.dialogCreateChangeHeading());
-    ProjectApi.getBranches(
-        project,
-        new GerritCallback<JsArray<BranchInfo>>() {
-          @Override
-          public void onSuccess(JsArray<BranchInfo> result) {
-            branches = Natives.asList(result);
-          }
-        });
-
-    topic = new TextBox();
-    topic.setWidth("100%");
-    topic.getElement().getStyle().setProperty("boxSizing", "border-box");
-    FlowPanel newTopicPanel = new FlowPanel();
-    newTopicPanel.setStyleName(Gerrit.RESOURCES.css().commentedActionMessage());
-    newTopicPanel.add(topic);
-    panel.insert(newTopicPanel, 0);
-    panel.insert(new SmallHeading(Util.C.newChangeTopicSuggestion()), 0);
-
-    newChange =
-        new SuggestBox(
-            new HighlightSuggestOracle() {
-              @Override
-              protected void onRequestSuggestions(Request request, Callback done) {
-                List<BranchSuggestion> suggestions = new ArrayList<>();
-                for (BranchInfo b : branches) {
-                  if (b.ref().contains(request.getQuery())) {
-                    suggestions.add(new BranchSuggestion(b));
-                  }
-                }
-                done.onSuggestionsReady(request, new Response(suggestions));
-              }
-            });
-
-    newChange.setWidth("100%");
-    newChange.getElement().getStyle().setProperty("boxSizing", "border-box");
-    FlowPanel newChangePanel = new FlowPanel();
-    newChangePanel.setStyleName(Gerrit.RESOURCES.css().commentedActionMessage());
-    newChangePanel.add(newChange);
-    panel.insert(newChangePanel, 0);
-    panel.insert(new SmallHeading(Util.C.newChangeBranchSuggestion()), 0);
-
-    message.setCharacterWidth(70);
-  }
-
-  @Override
-  public void center() {
-    super.center();
-    GlobalKey.dialog(this);
-    newChange.setFocus(true);
-  }
-
-  public String getDestinationBranch() {
-    return newChange.getText();
-  }
-
-  public String getDestinationTopic() {
-    return topic.getText();
-  }
-
-  static class BranchSuggestion implements Suggestion {
-    private BranchInfo branch;
-
-    BranchSuggestion(BranchInfo branch) {
-      this.branch = branch;
-    }
-
-    @Override
-    public String getDisplayString() {
-      return branch.getShortName();
-    }
-
-    @Override
-    public String getReplacementString() {
-      return branch.getShortName();
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FancyFlexTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FancyFlexTable.java
deleted file mode 100644
index 045e0ae..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FancyFlexTable.java
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Document;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlexTable;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.safehtml.client.SafeHtml;
-import java.util.Comparator;
-import java.util.Iterator;
-
-public abstract class FancyFlexTable<RowItem> extends Composite {
-  private static final FancyFlexTableImpl impl = GWT.create(FancyFlexTableImpl.class);
-
-  protected static final int C_ARROW = 0;
-
-  protected final MyFlexTable table;
-
-  protected FancyFlexTable() {
-    table = createFlexTable();
-    table.addStyleName(Gerrit.RESOURCES.css().changeTable());
-    table.setWidth("100%");
-    initWidget(table);
-
-    table.setText(0, C_ARROW, "");
-    table.getCellFormatter().addStyleName(0, C_ARROW, Gerrit.RESOURCES.css().iconHeader());
-  }
-
-  protected MyFlexTable createFlexTable() {
-    return new MyFlexTable();
-  }
-
-  protected RowItem getRowItem(int row) {
-    return FancyFlexTable.<RowItem>getRowItem(table.getCellFormatter().getElement(row, 0));
-  }
-
-  protected void setRowItem(int row, RowItem item) {
-    setRowItem(table.getCellFormatter().getElement(row, 0), item);
-  }
-
-  /**
-   * Finds an item in the table.
-   *
-   * @param comparator comparator by which the items in the table are sorted
-   * @param item the item that should be found
-   * @return if the item is found the number of the row that contains the item; if the item is not
-   *     found {@code -1}
-   */
-  protected int findRowItem(Comparator<RowItem> comparator, RowItem item) {
-    int row = lookupRowItem(comparator, item);
-    if (row < table.getRowCount() && comparator.compare(item, getRowItem(row)) == 0) {
-      return row;
-    }
-    return -1;
-  }
-
-  /**
-   * Finds the number of the row where a new item should be inserted into the table.
-   *
-   * @param comparator comparator by which the items in the table are sorted
-   * @param item the new item that should be inserted
-   * @return if the item is not yet contained in the table, the number of the row where the new item
-   *     should be inserted; if the item is already contained in the table {@code -1}
-   */
-  protected int getInsertRow(Comparator<RowItem> comparator, RowItem item) {
-    int row = lookupRowItem(comparator, item);
-    if (row >= table.getRowCount() || comparator.compare(item, getRowItem(row)) != 0) {
-      return row;
-    }
-    return -1;
-  }
-
-  /**
-   * Makes a binary search for the given row item over the table.
-   *
-   * @param comparator comparator by which the items in the table are sorted
-   * @param item the item that should be looked up
-   * @return if the item is found the number of the row that contains the item; if the item is not
-   *     found the number of the row where the item should be inserted according to the given
-   *     comparator.
-   */
-  private int lookupRowItem(Comparator<RowItem> comparator, RowItem item) {
-    int left = 1;
-    int right = table.getRowCount() - 1;
-    while (left <= right) {
-      int middle = (left + right) >>> 1; // (left+right)/2
-      RowItem i = getRowItem(middle);
-      int cmp = comparator.compare(i, item);
-
-      if (cmp < 0) {
-        left = middle + 1;
-      } else if (cmp > 0) {
-        right = middle - 1;
-      } else {
-        // item is already contained in the table
-        return middle;
-      }
-    }
-    return left;
-  }
-
-  protected void resetHtml(SafeHtml body) {
-    for (Iterator<Widget> i = table.iterator(); i.hasNext(); ) {
-      i.next();
-      i.remove();
-    }
-    impl.resetHtml(table, body);
-  }
-
-  protected void scrollIntoView(int topRow, int endRow) {
-    final CellFormatter fmt = table.getCellFormatter();
-    final Element top = fmt.getElement(topRow, C_ARROW).getParentElement();
-    final Element end = fmt.getElement(endRow, C_ARROW).getParentElement();
-
-    final int rTop = top.getAbsoluteTop();
-    final int rEnd = end.getAbsoluteTop() + end.getOffsetHeight();
-    final int rHeight = rEnd - rTop;
-
-    final int sTop = Document.get().getScrollTop();
-    final int sHeight = Document.get().getClientHeight();
-    final int sEnd = sTop + sHeight;
-
-    final int nTop;
-    if (sHeight <= rHeight) {
-      // The region is larger than the visible area, make the top
-      // exactly the top of the region, its the most visible area.
-      //
-      nTop = rTop;
-    } else if (sTop <= rTop && rTop <= sEnd) {
-      // At least part of the region is already visible.
-      //
-      if (rEnd <= sEnd) {
-        // ... actually its all visible. Don't scroll.
-        //
-        return;
-      }
-
-      // Move only enough to make the end visible.
-      //
-      nTop = sTop + (rHeight - (sEnd - rTop));
-    } else {
-      // None of the region is visible. Make it visible.
-      //
-      nTop = rTop;
-    }
-    Document.get().setScrollTop(nTop);
-  }
-
-  protected void applyDataRowStyle(int newRow) {
-    table.getCellFormatter().addStyleName(newRow, C_ARROW, Gerrit.RESOURCES.css().iconCell());
-    table.getCellFormatter().addStyleName(newRow, C_ARROW, Gerrit.RESOURCES.css().leftMostCell());
-  }
-
-  /**
-   * Get the td element that contains another element.
-   *
-   * @param target the child element whose parent td is required.
-   * @return the td containing element {@code target}; null if {@code target} is not a member of
-   *     this table.
-   */
-  protected Element getParentCell(Element target) {
-    final Element body = FancyFlexTableImpl.getBodyElement(table);
-    for (Element td = target; td != null && td != body; td = DOM.getParent(td)) {
-      // If it's a TD, it might be the one we're looking for.
-      if ("td".equalsIgnoreCase(td.getTagName())) {
-        // Make sure it's directly a part of this table.
-        Element tr = DOM.getParent(td);
-        if (DOM.getParent(tr) == body) {
-          return td;
-        }
-      }
-    }
-    return null;
-  }
-
-  /** @return the row of the child element; -1 if the child is not in the table. */
-  protected int rowOf(Element target) {
-    final Element td = getParentCell(target);
-    if (td == null) {
-      return -1;
-    }
-    final Element tr = DOM.getParent(td);
-    final Element body = DOM.getParent(tr);
-    return DOM.getChildIndex(body, tr);
-  }
-
-  /** @return the cell of the child element; -1 if the child is not in the table. */
-  protected int columnOf(Element target) {
-    final Element td = getParentCell(target);
-    if (td == null) {
-      return -1;
-    }
-    final Element tr = DOM.getParent(td);
-    return DOM.getChildIndex(tr, td);
-  }
-
-  protected static class MyFlexTable extends FlexTable {}
-
-  private static native <ItemType> void setRowItem(Element td, ItemType c)
-      /*-{ td['__gerritRowItem'] = c; }-*/ ;
-
-  private static native <ItemType> ItemType getRowItem(Element td)
-      /*-{ return td['__gerritRowItem']; }-*/ ;
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FancyFlexTableImpl.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FancyFlexTableImpl.java
deleted file mode 100644
index a3a2a7a..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FancyFlexTableImpl.java
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.user.client.ui.FlexTable;
-import com.google.gwt.user.client.ui.HTMLTable;
-import com.google.gwtexpui.safehtml.client.SafeHtml;
-
-public class FancyFlexTableImpl {
-  public void resetHtml(FlexTable myTable, SafeHtml body) {
-    SafeHtml.setInnerHTML(getBodyElement(myTable), body);
-  }
-
-  protected static native Element getBodyElement(HTMLTable myTable)
-      /*-{ return myTable.@com.google.gwt.user.client.ui.HTMLTable::bodyElem; }-*/ ;
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FancyFlexTableImplIE8.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FancyFlexTableImplIE8.java
deleted file mode 100644
index 3eae0f8..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FancyFlexTableImplIE8.java
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.ui.FlexTable;
-import com.google.gwt.user.client.ui.HTMLTable;
-import com.google.gwtexpui.safehtml.client.SafeHtml;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-
-public class FancyFlexTableImplIE8 extends FancyFlexTableImpl {
-  @Override
-  public void resetHtml(FlexTable myTable, SafeHtml bodyHtml) {
-    final Element oldBody = getBodyElement(myTable);
-    final Element newBody = parseBody(bodyHtml);
-    assert newBody != null;
-
-    final Element tableElem = DOM.getParent(oldBody);
-    tableElem.removeChild(oldBody);
-    setBodyElement(myTable, newBody);
-    DOM.appendChild(tableElem, newBody);
-  }
-
-  private static Element parseBody(SafeHtml body) {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    b.openElement("table");
-    b.append(body);
-    b.closeElement("table");
-
-    final Element newTable = SafeHtml.parse(b);
-    for (Element e = DOM.getFirstChild(newTable); e != null; e = DOM.getNextSibling(e)) {
-      if ("tbody".equals(e.getTagName().toLowerCase())) {
-        return e;
-      }
-    }
-    return null;
-  }
-
-  private static native void setBodyElement(HTMLTable myTable, Element newBody)
-      /*-{ myTable.@com.google.gwt.user.client.ui.HTMLTable::bodyElem = newBody; }-*/ ;
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/HighlightingInlineHyperlink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/HighlightingInlineHyperlink.java
deleted file mode 100644
index f8e382a..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/HighlightingInlineHyperlink.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-public class HighlightingInlineHyperlink extends InlineHyperlink {
-
-  private String toHighlight;
-
-  public HighlightingInlineHyperlink(final String text, String token, String toHighlight) {
-    super(text, token);
-    this.toHighlight = toHighlight;
-    highlight(text, toHighlight);
-  }
-
-  @Override
-  public void setText(String text) {
-    super.setText(text);
-    highlight(text, toHighlight);
-  }
-
-  private void highlight(String text, String toHighlight) {
-    setHTML(Util.highlight(text, toHighlight));
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/HighlightingProjectsTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/HighlightingProjectsTable.java
deleted file mode 100644
index 1e3be3f..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/HighlightingProjectsTable.java
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.projects.ProjectInfo;
-import com.google.gerrit.client.projects.ProjectMap;
-import com.google.gwt.user.client.ui.InlineHTML;
-
-public class HighlightingProjectsTable extends ProjectsTable {
-  private String toHighlight;
-
-  public void display(ProjectMap projects, String toHighlight) {
-    this.toHighlight = toHighlight;
-    super.display(projects);
-  }
-
-  @Override
-  protected void populate(int row, ProjectInfo k) {
-    populateState(row, k);
-    table.setWidget(
-        row, ProjectsTable.C_NAME, new InlineHTML(Util.highlight(k.name(), toHighlight)));
-    table.setText(row, ProjectsTable.C_DESCRIPTION, k.description());
-
-    setRowItem(row, k);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/HintTextBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/HintTextBox.java
deleted file mode 100644
index 4ccfe9d..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/HintTextBox.java
+++ /dev/null
@@ -1,218 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gwt.event.dom.client.BlurEvent;
-import com.google.gwt.event.dom.client.BlurHandler;
-import com.google.gwt.event.dom.client.FocusEvent;
-import com.google.gwt.event.dom.client.FocusHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyDownEvent;
-import com.google.gwt.event.dom.client.KeyDownHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.ui.SuggestBox;
-import com.google.gwt.user.client.ui.SuggestBox.DefaultSuggestionDisplay;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.globalkey.client.NpTextBox;
-
-public class HintTextBox extends NpTextBox {
-  private HandlerRegistration hintFocusHandler;
-  private HandlerRegistration hintBlurHandler;
-  private HandlerRegistration keyDownHandler;
-
-  private String hintText;
-  private String hintStyleName = Gerrit.RESOURCES.css().inputFieldTypeHint();
-
-  private String prevText;
-
-  private boolean hintOn;
-  private boolean isFocused;
-
-  @Override
-  public String getText() {
-    if (hintOn) {
-      return "";
-    }
-    return super.getText();
-  }
-
-  @Override
-  public void setText(String text) {
-    focusHint();
-
-    super.setText(text);
-    prevText = text;
-
-    if (!isFocused) {
-      blurHint();
-    }
-  }
-
-  public String getHintText() {
-    return hintText;
-  }
-
-  public void setHintText(String text) {
-    if (text == null) {
-      if (hintText == null) { // was not set, still not set, no change.
-        return;
-      }
-
-      // Clearing a previously set Hint
-      hintFocusHandler.removeHandler();
-      hintFocusHandler = null;
-      hintBlurHandler.removeHandler();
-      hintBlurHandler = null;
-      keyDownHandler.removeHandler();
-      keyDownHandler = null;
-      hintText = null;
-      focusHint();
-
-      return;
-    }
-
-    // Setting Hints
-
-    if (hintText == null) { // first time (was not already set)
-      hintText = text;
-
-      hintFocusHandler =
-          addFocusHandler(
-              new FocusHandler() {
-                @Override
-                public void onFocus(FocusEvent event) {
-                  focusHint();
-                  prevText = getText();
-                  isFocused = true;
-                }
-              });
-
-      hintBlurHandler =
-          addBlurHandler(
-              new BlurHandler() {
-                @Override
-                public void onBlur(BlurEvent event) {
-                  blurHint();
-                  isFocused = false;
-                }
-              });
-
-      /*
-       * There seems to be a strange bug (at least on firefox 3.5.9 ubuntu) with
-       * the textbox under the following circumstances:
-       *  1) The field is not focused with BText in it.
-       *  2) The field receives focus and a focus listener changes the text to FText
-       *  3) The ESC key is pressed and the value of the field has not changed
-       *     (ever) from FText
-       *  4) BUG: The text value gets reset to BText!
-       *
-       *  A counter to this bug seems to be to force setFocus(false) on ESC.
-       */
-
-      /* Chrome does not create a KeyPressEvent on ESC, so use KeyDownEvents */
-      keyDownHandler =
-          addKeyDownHandler(
-              new KeyDownHandler() {
-                @Override
-                public void onKeyDown(KeyDownEvent event) {
-                  onKey(event.getNativeKeyCode());
-                }
-              });
-
-    } else { // Changing an already set Hint
-
-      focusHint();
-      hintText = text;
-    }
-
-    if (!isFocused) {
-      blurHint();
-    }
-  }
-
-  private void onKey(int key) {
-    if (key == KeyCodes.KEY_ESCAPE) {
-      setText(prevText);
-
-      Widget p = getParent();
-      if (p instanceof SuggestBox) {
-        // Since the text was changed, ensure that the SuggestBox is
-        // aware of this change so that it will refresh properly on
-        // the next keystroke.  Without this, if the first keystroke
-        // recreates the same string as before ESC was pressed, the
-        // SuggestBox will think that the string has not changed, and
-        // it will not yet provide any Suggestions.
-        ((SuggestBox) p).showSuggestionList();
-
-        // The suggestion list lingers if we don't hide it.
-        ((DefaultSuggestionDisplay) ((SuggestBox) p).getSuggestionDisplay()).hideSuggestions();
-      }
-
-      setFocus(false);
-    }
-  }
-
-  public void setHintStyleName(String styleName) {
-    if (hintStyleName != null && hintOn) {
-      removeStyleName(hintStyleName);
-    }
-
-    hintStyleName = styleName;
-
-    if (styleName != null && hintOn) {
-      addStyleName(styleName);
-    }
-  }
-
-  public String getHintStyleName() {
-    return hintStyleName;
-  }
-
-  protected void blurHint() {
-    if (!hintOn && getHintText() != null && "".equals(super.getText())) {
-      hintOn = true;
-      super.setText(getHintText());
-      if (getHintStyleName() != null) {
-        addStyleName(getHintStyleName());
-      }
-    }
-  }
-
-  protected void focusHint() {
-    if (hintOn) {
-      super.setText("");
-      if (getHintStyleName() != null) {
-        removeStyleName(getHintStyleName());
-      }
-      hintOn = false;
-    }
-  }
-
-  @Override
-  public void setFocus(boolean focus) {
-    super.setFocus(focus);
-
-    if (focus != isFocused) {
-      if (focus) {
-        focusHint();
-      } else {
-        blurHint();
-      }
-    }
-
-    isFocused = focus;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/Hyperlink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/Hyperlink.java
deleted file mode 100644
index c35d097..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/Hyperlink.java
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.impl.HyperlinkImpl;
-
-/** Standard GWT hyperlink with late updating of the token. */
-public class Hyperlink extends com.google.gwt.user.client.ui.Hyperlink {
-  public static final HyperlinkImpl impl = GWT.create(HyperlinkImpl.class);
-
-  /** Initialize a default hyperlink with no target and no text. */
-  public Hyperlink() {}
-
-  /**
-   * Creates a hyperlink with its text and target history token specified.
-   *
-   * @param text the hyperlink's text
-   * @param token the history token to which it will link, which may not be null (use {@link Anchor}
-   *     instead if you don't need history processing)
-   */
-  public Hyperlink(String text, String token) {
-    super(text, token);
-  }
-
-  /**
-   * Creates a hyperlink with its text and target history token specified.
-   *
-   * @param text the hyperlink's text
-   * @param asHTML {@code true} to treat the specified text as html
-   * @param token the history token to which it will link
-   * @see #setTargetHistoryToken
-   */
-  public Hyperlink(String text, boolean asHTML, String token) {
-    super(text, asHTML, token);
-  }
-
-  @Override
-  public void onBrowserEvent(Event event) {
-    if (DOM.eventGetType(event) == Event.ONCLICK && impl.handleAsClick(event)) {
-      event.preventDefault();
-      go();
-    } else {
-      super.onBrowserEvent(event);
-    }
-  }
-
-  /** Create the screen and start rendering, updating the browser history. */
-  public void go() {
-    Gerrit.display(getTargetHistoryToken());
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/InlineHyperlink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/InlineHyperlink.java
deleted file mode 100644
index a4edb5b..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/InlineHyperlink.java
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import static com.google.gerrit.client.ui.Hyperlink.impl;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Event;
-
-/** Standard GWT hyperlink with late updating of the token. */
-public class InlineHyperlink extends com.google.gwt.user.client.ui.InlineHyperlink {
-  /**
-   * Creates a link with its text and target history token specified.
-   *
-   * @param text the hyperlink's text
-   * @param token the history token to which it will link
-   */
-  public InlineHyperlink(String text, String token) {
-    super(text, token);
-  }
-
-  /** Creates an empty link. */
-  public InlineHyperlink() {}
-
-  @Override
-  public void onBrowserEvent(Event event) {
-    if (DOM.eventGetType(event) == Event.ONCLICK && impl.handleAsClick(event)) {
-      event.preventDefault();
-      go();
-    } else {
-      super.onBrowserEvent(event);
-    }
-  }
-
-  /** Create the screen and start rendering, updating the browser history. */
-  public void go() {
-    Gerrit.display(getTargetHistoryToken());
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/LinkMenuBar.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/LinkMenuBar.java
deleted file mode 100644
index d3db098..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/LinkMenuBar.java
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gwt.aria.client.Roles;
-import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Widget;
-
-public class LinkMenuBar extends Composite implements ScreenLoadHandler {
-  private final FlowPanel body;
-
-  public LinkMenuBar() {
-    body = new FlowPanel();
-    initWidget(body);
-    setStyleName(Gerrit.RESOURCES.css().linkMenuBar());
-    Roles.getMenubarRole().set(getElement());
-    Gerrit.EVENT_BUS.addHandler(ScreenLoadEvent.TYPE, this);
-  }
-
-  public void addItem(String text, Command imp) {
-    add(new CommandMenuItem(text, imp));
-  }
-
-  public void addItem(CommandMenuItem i) {
-    add(i);
-  }
-
-  public void addItem(LinkMenuItem i) {
-    i.setMenuBar(this);
-    add(i);
-  }
-
-  public void insertItem(LinkMenuItem i, int beforeIndex) {
-    i.setMenuBar(this);
-    insert(i, beforeIndex);
-  }
-
-  public void clear() {
-    body.clear();
-  }
-
-  public LinkMenuItem find(String targetToken) {
-    for (Widget w : body) {
-      if (w instanceof LinkMenuItem) {
-        LinkMenuItem m = (LinkMenuItem) w;
-        if (targetToken.equals(m.getTargetHistoryToken())) {
-          return m;
-        }
-      }
-    }
-    return null;
-  }
-
-  public void add(Widget i) {
-    if (body.getWidgetCount() > 0) {
-      final Widget p = body.getWidget(body.getWidgetCount() - 1);
-      p.addStyleName(Gerrit.RESOURCES.css().linkMenuItemNotLast());
-    }
-    body.add(i);
-  }
-
-  public void insert(Widget i, int beforeIndex) {
-    if (body.getWidgetCount() == 0 || body.getWidgetCount() <= beforeIndex) {
-      add(i);
-      return;
-    }
-    body.insert(i, beforeIndex);
-  }
-
-  public int getWidgetIndex(Widget i) {
-    return body.getWidgetIndex(i);
-  }
-
-  @Override
-  public void onScreenLoad(ScreenLoadEvent event) {}
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/LinkMenuItem.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/LinkMenuItem.java
deleted file mode 100644
index 8a8ab25..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/LinkMenuItem.java
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gwt.aria.client.Roles;
-import com.google.gwt.dom.client.AnchorElement;
-
-public class LinkMenuItem extends InlineHyperlink implements ScreenLoadHandler {
-  private LinkMenuBar bar;
-
-  public LinkMenuItem(String text, String targetHistoryToken) {
-    super(text, targetHistoryToken);
-    setStyleName(Gerrit.RESOURCES.css().menuItem());
-    Roles.getMenuitemRole().set(getElement());
-    Gerrit.EVENT_BUS.addHandler(ScreenLoadEvent.TYPE, this);
-  }
-
-  @Override
-  public void go() {
-    super.go();
-    AnchorElement.as(getElement()).blur();
-  }
-
-  public void setMenuBar(LinkMenuBar bar) {
-    this.bar = bar;
-  }
-
-  @Override
-  public void onScreenLoad(ScreenLoadEvent event) {
-    if (match(event.getScreen().getToken())) {
-      Gerrit.selectMenu(bar);
-      addStyleName(Gerrit.RESOURCES.css().activeRow());
-    } else {
-      removeStyleName(Gerrit.RESOURCES.css().activeRow());
-    }
-  }
-
-  protected boolean match(String token) {
-    return token.equals(getTargetHistoryToken());
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/MenuScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/MenuScreen.java
deleted file mode 100644
index 0f28ddc..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/MenuScreen.java
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.Widget;
-
-public abstract class MenuScreen extends Screen {
-  private final LinkMenuBar menu;
-  private final FlowPanel body;
-
-  public MenuScreen() {
-    menu = new LinkMenuBar();
-    menu.setStyleName(Gerrit.RESOURCES.css().menuScreenMenuBar());
-    body = new FlowPanel();
-  }
-
-  @Override
-  protected void onInitUI() {
-    super.onInitUI();
-
-    HorizontalPanel hp = new HorizontalPanel();
-    hp.add(menu);
-    hp.add(body);
-    super.add(hp);
-  }
-
-  @Override
-  public void setToken(String token) {
-    LinkMenuItem self = menu.find(token);
-    if (self != null) {
-      self.addStyleName(Gerrit.RESOURCES.css().activeRow());
-    }
-    super.setToken(token);
-  }
-
-  @Override
-  protected FlowPanel getBody() {
-    return body;
-  }
-
-  @Override
-  protected void add(Widget w) {
-    body.add(w);
-  }
-
-  protected void link(String text, String target) {
-    link(text, target, true);
-  }
-
-  protected void link(String text, String target, boolean visible) {
-    final LinkMenuItem item = new LinkMenuItem(text, target);
-    item.setStyleName(Gerrit.RESOURCES.css().menuItem());
-    item.setVisible(visible);
-    menu.add(item);
-  }
-
-  protected void setLinkVisible(String token, boolean visible) {
-    final LinkMenuItem item = menu.find(token);
-    item.setVisible(visible);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/MorphingTabPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/MorphingTabPanel.java
deleted file mode 100644
index 7fd6432..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/MorphingTabPanel.java
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (C) 2011 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gwt.event.logical.shared.SelectionEvent;
-import com.google.gwt.event.logical.shared.SelectionHandler;
-import com.google.gwt.user.client.ui.TabPanel;
-import com.google.gwt.user.client.ui.Widget;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A TabPanel which allows entries to be hidden. This class is not yet designed to handle removes or
- * any other add methods than the one overridden here. It is also not designed to handle anything
- * other than text for the tab.
- */
-public class MorphingTabPanel extends TabPanel {
-  // Keep track of the order the widgets/texts should be in when not hidden.
-  private List<Widget> widgets = new ArrayList<>();
-  private List<String> texts = new ArrayList<>();
-
-  // currently visible widgets
-  private List<Widget> visibles = new ArrayList<>();
-
-  private int selection;
-
-  public MorphingTabPanel() {
-    addSelectionHandler(
-        new SelectionHandler<Integer>() {
-          @Override
-          public void onSelection(SelectionEvent<Integer> ev) {
-            selection = ev.getSelectedItem();
-          }
-        });
-  }
-
-  public int getSelectedIndex() {
-    return selection;
-  }
-
-  public Widget getSelectedWidget() {
-    return getWidget(getSelectedIndex());
-  }
-
-  @Override
-  public void clear() {
-    super.clear();
-    widgets.clear();
-    texts.clear();
-    visibles.clear();
-  }
-
-  @Override
-  public void add(Widget w, String tabText) {
-    addInvisible(w, tabText);
-    visibles.add(w);
-    super.add(w, tabText);
-  }
-
-  public void addInvisible(Widget w, String tabText) {
-    widgets.add(w);
-    texts.add(tabText);
-  }
-
-  public void setVisible(Widget w, boolean visible) {
-    if (visible) {
-      if (!visibles.contains(w)) {
-        int origPos = widgets.indexOf(w);
-
-        /* Re-insert the widget right after the first visible widget found
-        when scanning backwards from the current widget */
-        for (int pos = origPos - 1; pos >= 0; pos--) {
-          int visiblePos = visibles.indexOf(widgets.get(pos));
-          if (visiblePos != -1) {
-            visibles.add(visiblePos + 1, w);
-            insert(w, texts.get(origPos), visiblePos + 1);
-            break;
-          }
-        }
-      }
-    } else {
-      int i = visibles.indexOf(w);
-      if (i != -1) {
-        visibles.remove(i);
-        remove(i);
-      }
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/MoveDialog.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/MoveDialog.java
deleted file mode 100644
index 3821e93..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/MoveDialog.java
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (C) 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.Util;
-import com.google.gerrit.client.projects.BranchInfo;
-import com.google.gerrit.client.projects.ProjectApi;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.SuggestBox;
-import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-import com.google.gwtexpui.safehtml.client.HighlightSuggestOracle;
-import java.util.ArrayList;
-import java.util.List;
-
-public abstract class MoveDialog extends TextAreaActionDialog {
-  private SuggestBox newBranch;
-  private List<BranchInfo> branches;
-
-  public MoveDialog(Project.NameKey project) {
-    super(Util.C.moveTitle(), Util.C.moveChangeMessage());
-    ProjectApi.getBranches(
-        project,
-        new GerritCallback<JsArray<BranchInfo>>() {
-          @Override
-          public void onSuccess(JsArray<BranchInfo> result) {
-            branches = Natives.asList(result);
-          }
-        });
-
-    newBranch =
-        new SuggestBox(
-            new HighlightSuggestOracle() {
-              @Override
-              protected void onRequestSuggestions(Request request, Callback done) {
-                List<BranchSuggestion> suggestions = new ArrayList<>();
-                for (BranchInfo b : branches) {
-                  if (b.ref().contains(request.getQuery())) {
-                    suggestions.add(new BranchSuggestion(b));
-                  }
-                }
-                done.onSuggestionsReady(request, new Response(suggestions));
-              }
-            });
-
-    newBranch.setWidth("100%");
-    newBranch.getElement().getStyle().setProperty("boxSizing", "border-box");
-    message.setCharacterWidth(70);
-
-    FlowPanel mwrap = new FlowPanel();
-    mwrap.setStyleName(Gerrit.RESOURCES.css().commentedActionMessage());
-    mwrap.add(newBranch);
-
-    panel.insert(mwrap, 0);
-    panel.insert(new SmallHeading(Util.C.headingMoveBranch()), 0);
-  }
-
-  @Override
-  public void center() {
-    super.center();
-    GlobalKey.dialog(this);
-    newBranch.setFocus(true);
-  }
-
-  public String getDestinationBranch() {
-    return newBranch.getText();
-  }
-
-  static class BranchSuggestion implements Suggestion {
-    private BranchInfo branch;
-
-    BranchSuggestion(BranchInfo branch) {
-      this.branch = branch;
-    }
-
-    @Override
-    public String getDisplayString() {
-      String refsHeads = "refs/heads/";
-      if (branch.ref().startsWith(refsHeads)) {
-        return branch.ref().substring(refsHeads.length());
-      }
-      return branch.ref();
-    }
-
-    @Override
-    public String getReplacementString() {
-      return branch.getShortName();
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/NavigationTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/NavigationTable.java
deleted file mode 100644
index 7e34730..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/NavigationTable.java
+++ /dev/null
@@ -1,407 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gwt.dom.client.Document;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.ScrollPanel;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-import com.google.gwtexpui.globalkey.client.KeyCommand;
-import com.google.gwtexpui.globalkey.client.KeyCommandSet;
-import com.google.gwtexpui.safehtml.client.SafeHtml;
-import java.util.LinkedHashMap;
-import java.util.Map.Entry;
-
-public abstract class NavigationTable<RowItem> extends FancyFlexTable<RowItem> {
-  protected class MyFlexTable extends FancyFlexTable.MyFlexTable {
-    public MyFlexTable() {
-      sinkEvents(Event.ONDBLCLICK | Event.ONCLICK);
-    }
-
-    @Override
-    public void onBrowserEvent(Event event) {
-      switch (DOM.eventGetType(event)) {
-        case Event.ONCLICK:
-          {
-            // Find out which cell was actually clicked.
-            final Element td = getEventTargetCell(event);
-            if (td == null) {
-              break;
-            }
-            final int row = rowOf(td);
-            if (getRowItem(row) != null) {
-              onCellSingleClick(event, rowOf(td), columnOf(td));
-              return;
-            }
-            break;
-          }
-        case Event.ONDBLCLICK:
-          {
-            // Find out which cell was actually clicked.
-            Element td = getEventTargetCell(event);
-            if (td == null) {
-              return;
-            }
-            onCellDoubleClick(rowOf(td), columnOf(td));
-            return;
-          }
-      }
-      super.onBrowserEvent(event);
-    }
-  }
-
-  @SuppressWarnings("serial")
-  private static final LinkedHashMap<String, Object> savedPositions =
-      new LinkedHashMap<String, Object>(10, 0.75f, true) {
-        @Override
-        protected boolean removeEldestEntry(Entry<String, Object> eldest) {
-          return size() >= 20;
-        }
-      };
-
-  private final Image pointer;
-  protected final KeyCommandSet keysNavigation;
-  protected final KeyCommandSet keysAction;
-  private HandlerRegistration regNavigation;
-  private HandlerRegistration regAction;
-  private int currentRow = -1;
-  private String saveId;
-
-  private boolean computedScrollType;
-  private ScrollPanel parentScrollPanel;
-
-  protected NavigationTable(String itemHelpName) {
-    this();
-    keysNavigation.add(
-        new PrevKeyCommand(0, 'k', Util.M.helpListPrev(itemHelpName)),
-        new NextKeyCommand(0, 'j', Util.M.helpListNext(itemHelpName)));
-    keysNavigation.add(new OpenKeyCommand(0, 'o', Util.M.helpListOpen(itemHelpName)));
-    keysNavigation.add(
-        new OpenKeyCommand(0, KeyCodes.KEY_ENTER, Util.M.helpListOpen(itemHelpName)));
-  }
-
-  protected NavigationTable() {
-    pointer = new Image(Gerrit.RESOURCES.arrowRight());
-    keysNavigation = new KeyCommandSet(Gerrit.C.sectionNavigation());
-    keysAction = new KeyCommandSet(Gerrit.C.sectionActions());
-  }
-
-  protected abstract void onOpenRow(int row);
-
-  protected abstract Object getRowItemKey(RowItem item);
-
-  private void onUp() {
-    for (int row = currentRow - 1; row >= 0; row--) {
-      if (getRowItem(row) != null) {
-        movePointerTo(row);
-        break;
-      }
-    }
-  }
-
-  private void onDown() {
-    final int max = table.getRowCount();
-    for (int row = currentRow + 1; row < max; row++) {
-      if (getRowItem(row) != null) {
-        movePointerTo(row);
-        break;
-      }
-    }
-  }
-
-  private void onOpen() {
-    if (0 <= currentRow && currentRow < table.getRowCount()) {
-      if (getRowItem(currentRow) != null) {
-        onOpenRow(currentRow);
-      }
-    }
-  }
-
-  /**
-   * Invoked when the user double clicks on a table cell.
-   *
-   * @param row row number.
-   * @param column column number.
-   */
-  protected void onCellDoubleClick(int row, int column) {
-    onOpenRow(row);
-  }
-
-  /**
-   * Invoked when the user clicks on a table cell.
-   *
-   * @param event click event.
-   * @param row row number.
-   * @param column column number.
-   */
-  protected void onCellSingleClick(Event event, int row, int column) {
-    movePointerTo(row);
-  }
-
-  protected int getCurrentRow() {
-    return currentRow;
-  }
-
-  protected void ensurePointerVisible() {
-    final int max = table.getRowCount();
-    int row = currentRow;
-    final int init = row;
-    if (row < 0) {
-      row = 0;
-    } else if (max <= row) {
-      row = max - 1;
-    }
-
-    final CellFormatter fmt = table.getCellFormatter();
-    final int sTop = Document.get().getScrollTop();
-    final int sEnd = sTop + Document.get().getClientHeight();
-
-    while (0 <= row && row < max) {
-      final Element cur = fmt.getElement(row, C_ARROW).getParentElement();
-      final int cTop = cur.getAbsoluteTop();
-      final int cEnd = cTop + cur.getOffsetHeight();
-
-      if (cEnd < sTop) {
-        row++;
-      } else if (sEnd < cTop) {
-        row--;
-      } else {
-        break;
-      }
-    }
-
-    if (init != row) {
-      movePointerTo(row, false);
-    }
-  }
-
-  protected void movePointerTo(int newRow) {
-    movePointerTo(newRow, true);
-  }
-
-  protected void movePointerTo(int newRow, boolean scroll) {
-    final CellFormatter fmt = table.getCellFormatter();
-    final boolean clear = 0 <= currentRow && currentRow < table.getRowCount();
-    if (clear) {
-      final Element tr = fmt.getElement(currentRow, C_ARROW).getParentElement();
-      UIObject.setStyleName(tr, Gerrit.RESOURCES.css().activeRow(), false);
-    }
-    if (0 <= newRow && newRow < table.getRowCount() && getRowItem(newRow) != null) {
-      table.setWidget(newRow, C_ARROW, pointer);
-      final Element tr = fmt.getElement(newRow, C_ARROW).getParentElement();
-      UIObject.setStyleName(tr, Gerrit.RESOURCES.css().activeRow(), true);
-      if (scroll && isAttached()) {
-        scrollIntoView(tr);
-      }
-    } else if (clear) {
-      table.setWidget(currentRow, C_ARROW, null);
-      pointer.removeFromParent();
-    }
-    currentRow = newRow;
-  }
-
-  protected void scrollIntoView(Element tr) {
-    if (!computedScrollType) {
-      parentScrollPanel = null;
-      Widget w = getParent();
-      while (w != null) {
-        if (w instanceof ScrollPanel) {
-          parentScrollPanel = (ScrollPanel) w;
-          break;
-        }
-        w = w.getParent();
-      }
-      computedScrollType = true;
-    }
-
-    if (parentScrollPanel != null) {
-      parentScrollPanel.ensureVisible(
-          new UIObject() {
-            {
-              setElement(tr);
-            }
-          });
-    } else {
-      int rt = tr.getAbsoluteTop();
-      int rl = tr.getAbsoluteLeft();
-      int rb = tr.getAbsoluteBottom();
-
-      int wt = Window.getScrollTop();
-      int wl = Window.getScrollLeft();
-
-      int wh = Window.getClientHeight();
-      int ww = Window.getClientWidth();
-      int wb = wt + wh;
-
-      // If the row is partially or fully obscured, scroll:
-      //
-      // rl < wl: Row left edge is off screen to left.
-      // rt < wt: Row top is above top of window.
-      // wb < rt: Row top is below bottom of window.
-      // wb < rb: Row bottom is below bottom of window.
-      if (rl < wl || rt < wt || wb < rt || wb < rb) {
-        if (rl < wl) {
-          // Left edge needs to move to make it visible.
-          // If the row fully fits in the window, set 0.
-          if (tr.getAbsoluteRight() < ww) {
-            wl = 0;
-          } else {
-            wl = Math.max(tr.getAbsoluteLeft() - 5, 0);
-          }
-        }
-
-        // Vertically center the row in the window.
-        int h = (wh - (rb - rt)) / 2;
-        Window.scrollTo(wl, Math.max(rt - h, 0));
-      }
-    }
-  }
-
-  protected void movePointerTo(Object oldId) {
-    final int row = findRow(oldId);
-    if (0 <= row) {
-      movePointerTo(row);
-    }
-  }
-
-  protected int findRow(Object oldId) {
-    if (oldId != null) {
-      final int max = table.getRowCount();
-      for (int row = 0; row < max; row++) {
-        final RowItem c = getRowItem(row);
-        if (c != null && oldId.equals(getRowItemKey(c))) {
-          return row;
-        }
-      }
-    }
-    return -1;
-  }
-
-  @Override
-  public void resetHtml(SafeHtml body) {
-    currentRow = -1;
-    super.resetHtml(body);
-  }
-
-  public void finishDisplay() {
-    if (currentRow >= table.getRowCount()) {
-      currentRow = -1;
-    }
-    if (saveId != null) {
-      movePointerTo(savedPositions.get(saveId));
-    }
-    if (currentRow < 0) {
-      onDown();
-    }
-  }
-
-  public void setSavePointerId(String id) {
-    saveId = id;
-  }
-
-  public void setRegisterKeys(boolean on) {
-    if (on && isAttached()) {
-      if (regNavigation == null) {
-        regNavigation = GlobalKey.add(this, keysNavigation);
-      }
-      if (regAction == null) {
-        regAction = GlobalKey.add(this, keysAction);
-      }
-    } else {
-      if (regNavigation != null) {
-        regNavigation.removeHandler();
-        regNavigation = null;
-      }
-      if (regAction != null) {
-        regAction.removeHandler();
-        regAction = null;
-      }
-    }
-  }
-
-  @Override
-  protected void onLoad() {
-    computedScrollType = false;
-    parentScrollPanel = null;
-  }
-
-  @Override
-  protected void onUnload() {
-    setRegisterKeys(false);
-
-    if (saveId != null && currentRow >= 0) {
-      final RowItem c = getRowItem(currentRow);
-      if (c != null) {
-        savedPositions.put(saveId, getRowItemKey(c));
-      }
-    }
-
-    computedScrollType = false;
-    parentScrollPanel = null;
-    super.onUnload();
-  }
-
-  @Override
-  protected MyFlexTable createFlexTable() {
-    return new MyFlexTable();
-  }
-
-  public class PrevKeyCommand extends KeyCommand {
-    public PrevKeyCommand(int mask, char key, String help) {
-      super(mask, key, help);
-    }
-
-    @Override
-    public void onKeyPress(KeyPressEvent event) {
-      ensurePointerVisible();
-      onUp();
-    }
-  }
-
-  public class NextKeyCommand extends KeyCommand {
-    public NextKeyCommand(int mask, char key, String help) {
-      super(mask, key, help);
-    }
-
-    @Override
-    public void onKeyPress(KeyPressEvent event) {
-      ensurePointerVisible();
-      onDown();
-    }
-  }
-
-  public class OpenKeyCommand extends KeyCommand {
-    public OpenKeyCommand(int mask, int key, String help) {
-      super(mask, key, help);
-    }
-
-    @Override
-    public void onKeyPress(KeyPressEvent event) {
-      ensurePointerVisible();
-      onOpen();
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/NeedsSignInKeyCommand.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/NeedsSignInKeyCommand.java
deleted file mode 100644
index 4420762..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/NeedsSignInKeyCommand.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gwtexpui.globalkey.client.KeyCommand;
-
-public abstract class NeedsSignInKeyCommand extends KeyCommand {
-  public NeedsSignInKeyCommand(int mask, int key, String help) {
-    super(mask, key, help);
-  }
-
-  public NeedsSignInKeyCommand(int mask, char key, String help) {
-    super(mask, key, help);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/NpIntTextBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/NpIntTextBox.java
deleted file mode 100644
index 8be6647..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/NpIntTextBox.java
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyDownEvent;
-import com.google.gwt.event.dom.client.KeyDownHandler;
-import com.google.gwt.event.dom.client.KeyEvent;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwtexpui.globalkey.client.NpTextBox;
-
-/** Text box that accepts only integer values. */
-public class NpIntTextBox extends NpTextBox {
-  private int intValue;
-
-  public NpIntTextBox() {
-    init();
-  }
-
-  private void init() {
-    addKeyDownHandler(
-        new KeyDownHandler() {
-          @Override
-          public void onKeyDown(KeyDownEvent event) {
-            int code = event.getNativeKeyCode();
-            onKey(event, code, code);
-          }
-        });
-    addKeyPressHandler(
-        new KeyPressHandler() {
-          @Override
-          public void onKeyPress(KeyPressEvent event) {
-            int charCode = event.getCharCode();
-            int keyCode = event.getNativeEvent().getKeyCode();
-            onKey(event, charCode, keyCode);
-          }
-        });
-  }
-
-  private void onKey(KeyEvent<?> event, int charCode, int keyCode) {
-    if ('0' <= charCode && charCode <= '9') {
-      if (event.isAnyModifierKeyDown()) {
-        event.preventDefault();
-      }
-    } else {
-      switch (keyCode) {
-        case KeyCodes.KEY_BACKSPACE:
-        case KeyCodes.KEY_LEFT:
-        case KeyCodes.KEY_RIGHT:
-        case KeyCodes.KEY_HOME:
-        case KeyCodes.KEY_END:
-        case KeyCodes.KEY_TAB:
-        case KeyCodes.KEY_DELETE:
-          break;
-
-        default:
-          // Allow copy and paste using ctl-c/ctrl-v,
-          // or whatever the platform's convention is.
-          if (!(event.isControlKeyDown() || event.isMetaKeyDown() || event.isAltKeyDown())) {
-            event.preventDefault();
-          }
-          break;
-      }
-    }
-  }
-
-  public int getIntValue() {
-    String txt = getText().trim();
-    if (!txt.isEmpty()) {
-      try {
-        intValue = Integer.parseInt(getText());
-      } catch (NumberFormatException e) {
-        // Ignored
-      }
-    }
-    return intValue;
-  }
-
-  public void setIntValue(int v) {
-    intValue = v;
-    setText(Integer.toString(v));
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/OnEditEnabler.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/OnEditEnabler.java
deleted file mode 100644
index 2c7fcd4..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/OnEditEnabler.java
+++ /dev/null
@@ -1,192 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;
-import com.google.gwt.event.dom.client.ChangeEvent;
-import com.google.gwt.event.dom.client.ChangeHandler;
-import com.google.gwt.event.dom.client.FocusEvent;
-import com.google.gwt.event.dom.client.FocusHandler;
-import com.google.gwt.event.dom.client.KeyDownEvent;
-import com.google.gwt.event.dom.client.KeyDownHandler;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.event.dom.client.MouseUpEvent;
-import com.google.gwt.event.dom.client.MouseUpHandler;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.logical.shared.ValueChangeHandler;
-import com.google.gwt.event.shared.GwtEvent;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.FocusWidget;
-import com.google.gwt.user.client.ui.ListBox;
-import com.google.gwt.user.client.ui.TextBoxBase;
-import com.google.gwt.user.client.ui.ValueBoxBase;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Enables a FocusWidget (e.g. a Button) if an edit is detected from any registered input widget.
- */
-public class OnEditEnabler
-    implements KeyPressHandler,
-        KeyDownHandler,
-        MouseUpHandler,
-        ChangeHandler,
-        ValueChangeHandler<Object> {
-
-  private final FocusWidget widget;
-  private Map<TextBoxBase, String> strings = new HashMap<>();
-  private String originalValue;
-
-  // The first parameter to the contructors must be the FocusWidget to enable,
-  // subsequent parameters are widgets to listenTo.
-
-  public OnEditEnabler(FocusWidget w, TextBoxBase tb) {
-    this(w);
-    originalValue = tb.getValue().trim();
-    listenTo(tb);
-  }
-
-  public OnEditEnabler(FocusWidget w, ListBox lb) {
-    this(w);
-    listenTo(lb);
-  }
-
-  public OnEditEnabler(FocusWidget w, CheckBox cb) {
-    this(w);
-    listenTo(cb);
-  }
-
-  public OnEditEnabler(FocusWidget w) {
-    widget = w;
-  }
-
-  public void updateOriginalValue(TextBoxBase tb) {
-    originalValue = tb.getValue().trim();
-  }
-
-  // Register input widgets to be listened to
-
-  public void listenTo(TextBoxBase tb) {
-    strings.put(tb, tb.getText().trim());
-    tb.addKeyPressHandler(this);
-
-    // Is there another way to capture middle button X11 pastes in browsers
-    // which do not yet support ONPASTE events (Firefox)?
-    tb.addMouseUpHandler(this);
-
-    // Resetting the "original text" on focus ensures that we are
-    // up to date with non-user updates of the text (calls to
-    // setText()...) and also up to date with user changes which
-    // occurred after enabling "widget".
-    tb.addFocusHandler(
-        new FocusHandler() {
-          @Override
-          public void onFocus(FocusEvent event) {
-            strings.put(tb, tb.getText().trim());
-          }
-        });
-
-    // CTRL-V Pastes in Chrome seem only detectable via BrowserEvents or
-    // KeyDownEvents, the latter is better.
-    tb.addKeyDownHandler(this);
-  }
-
-  public void listenTo(ListBox lb) {
-    lb.addChangeHandler(this);
-  }
-
-  @SuppressWarnings({"unchecked", "rawtypes"})
-  public void listenTo(CheckBox cb) {
-    cb.addValueChangeHandler((ValueChangeHandler) this);
-  }
-
-  // Handlers
-
-  @Override
-  public void onKeyPress(KeyPressEvent e) {
-    on(e);
-  }
-
-  @Override
-  public void onKeyDown(KeyDownEvent e) {
-    on(e);
-  }
-
-  @Override
-  public void onMouseUp(MouseUpEvent e) {
-    on(e);
-  }
-
-  @Override
-  public void onChange(ChangeEvent e) {
-    on(e);
-  }
-
-  @SuppressWarnings("rawtypes")
-  @Override
-  public void onValueChange(ValueChangeEvent e) {
-    on(e);
-  }
-
-  private void on(GwtEvent<?> e) {
-    if (widget.isEnabled()
-        || !(e.getSource() instanceof FocusWidget)
-        || !((FocusWidget) e.getSource()).isEnabled()) {
-      if (e.getSource() instanceof ValueBoxBase) {
-        final TextBoxBase box = ((TextBoxBase) e.getSource());
-        Scheduler.get()
-            .scheduleDeferred(
-                new ScheduledCommand() {
-                  @Override
-                  public void execute() {
-                    if (box.getValue().trim().equals(originalValue)) {
-                      widget.setEnabled(false);
-                    }
-                  }
-                });
-      }
-      return;
-    }
-
-    if (e.getSource() instanceof TextBoxBase) {
-      onTextBoxBase((TextBoxBase) e.getSource());
-    } else {
-      // For many widgets, we can assume that a change is an edit. If
-      // a widget does not work that way, it should be special cased
-      // above.
-      widget.setEnabled(true);
-    }
-  }
-
-  private void onTextBoxBase(TextBoxBase tb) {
-    // The text appears to not get updated until the handlers complete.
-    Scheduler.get()
-        .scheduleDeferred(
-            new ScheduledCommand() {
-              @Override
-              public void execute() {
-                String orig = strings.get(tb);
-                if (orig == null) {
-                  orig = "";
-                }
-                if (!orig.equals(tb.getText().trim())) {
-                  widget.setEnabled(true);
-                }
-              }
-            });
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/PagingHyperlink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/PagingHyperlink.java
deleted file mode 100644
index 7f0ef68..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/PagingHyperlink.java
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.admin.AdminConstants;
-
-public class PagingHyperlink extends Hyperlink {
-
-  public static PagingHyperlink createPrev() {
-    return new PagingHyperlink(AdminConstants.I.pagedListPrev());
-  }
-
-  public static PagingHyperlink createNext() {
-    return new PagingHyperlink(AdminConstants.I.pagedListNext());
-  }
-
-  private PagingHyperlink(String text) {
-    super(text, true, "");
-    setStyleName(Gerrit.RESOURCES.css().pagingLink());
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ParentProjectBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ParentProjectBox.java
deleted file mode 100644
index 7c45a20..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ParentProjectBox.java
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.projects.ProjectApi;
-import com.google.gerrit.client.projects.ProjectInfo;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Composite;
-import java.util.HashSet;
-import java.util.Set;
-
-public class ParentProjectBox extends Composite {
-  private final RemoteSuggestBox suggestBox;
-  private final ParentProjectNameSuggestOracle suggestOracle;
-
-  public ParentProjectBox() {
-    suggestOracle = new ParentProjectNameSuggestOracle();
-    suggestBox = new RemoteSuggestBox(suggestOracle);
-    initWidget(suggestBox);
-  }
-
-  public void setVisibleLength(int len) {
-    suggestBox.setVisibleLength(len);
-  }
-
-  public void setProject(Project.NameKey project) {
-    suggestOracle.setProject(project);
-  }
-
-  public void setParentProject(Project.NameKey parent) {
-    suggestBox.setText(parent != null ? parent.get() : "");
-  }
-
-  public Project.NameKey getParentProjectName() {
-    final String projectName = suggestBox.getText().trim();
-    if (projectName.isEmpty()) {
-      return null;
-    }
-    return new Project.NameKey(projectName);
-  }
-
-  private static class ParentProjectNameSuggestOracle extends ProjectNameSuggestOracle {
-    private Set<String> exclude = new HashSet<>();
-
-    public void setProject(Project.NameKey project) {
-      exclude.clear();
-      exclude.add(project.get());
-      ProjectApi.getChildren(
-          project,
-          true,
-          new AsyncCallback<JsArray<ProjectInfo>>() {
-            @Override
-            public void onSuccess(JsArray<ProjectInfo> result) {
-              for (ProjectInfo p : Natives.asList(result)) {
-                exclude.add(p.name());
-              }
-            }
-
-            @Override
-            public void onFailure(Throwable caught) {}
-          });
-    }
-
-    @Override
-    public void _onRequestSuggestions(Request req, Callback callback) {
-      super._onRequestSuggestions(
-          req,
-          new Callback() {
-            @Override
-            public void onSuggestionsReady(Request request, Response response) {
-              if (exclude.size() > 0) {
-                Set<Suggestion> filteredSuggestions = new HashSet<>(response.getSuggestions());
-                for (Suggestion s : response.getSuggestions()) {
-                  if (exclude.contains(s.getReplacementString())) {
-                    filteredSuggestions.remove(s);
-                  }
-                }
-                response.setSuggestions(filteredSuggestions);
-              }
-              callback.onSuggestionsReady(request, response);
-            }
-          });
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectLink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectLink.java
deleted file mode 100644
index c5b609a..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectLink.java
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Project;
-
-/** Link to the default dashboard of a project. */
-public class ProjectLink extends InlineHyperlink {
-  public ProjectLink(Project.NameKey proj) {
-    this(proj.get(), proj);
-  }
-
-  public ProjectLink(String text, Project.NameKey proj) {
-    super(text, PageLinks.toProjectDefaultDashboard(proj));
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectLinkMenuItem.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectLinkMenuItem.java
deleted file mode 100644
index 114f794..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectLinkMenuItem.java
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Dispatcher;
-import com.google.gerrit.client.admin.ProjectScreen;
-import com.google.gerrit.reviewdb.client.Project;
-
-public class ProjectLinkMenuItem extends LinkMenuItem {
-  protected final String panel;
-
-  public ProjectLinkMenuItem(String text, String panel) {
-    super(text, "");
-    this.panel = panel;
-  }
-
-  @Override
-  public void onScreenLoad(ScreenLoadEvent event) {
-    Screen screen = event.getScreen();
-    Project.NameKey projectKey;
-    if (screen instanceof ProjectScreen) {
-      projectKey = ((ProjectScreen) screen).getProjectKey();
-    } else {
-      projectKey = ProjectScreen.getSavedKey();
-    }
-
-    if (projectKey != null) {
-      setVisible(true);
-      onScreenLoad(projectKey);
-    } else {
-      setVisible(false);
-    }
-    super.onScreenLoad(event);
-  }
-
-  protected void onScreenLoad(Project.NameKey project) {
-    setTargetHistoryToken(Dispatcher.toProjectAdmin(project, panel));
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectListPopup.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectListPopup.java
deleted file mode 100644
index 89bff71..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectListPopup.java
+++ /dev/null
@@ -1,233 +0,0 @@
-// Copyright (C) 2011 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.account.Util;
-import com.google.gerrit.client.projects.ProjectMap;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyUpEvent;
-import com.google.gwt.event.dom.client.KeyUpHandler;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.DialogBox;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.ScrollPanel;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-import com.google.gwtexpui.globalkey.client.HidePopupPanelCommand;
-import com.google.gwtexpui.globalkey.client.NpTextBox;
-
-/** A popup containing all projects. */
-public class ProjectListPopup {
-  private HighlightingProjectsTable projectsTab;
-  private DialogBox popup;
-  private NpTextBox filterTxt;
-  private HorizontalPanel filterPanel;
-  private String match;
-  private Query query;
-  private Button closeTop;
-  private Button closeBottom;
-  private ScrollPanel sp;
-  private PopupPanel.PositionCallback popupPosition;
-  private int preferredTop;
-  private int preferredLeft;
-  private boolean poppingUp;
-  private boolean firstPopupLoad = true;
-
-  public void initPopup(String popupText, String currentPageLink) {
-    createWidgets(popupText, currentPageLink);
-    final FlowPanel pfp = new FlowPanel();
-    pfp.add(filterPanel);
-    pfp.add(closeTop);
-    sp = new ScrollPanel(projectsTab);
-    sp.setSize("100%", "100%");
-    pfp.add(sp);
-    pfp.add(closeBottom);
-    popup.setWidget(pfp);
-    popup.setHeight("100%");
-    popupPosition = getPositionCallback();
-  }
-
-  protected PopupPanel.PositionCallback getPositionCallback() {
-    return new PopupPanel.PositionCallback() {
-      @Override
-      public void setPosition(int offsetWidth, int offsetHeight) {
-        if (preferredTop + offsetHeight > Window.getClientWidth()) {
-          preferredTop = Window.getClientWidth() - offsetHeight;
-        }
-        if (preferredLeft + offsetWidth > Window.getClientWidth()) {
-          preferredLeft = Window.getClientWidth() - offsetWidth;
-        }
-
-        if (preferredTop < 0) {
-          sp.setHeight((sp.getOffsetHeight() + preferredTop) + "px");
-          preferredTop = 0;
-        }
-        if (preferredLeft < 0) {
-          sp.setWidth((sp.getOffsetWidth() + preferredLeft) + "px");
-          preferredLeft = 0;
-        }
-
-        popup.setPopupPosition(preferredLeft, preferredTop);
-      }
-    };
-  }
-
-  /**
-   * Invoked after moving pointer to a project.
-   *
-   * @param projectName project name.
-   */
-  protected void onMovePointerTo(String projectName) {}
-
-  /**
-   * Invoked after opening a project row.
-   *
-   * @param projectName project name.
-   */
-  protected void openRow(String projectName) {}
-
-  public boolean isPoppingUp() {
-    return poppingUp;
-  }
-
-  private void createWidgets(String popupText, String currentPageLink) {
-    filterPanel = new HorizontalPanel();
-    filterPanel.setStyleName(Gerrit.RESOURCES.css().projectFilterPanel());
-    final Label filterLabel =
-        new Label(com.google.gerrit.client.admin.AdminConstants.I.projectFilter());
-    filterLabel.setStyleName(Gerrit.RESOURCES.css().projectFilterLabel());
-    filterPanel.add(filterLabel);
-    filterTxt = new NpTextBox();
-    filterTxt.addKeyUpHandler(
-        new KeyUpHandler() {
-          @Override
-          public void onKeyUp(KeyUpEvent event) {
-            Query q = new Query(filterTxt.getValue());
-            if (!match.equals(q.qMatch)) {
-              if (query == null) {
-                q.run();
-              }
-              query = q;
-            }
-          }
-        });
-    filterPanel.add(filterTxt);
-
-    projectsTab =
-        new HighlightingProjectsTable() {
-          @Override
-          protected void movePointerTo(int row, boolean scroll) {
-            super.movePointerTo(row, scroll);
-            onMovePointerTo(getRowItem(row).name());
-          }
-
-          @Override
-          protected void onOpenRow(int row) {
-            super.onOpenRow(row);
-            openRow(getRowItem(row).name());
-          }
-        };
-    projectsTab.setSavePointerId(currentPageLink);
-
-    closeTop = createCloseButton();
-    closeBottom = createCloseButton();
-
-    popup = new DialogBox();
-    popup.setModal(false);
-    popup.setText(popupText);
-  }
-
-  private Button createCloseButton() {
-    Button close = new Button(Util.C.projectsClose());
-    close.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            closePopup();
-          }
-        });
-    return close;
-  }
-
-  public void displayPopup() {
-    poppingUp = true;
-    if (firstPopupLoad) { // For sizing/positioning, delay display until loaded
-      match = "";
-      query = new Query(match).run();
-    } else {
-      popup.setPopupPositionAndShow(popupPosition);
-      GlobalKey.dialog(popup);
-      GlobalKey.addApplication(popup, new HidePopupPanelCommand(0, KeyCodes.KEY_ESCAPE, popup));
-      projectsTab.setRegisterKeys(true);
-      projectsTab.finishDisplay();
-      filterTxt.setFocus(true);
-      poppingUp = false;
-    }
-  }
-
-  public void closePopup() {
-    popup.hide();
-  }
-
-  public void setPreferredCoordinates(int top, int left) {
-    this.preferredTop = top;
-    this.preferredLeft = left;
-  }
-
-  private class Query {
-    private final String qMatch;
-
-    Query(String match) {
-      this.qMatch = match;
-    }
-
-    Query run() {
-      ProjectMap.match(
-          qMatch,
-          new GerritCallback<ProjectMap>() {
-            @Override
-            public void onSuccess(ProjectMap result) {
-              if (!firstPopupLoad && !popup.isShowing()) {
-                query = null;
-              } else if (query == Query.this) {
-                query = null;
-                showMap(result);
-              } else {
-                query.run();
-              }
-            }
-          });
-      return this;
-    }
-
-    private void showMap(ProjectMap result) {
-      ProjectListPopup.this.match = qMatch;
-      projectsTab.display(result, qMatch);
-
-      if (firstPopupLoad) {
-        // Display was delayed until table was loaded
-        firstPopupLoad = false;
-        displayPopup();
-      }
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectNameSuggestOracle.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectNameSuggestOracle.java
deleted file mode 100644
index f2ebf81..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectNameSuggestOracle.java
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.projects.ProjectMap;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-
-/** Suggestion Oracle for Project.NameKey entities. */
-public class ProjectNameSuggestOracle extends SuggestAfterTypingNCharsOracle {
-  @Override
-  public void _onRequestSuggestions(Request req, Callback callback) {
-    ProjectMap.suggest(
-        req.getQuery(),
-        req.getLimit(),
-        new GerritCallback<ProjectMap>() {
-          @Override
-          public void onSuccess(ProjectMap map) {
-            callback.onSuggestionsReady(req, new Response(Natives.asList(map.values())));
-          }
-        });
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectSearchLink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectSearchLink.java
deleted file mode 100644
index f0e06a0..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectSearchLink.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.admin.AdminConstants;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.ui.Image;
-
-public class ProjectSearchLink extends InlineHyperlink {
-
-  public ProjectSearchLink(Project.NameKey projectName) {
-    super(" ", PageLinks.toProjectDefaultDashboard(projectName));
-    setTitle(AdminConstants.I.projectListQueryLink());
-    final Image image = new Image(Gerrit.RESOURCES.queryIcon());
-    image.setStyleName(Gerrit.RESOURCES.css().queryIcon());
-    DOM.insertBefore(getElement(), image.getElement(), DOM.getFirstChild(getElement()));
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectsTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectsTable.java
deleted file mode 100644
index 3576b12..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectsTable.java
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import static java.util.Comparator.comparing;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.projects.ProjectInfo;
-import com.google.gerrit.client.projects.ProjectMap;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
-import com.google.gwt.user.client.ui.Image;
-import java.util.List;
-
-public class ProjectsTable extends NavigationTable<ProjectInfo> {
-  public static final int C_STATE = 1;
-  public static final int C_NAME = 2;
-  public static final int C_DESCRIPTION = 3;
-  public static final int C_REPO_BROWSER = 4;
-
-  public ProjectsTable() {
-    super(Util.C.projectItemHelp());
-    initColumnHeaders();
-  }
-
-  protected void initColumnHeaders() {
-    table.setText(0, C_STATE, Util.C.projectStateAbbrev());
-    table.getCellFormatter().getElement(0, C_STATE).setTitle(Util.C.projectStateHelp());
-    table.setText(0, C_NAME, Util.C.projectName());
-    table.setText(0, C_DESCRIPTION, Util.C.projectDescription());
-
-    final FlexCellFormatter fmt = table.getFlexCellFormatter();
-    fmt.addStyleName(0, C_STATE, Gerrit.RESOURCES.css().iconHeader());
-    fmt.addStyleName(0, C_NAME, Gerrit.RESOURCES.css().dataHeader());
-    fmt.addStyleName(0, C_DESCRIPTION, Gerrit.RESOURCES.css().dataHeader());
-  }
-
-  @Override
-  protected Object getRowItemKey(ProjectInfo item) {
-    return item.name();
-  }
-
-  @Override
-  protected void onOpenRow(int row) {
-    if (row > 0) {
-      movePointerTo(row);
-    }
-  }
-
-  public void display(ProjectMap projects) {
-    displaySubset(projects, 0, projects.size());
-  }
-
-  public void displaySubset(ProjectMap projects, int fromIndex, int toIndex) {
-    while (1 < table.getRowCount()) {
-      table.removeRow(table.getRowCount() - 1);
-    }
-
-    List<ProjectInfo> list = Natives.asList(projects.values());
-    list.sort(comparing(ProjectInfo::name));
-    for (ProjectInfo p : list.subList(fromIndex, toIndex)) {
-      insert(table.getRowCount(), p);
-    }
-
-    finishDisplay();
-  }
-
-  protected void insert(int row, ProjectInfo k) {
-    table.insertRow(row);
-
-    applyDataRowStyle(row);
-
-    final FlexCellFormatter fmt = table.getFlexCellFormatter();
-    fmt.addStyleName(row, C_STATE, Gerrit.RESOURCES.css().iconCell());
-    fmt.addStyleName(row, C_NAME, Gerrit.RESOURCES.css().dataCell());
-    fmt.addStyleName(row, C_NAME, Gerrit.RESOURCES.css().projectNameColumn());
-    fmt.addStyleName(row, C_DESCRIPTION, Gerrit.RESOURCES.css().dataCell());
-
-    populate(row, k);
-  }
-
-  protected void populate(int row, ProjectInfo k) {
-    populateState(row, k);
-    table.setText(row, C_NAME, k.name());
-    table.setText(row, C_DESCRIPTION, k.description());
-
-    setRowItem(row, k);
-  }
-
-  protected void populateState(int row, ProjectInfo k) {
-    Image state = new Image();
-    switch (k.state()) {
-      case HIDDEN:
-        state.setResource(Gerrit.RESOURCES.redNot());
-        state.setTitle(com.google.gerrit.client.admin.Util.toLongString(k.state()));
-        table.setWidget(row, ProjectsTable.C_STATE, state);
-        break;
-      case READ_ONLY:
-        state.setResource(Gerrit.RESOURCES.readOnly());
-        state.setTitle(com.google.gerrit.client.admin.Util.toLongString(k.state()));
-        table.setWidget(row, ProjectsTable.C_STATE, state);
-        break;
-      case ACTIVE:
-      default:
-        // Intentionally left blank, do not show an icon when active.
-        break;
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/RebaseDialog.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/RebaseDialog.java
deleted file mode 100644
index e03ac46..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/RebaseDialog.java
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.ChangeList;
-import com.google.gerrit.client.changes.Util;
-import com.google.gerrit.client.info.ChangeInfo;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.extensions.client.ListChangesOption;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.SuggestBox;
-import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-import com.google.gwtexpui.safehtml.client.HighlightSuggestOracle;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-public abstract class RebaseDialog extends CommentedActionDialog {
-  private final SuggestBox base;
-  private final CheckBox changeParent;
-  private List<ChangeInfo> candidateChanges;
-  private final boolean sendEnabled;
-
-  public RebaseDialog(
-      final Project.NameKey project,
-      final String branch,
-      final Change.Id changeId,
-      final boolean sendEnabled) {
-    super(Util.C.rebaseTitle(), null);
-    this.sendEnabled = sendEnabled;
-    sendButton.setText(Util.C.buttonRebaseChangeSend());
-
-    // Create the suggestion box to filter over a list of recent changes
-    // open on the same branch. The list of candidates is primed by the
-    // changeParent CheckBox (below) getting enabled by the user.
-    base =
-        new SuggestBox(
-            new HighlightSuggestOracle() {
-              @Override
-              protected void onRequestSuggestions(Request request, Callback done) {
-                String query = request.getQuery().toLowerCase();
-                List<ChangeSuggestion> suggestions = new ArrayList<>();
-                for (ChangeInfo ci : candidateChanges) {
-                  if (changeId.equals(ci.legacyId())) {
-                    continue; // do not suggest current change
-                  }
-                  String id = String.valueOf(ci.legacyId().get());
-                  if (id.contains(query) || ci.subject().toLowerCase().contains(query)) {
-                    suggestions.add(new ChangeSuggestion(ci));
-                    if (suggestions.size() >= 50) { // limit to 50 suggestions
-                      break;
-                    }
-                  }
-                }
-                done.onSuggestionsReady(request, new Response(suggestions));
-              }
-            });
-    base.getElement().setAttribute("placeholder", Util.C.rebasePlaceholderMessage());
-    base.setStyleName(Gerrit.RESOURCES.css().rebaseSuggestBox());
-
-    // The changeParent checkbox must be clicked to load into browser memory
-    // a list of open changes from the same project and same branch that this
-    // change may rebase onto.
-    changeParent = new CheckBox(Util.C.rebaseConfirmMessage());
-    changeParent.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            if (changeParent.getValue()) {
-              ChangeList.query(
-                  PageLinks.projectQuery(project)
-                      + " "
-                      + PageLinks.op("branch", branch)
-                      + " is:open -age:90d",
-                  Collections.<ListChangesOption>emptySet(),
-                  new GerritCallback<ChangeList>() {
-                    @Override
-                    public void onSuccess(ChangeList result) {
-                      candidateChanges = Natives.asList(result);
-                      updateControls(true);
-                    }
-
-                    @Override
-                    public void onFailure(Throwable err) {
-                      updateControls(false);
-                      changeParent.setValue(false);
-                      super.onFailure(err);
-                    }
-                  });
-            } else {
-              updateControls(false);
-            }
-          }
-        });
-
-    // add the checkbox and suggestbox widgets to the content panel
-    contentPanel.add(changeParent);
-    contentPanel.add(base);
-    contentPanel.setStyleName(Gerrit.RESOURCES.css().rebaseContentPanel());
-  }
-
-  @Override
-  public void center() {
-    super.center();
-    GlobalKey.dialog(this);
-    updateControls(false);
-  }
-
-  private void updateControls(boolean changeParentEnabled) {
-    if (changeParentEnabled) {
-      sendButton.setTitle(null);
-      sendButton.setEnabled(true);
-      base.setEnabled(true);
-      base.setFocus(true);
-    } else {
-      base.setEnabled(false);
-      sendButton.setEnabled(sendEnabled);
-      if (sendEnabled) {
-        sendButton.setTitle(null);
-        sendButton.setFocus(true);
-      } else {
-        sendButton.setTitle(Util.C.rebaseNotPossibleMessage());
-        cancelButton.setFocus(true);
-      }
-    }
-  }
-
-  public String getBase() {
-    return changeParent.getValue() ? base.getText() : null;
-  }
-
-  private static class ChangeSuggestion implements Suggestion {
-    private ChangeInfo change;
-
-    ChangeSuggestion(ChangeInfo change) {
-      this.change = change;
-    }
-
-    @Override
-    public String getDisplayString() {
-      return String.valueOf(change.legacyId().get()) + ": " + change.subject();
-    }
-
-    @Override
-    public String getReplacementString() {
-      return String.valueOf(change.legacyId().get());
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/RemoteSuggestBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/RemoteSuggestBox.java
deleted file mode 100644
index 5d741cf..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/RemoteSuggestBox.java
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package com.google.gerrit.client.ui;
-
-import com.google.gwt.event.dom.client.FocusEvent;
-import com.google.gwt.event.dom.client.FocusHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyDownEvent;
-import com.google.gwt.event.dom.client.KeyDownHandler;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.event.logical.shared.HasCloseHandlers;
-import com.google.gwt.event.logical.shared.HasSelectionHandlers;
-import com.google.gwt.event.logical.shared.SelectionEvent;
-import com.google.gwt.event.logical.shared.SelectionHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.Focusable;
-import com.google.gwt.user.client.ui.HasText;
-import com.google.gwt.user.client.ui.SuggestBox;
-import com.google.gwt.user.client.ui.SuggestBox.DefaultSuggestionDisplay;
-import com.google.gwt.user.client.ui.SuggestOracle;
-import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
-import com.google.gwt.user.client.ui.TextBoxBase;
-
-public class RemoteSuggestBox extends Composite
-    implements Focusable,
-        HasText,
-        HasSelectionHandlers<String>,
-        HasCloseHandlers<RemoteSuggestBox> {
-  private final RemoteSuggestOracle remoteSuggestOracle;
-  private final DefaultSuggestionDisplay display;
-  private final HintTextBox textBox;
-  private final SuggestBox suggestBox;
-  private boolean submitOnSelection;
-
-  public RemoteSuggestBox(SuggestOracle oracle) {
-    remoteSuggestOracle = new RemoteSuggestOracle(oracle);
-    remoteSuggestOracle.setServeSuggestions(true);
-    display = new DefaultSuggestionDisplay();
-
-    textBox = new HintTextBox();
-    textBox.addKeyDownHandler(
-        new KeyDownHandler() {
-          @Override
-          public void onKeyDown(KeyDownEvent e) {
-            submitOnSelection = false;
-            if (e.getNativeKeyCode() == KeyCodes.KEY_ESCAPE) {
-              CloseEvent.fire(RemoteSuggestBox.this, RemoteSuggestBox.this);
-            } else if (e.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
-              if (display.isSuggestionListShowing()) {
-                if (textBox.getValue().equals(remoteSuggestOracle.getLast())) {
-                  submitOnSelection = true;
-                } else {
-                  display.hideSuggestions();
-                }
-              } else {
-                SelectionEvent.fire(RemoteSuggestBox.this, getText());
-              }
-            }
-          }
-        });
-
-    suggestBox = new SuggestBox(remoteSuggestOracle, textBox, display);
-    suggestBox.addSelectionHandler(
-        new SelectionHandler<Suggestion>() {
-          @Override
-          public void onSelection(SelectionEvent<Suggestion> event) {
-            if (submitOnSelection) {
-              SelectionEvent.fire(RemoteSuggestBox.this, getText());
-            }
-            remoteSuggestOracle.cancelOutstandingRequest();
-            display.hideSuggestions();
-          }
-        });
-    initWidget(suggestBox);
-  }
-
-  public void setHintText(String hint) {
-    textBox.setHintText(hint);
-  }
-
-  public void setVisibleLength(int len) {
-    textBox.setVisibleLength(len);
-  }
-
-  public void setEnabled(boolean enabled) {
-    suggestBox.setEnabled(enabled);
-  }
-
-  public TextBoxBase getTextBox() {
-    return textBox;
-  }
-
-  @Override
-  public String getText() {
-    return suggestBox.getText();
-  }
-
-  @Override
-  public void setText(String value) {
-    suggestBox.setText(value);
-  }
-
-  @Override
-  public void setFocus(boolean focus) {
-    suggestBox.setFocus(focus);
-  }
-
-  @Override
-  public int getTabIndex() {
-    return suggestBox.getTabIndex();
-  }
-
-  @Override
-  public void setAccessKey(char key) {
-    suggestBox.setAccessKey(key);
-  }
-
-  @Override
-  public void setTabIndex(int index) {
-    suggestBox.setTabIndex(index);
-  }
-
-  @Override
-  public HandlerRegistration addSelectionHandler(SelectionHandler<String> h) {
-    return addHandler(h, SelectionEvent.getType());
-  }
-
-  @Override
-  public HandlerRegistration addCloseHandler(CloseHandler<RemoteSuggestBox> h) {
-    return addHandler(h, CloseEvent.getType());
-  }
-
-  public void selectAll() {
-    suggestBox.getValueBox().selectAll();
-  }
-
-  public void enableDefaultSuggestions() {
-    textBox.addFocusHandler(
-        new FocusHandler() {
-          @Override
-          public void onFocus(FocusEvent focusEvent) {
-            if (textBox.getText().equals("")) {
-              suggestBox.showSuggestionList();
-            }
-          }
-        });
-  }
-
-  public void setServeSuggestionsOnOracle(boolean serveSuggestions) {
-    remoteSuggestOracle.setServeSuggestions(serveSuggestions);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/Screen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/Screen.java
deleted file mode 100644
index 03ed899..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/Screen.java
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.projects.ThemeInfo;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.HasHorizontalAlignment;
-import com.google.gwt.user.client.ui.InlineLabel;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.user.client.View;
-
-/**
- * A Screen layout with a header and a body.
- *
- * <p>The header is mainly a text title, but it can be decorated in the West, the East, and the
- * FarEast by any Widget. The West and East decorations will surround the text on the left and right
- * respectively, and the FarEast will be right justified to the right edge of the screen. The East
- * decoration will expand to take up any extra space.
- */
-public abstract class Screen extends View {
-  private Grid header;
-  private InlineLabel headerText;
-  private FlowPanel body;
-  private String token;
-  private boolean requiresSignIn;
-  private String windowTitle;
-  private Widget titleWidget;
-
-  private ThemeInfo theme;
-  private boolean setTheme;
-
-  protected Screen() {
-    initWidget(new FlowPanel());
-    setStyleName(Gerrit.RESOURCES.css().screen());
-    body = new FlowPanel();
-  }
-
-  @Override
-  protected void onLoad() {
-    super.onLoad();
-    if (header == null) {
-      onInitUI();
-    }
-  }
-
-  @Override
-  protected void onUnload() {
-    super.onUnload();
-    if (setTheme) {
-      Gerrit.THEMER.clear();
-    }
-  }
-
-  public void registerKeys() {}
-
-  private enum Cols {
-    West,
-    Title,
-    East,
-    FarEast
-  }
-
-  protected void onInitUI() {
-    final FlowPanel me = (FlowPanel) getWidget();
-    me.add(header = new Grid(1, Cols.values().length));
-    me.add(body);
-
-    headerText = new InlineLabel();
-    if (titleWidget == null) {
-      titleWidget = headerText;
-    }
-    FlowPanel title = new FlowPanel();
-    title.add(titleWidget);
-    title.setStyleName(Gerrit.RESOURCES.css().screenHeader());
-    header.setWidget(0, Cols.Title.ordinal(), title);
-
-    header.setStyleName(Gerrit.RESOURCES.css().screenHeader());
-    header
-        .getCellFormatter()
-        .setHorizontalAlignment(0, Cols.FarEast.ordinal(), HasHorizontalAlignment.ALIGN_RIGHT);
-    // force FarEast all the way to the right
-    header.getCellFormatter().setWidth(0, Cols.FarEast.ordinal(), "100%");
-  }
-
-  protected void setWindowTitle(String text) {
-    windowTitle = text;
-    Gerrit.setWindowTitle(this, text);
-  }
-
-  protected void setPageTitle(String text) {
-    final String old = headerText.getText();
-    if (text.isEmpty()) {
-      header.setVisible(false);
-    } else {
-      headerText.setText(text);
-      header.setVisible(true);
-    }
-    if (windowTitle == null || windowTitle.equals(old)) {
-      setWindowTitle(text);
-    }
-  }
-
-  protected void setHeaderVisible(boolean value) {
-    header.setVisible(value);
-  }
-
-  public void setTitle(Widget w) {
-    titleWidget = w;
-  }
-
-  protected void setTitleEast(Widget w) {
-    header.setWidget(0, Cols.East.ordinal(), w);
-  }
-
-  protected void setTitleFarEast(Widget w) {
-    header.setWidget(0, Cols.FarEast.ordinal(), w);
-  }
-
-  protected void setTitleWest(Widget w) {
-    header.setWidget(0, Cols.West.ordinal(), w);
-  }
-
-  protected void add(Widget w) {
-    body.add(w);
-  }
-
-  protected FlowPanel getBody() {
-    return body;
-  }
-
-  protected void setTheme(ThemeInfo t) {
-    theme = t;
-  }
-
-  /** Get the history token for this screen. */
-  public String getToken() {
-    return token;
-  }
-
-  /** Set the history token for this screen. */
-  public void setToken(String t) {
-    assert t != null && !t.isEmpty();
-    token = t;
-
-    if (isCurrentView()) {
-      Gerrit.updateImpl(token);
-    }
-  }
-
-  /**
-   * If this view can display the given token, update it.
-   *
-   * @param newToken token the UI wants to show.
-   * @return true if this view can show the token immediately, false if not.
-   */
-  public boolean displayToken(String newToken) {
-    return false;
-  }
-
-  /** Set whether or not {@link Gerrit#isSignedIn()} must be true. */
-  public final void setRequiresSignIn(boolean b) {
-    requiresSignIn = b;
-  }
-
-  /** Does {@link Gerrit#isSignedIn()} have to be true to be on this screen? */
-  public final boolean isRequiresSignIn() {
-    return requiresSignIn;
-  }
-
-  public void onShowView() {
-    if (windowTitle != null) {
-      Gerrit.setWindowTitle(this, windowTitle);
-    }
-    Gerrit.EVENT_BUS.fireEvent(new ScreenLoadEvent(this));
-    Gerrit.setQueryString(null);
-    registerKeys();
-
-    if (theme != null) {
-      Gerrit.THEMER.set(theme);
-      setTheme = true;
-    } else {
-      Gerrit.THEMER.clear();
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ScreenLoadEvent.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ScreenLoadEvent.java
deleted file mode 100644
index debd9a6..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ScreenLoadEvent.java
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gwt.event.shared.GwtEvent;
-
-public class ScreenLoadEvent extends GwtEvent<ScreenLoadHandler> {
-  private final Screen screen;
-
-  public ScreenLoadEvent(Screen screen) {
-    super();
-    this.screen = screen;
-  }
-
-  public static final Type<ScreenLoadHandler> TYPE = new Type<>();
-
-  @Override
-  protected void dispatch(ScreenLoadHandler handler) {
-    handler.onScreenLoad(this);
-  }
-
-  @Override
-  public GwtEvent.Type<ScreenLoadHandler> getAssociatedType() {
-    return TYPE;
-  }
-
-  public Screen getScreen() {
-    return screen;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ScreenLoadHandler.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ScreenLoadHandler.java
deleted file mode 100644
index 9a5eb03..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ScreenLoadHandler.java
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gwt.event.shared.EventHandler;
-
-public interface ScreenLoadHandler extends EventHandler {
-  void onScreenLoad(ScreenLoadEvent event);
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/SmallHeading.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/SmallHeading.java
deleted file mode 100644
index ea18d62..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/SmallHeading.java
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gwt.user.client.ui.Label;
-
-public class SmallHeading extends Label {
-  public SmallHeading() {
-    setStyleName(Gerrit.RESOURCES.css().smallHeading());
-  }
-
-  public SmallHeading(String text) {
-    this();
-    setText(text);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/SuggestAfterTypingNCharsOracle.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/SuggestAfterTypingNCharsOracle.java
deleted file mode 100644
index e24f347..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/SuggestAfterTypingNCharsOracle.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gwtexpui.safehtml.client.HighlightSuggestOracle;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Suggest oracle that only provides suggestions if the user has typed at least as many characters
- * as configured by 'suggest.from'. If 'suggest.from' is set to 0, suggestions will always be
- * provided.
- */
-public abstract class SuggestAfterTypingNCharsOracle extends HighlightSuggestOracle {
-
-  @Override
-  protected void onRequestSuggestions(Request req, Callback cb) {
-    if (req.getQuery() != null && req.getQuery().length() >= Gerrit.info().suggest().from()) {
-      _onRequestSuggestions(req, cb);
-    } else {
-      List<Suggestion> none = Collections.emptyList();
-      cb.onSuggestionsReady(req, new Response(none));
-    }
-  }
-
-  protected abstract void _onRequestSuggestions(Request request, Callback done);
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/TextAreaActionDialog.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/TextAreaActionDialog.java
deleted file mode 100644
index d7d5d6a..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/TextAreaActionDialog.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwtexpui.globalkey.client.NpTextArea;
-
-public abstract class TextAreaActionDialog extends CommentedActionDialog
-    implements CloseHandler<PopupPanel> {
-  protected final NpTextArea message;
-
-  public TextAreaActionDialog(String title, String heading) {
-    super(title, heading);
-
-    message = new NpTextArea();
-    message.setCharacterWidth(60);
-    message.setVisibleLines(10);
-    message.getElement().setPropertyBoolean("spellcheck", true);
-    setFocusOn(message);
-
-    contentPanel.add(message);
-  }
-
-  public String getMessageText() {
-    return message.getText().trim();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/UIConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/UIConstants.java
deleted file mode 100644
index 32bb796..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/UIConstants.java
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gwt.i18n.client.Constants;
-
-public interface UIConstants extends Constants {
-  String commentedActionButtonSend();
-
-  String commentedActionButtonCancel();
-
-  String projectName();
-
-  String projectDescription();
-
-  String projectItemHelp();
-
-  String projectStateAbbrev();
-
-  String projectStateHelp();
-
-  String dialogCreateChangeTitle();
-
-  String dialogCreateChangeHeading();
-
-  String newChangeBranchSuggestion();
-
-  String newChangeTopicSuggestion();
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/UIConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/UIConstants.properties
deleted file mode 100644
index 736e210..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/UIConstants.properties
+++ /dev/null
@@ -1,13 +0,0 @@
-commentedActionButtonSend = Submit
-commentedActionButtonCancel = Cancel
-
-projectName = Project Name
-projectDescription = Project Description
-projectItemHelp = project
-projectStateAbbrev = S
-projectStateHelp = State
-
-dialogCreateChangeTitle = Create Change
-dialogCreateChangeHeading = Description
-newChangeBranchSuggestion = Select branch for new change
-newChangeTopicSuggestion = Enter topic for new change
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/UIMessages.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/UIMessages.java
deleted file mode 100644
index af17390..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/UIMessages.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gwt.i18n.client.Messages;
-
-public interface UIMessages extends Messages {
-  String helpListOpen(String item);
-
-  String helpListPrev(String item);
-
-  String helpListNext(String item);
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/UIMessages.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/UIMessages.properties
deleted file mode 100644
index 1439245..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/UIMessages.properties
+++ /dev/null
@@ -1,3 +0,0 @@
-helpListOpen = Select {0}
-helpListPrev = Previous {0}
-helpListNext = Next {0}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/UserActivityMonitor.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/UserActivityMonitor.java
deleted file mode 100644
index 2b76b9b..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/UserActivityMonitor.java
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.RepeatingCommand;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.event.dom.client.MouseMoveEvent;
-import com.google.gwt.event.dom.client.MouseMoveHandler;
-import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.logical.shared.ValueChangeHandler;
-import com.google.gwt.event.shared.EventBus;
-import com.google.gwt.event.shared.GwtEvent;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.event.shared.SimpleEventBus;
-import com.google.gwt.user.client.History;
-import com.google.gwtexpui.globalkey.client.DocWidget;
-
-/** Checks for user keyboard and mouse activity. */
-public class UserActivityMonitor {
-  private static final long TIMEOUT = 10 * 60 * 1000;
-  private static final MonitorImpl impl;
-
-  /**
-   * @return true if there has been keyboard and/or mouse activity in recent enough history to
-   *     believe a user is still controlling this session.
-   */
-  public static boolean isActive() {
-    return impl.active || impl.recent;
-  }
-
-  public static HandlerRegistration addValueChangeHandler(ValueChangeHandler<Boolean> handler) {
-    return impl.addValueChangeHandler(handler);
-  }
-
-  static {
-    impl = new MonitorImpl();
-    DocWidget.get().addKeyPressHandler(impl);
-    DocWidget.get().addMouseMoveHandler(impl);
-    History.addValueChangeHandler(impl);
-    Scheduler.get().scheduleFixedDelay(impl, 60 * 1000);
-  }
-
-  private UserActivityMonitor() {}
-
-  private static class MonitorImpl
-      implements RepeatingCommand,
-          KeyPressHandler,
-          MouseMoveHandler,
-          ValueChangeHandler<String>,
-          HasValueChangeHandlers<Boolean> {
-    private final EventBus bus = new SimpleEventBus();
-    private boolean recent = true;
-    private boolean active = true;
-    private long last = System.currentTimeMillis();
-
-    @Override
-    public void onKeyPress(KeyPressEvent event) {
-      recent = true;
-    }
-
-    @Override
-    public void onMouseMove(MouseMoveEvent event) {
-      recent = true;
-    }
-
-    @Override
-    public void onValueChange(ValueChangeEvent<String> event) {
-      recent = true;
-    }
-
-    @Override
-    public boolean execute() {
-      long now = System.currentTimeMillis();
-      if (recent) {
-        if (!active) {
-          ValueChangeEvent.fire(this, active);
-        }
-        recent = false;
-        active = true;
-        last = now;
-      } else if (active && (now - last) > TIMEOUT) {
-        active = false;
-        ValueChangeEvent.fire(this, false);
-      }
-      return true;
-    }
-
-    @Override
-    public HandlerRegistration addValueChangeHandler(ValueChangeHandler<Boolean> handler) {
-      return bus.addHandler(ValueChangeEvent.getType(), handler);
-    }
-
-    @Override
-    public void fireEvent(GwtEvent<?> event) {
-      bus.fireEvent(event);
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/Util.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/Util.java
deleted file mode 100644
index 41e3573..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/Util.java
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.ui;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-
-public class Util {
-  public static final UIConstants C = GWT.create(UIConstants.class);
-  public static final UIMessages M = GWT.create(UIMessages.class);
-
-  public static String highlight(String text, String toHighlight) {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    if (toHighlight == null || "".equals(toHighlight)) {
-      b.append(text);
-      return b.toSafeHtml().asString();
-    }
-
-    int pos = 0;
-    int endPos = 0;
-    while ((pos = text.toLowerCase().indexOf(toHighlight.toLowerCase(), pos)) > -1) {
-      if (pos > endPos) {
-        b.append(text.substring(endPos, pos));
-      }
-      endPos = pos + toHighlight.length();
-      b.openElement("b");
-      b.append(text.substring(pos, endPos));
-      b.closeElement("b");
-      pos = endPos;
-    }
-    if (endPos < text.length()) {
-      b.append(text.substring(endPos));
-    }
-    return b.toSafeHtml().asString();
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/CodeMirror.gwt.xml b/gerrit-gwtui/src/main/java/net/codemirror/CodeMirror.gwt.xml
deleted file mode 100644
index add033f..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/CodeMirror.gwt.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
- Copyright (C) 2013 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<module>
-  <inherits name='com.google.gwt.logging.Logging'/>
-  <inherits name='com.google.gwt.resources.Resources'/>
-  <source path='addon'/>
-  <source path='lib'/>
-  <source path='keymap'/>
-  <source path='mode'/>
-  <source path='theme'/>
-</module>
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/addon/AddonInjector.java b/gerrit-gwtui/src/main/java/net/codemirror/addon/AddonInjector.java
deleted file mode 100644
index cb1891e..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/addon/AddonInjector.java
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.addon;
-
-import com.google.gwt.safehtml.shared.SafeUri;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import net.codemirror.lib.Loader;
-
-public class AddonInjector {
-  private static final Map<String, SafeUri> addonUris = new HashMap<>();
-
-  static {
-    addonUris.put(Addons.I.merge_bundled().getName(), Addons.I.merge_bundled().getSafeUri());
-  }
-
-  public static SafeUri getAddonScriptUri(String addon) {
-    return addonUris.get(addon);
-  }
-
-  private static boolean canLoad(String addon) {
-    return getAddonScriptUri(addon) != null;
-  }
-
-  private final Set<String> loading = new HashSet<>();
-  private int pending;
-  private AsyncCallback<Void> appCallback;
-
-  public AddonInjector add(String name) {
-    if (name == null) {
-      return this;
-    }
-
-    if (!canLoad(name)) {
-      Logger.getLogger("net.codemirror")
-          .log(Level.WARNING, "CodeMirror addon " + name + " not configured.");
-      return this;
-    }
-
-    loading.add(name);
-    return this;
-  }
-
-  public void inject(AsyncCallback<Void> appCallback) {
-    this.appCallback = appCallback;
-    for (String addon : loading) {
-      beginLoading(addon);
-    }
-    if (pending == 0) {
-      appCallback.onSuccess(null);
-    }
-  }
-
-  private void beginLoading(String addon) {
-    pending++;
-    Loader.injectScript(
-        getAddonScriptUri(addon),
-        new AsyncCallback<Void>() {
-          @Override
-          public void onSuccess(Void result) {
-            pending--;
-            if (pending == 0) {
-              appCallback.onSuccess(null);
-            }
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            if (--pending == 0) {
-              appCallback.onFailure(caught);
-            }
-          }
-        });
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/addon/Addons.java b/gerrit-gwtui/src/main/java/net/codemirror/addon/Addons.java
deleted file mode 100644
index 19a681c..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/addon/Addons.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.addon;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.resources.client.ClientBundle;
-import com.google.gwt.resources.client.DataResource;
-import com.google.gwt.resources.client.DataResource.DoNotEmbed;
-
-public interface Addons extends ClientBundle {
-  Addons I = GWT.create(Addons.class);
-
-  @Source("merge_bundled.js")
-  @DoNotEmbed
-  DataResource merge_bundled();
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/BlameConfig.java b/gerrit-gwtui/src/main/java/net/codemirror/lib/BlameConfig.java
deleted file mode 100644
index 1e81f83a..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/lib/BlameConfig.java
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.lib;
-
-import com.google.gwt.i18n.client.Messages;
-
-public interface BlameConfig extends Messages {
-  String shortBlameMsg(String commitId, String date, String author);
-
-  String detailedBlameMsg(String commitId, String author, String time, String msg);
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/BlameConfig.properties b/gerrit-gwtui/src/main/java/net/codemirror/lib/BlameConfig.properties
deleted file mode 100644
index 658b50f..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/lib/BlameConfig.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-shortBlameMsg={0} {1} {2}
-detailedBlameMsg=commit {0}\nAuthor: {1}\nDate: {2}\n\n{3}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/CodeMirror.java b/gerrit-gwtui/src/main/java/net/codemirror/lib/CodeMirror.java
deleted file mode 100644
index a84c464..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/lib/CodeMirror.java
+++ /dev/null
@@ -1,448 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.lib;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.diff.DisplaySide;
-import com.google.gerrit.client.rpc.CallbackGroup;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.NativeEvent;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import net.codemirror.lib.TextMarker.FromTo;
-
-/**
- * Glue to connect CodeMirror to be callable from GWT.
- *
- * @see <a href="http://codemirror.net/doc/manual.html#api">CodeMirror API</a>
- */
-public class CodeMirror extends JavaScriptObject {
-  public static void preload() {
-    initLibrary(CallbackGroup.<Void>emptyCallback());
-  }
-
-  public static void initLibrary(AsyncCallback<Void> cb) {
-    Loader.initLibrary(cb);
-  }
-
-  interface Style extends CssResource {
-    String activeLine();
-
-    String showTabs();
-
-    String margin();
-  }
-
-  static Style style() {
-    return Lib.I.style();
-  }
-
-  public static CodeMirror create(Element p, Configuration cfg) {
-    CodeMirror cm = newCM(p, cfg);
-    Extras.attach(cm);
-    return cm;
-  }
-
-  private static native CodeMirror newCM(Element p, Configuration cfg) /*-{
-    return $wnd.CodeMirror(p, cfg);
-  }-*/;
-
-  public final native void setOption(String option, boolean value) /*-{
-    this.setOption(option, value)
-  }-*/;
-
-  public final native void setOption(String option, double value) /*-{
-    this.setOption(option, value)
-  }-*/;
-
-  public final native void setOption(String option, String value) /*-{
-    this.setOption(option, value)
-  }-*/;
-
-  public final native void setOption(String option, JavaScriptObject val) /*-{
-    this.setOption(option, val)
-  }-*/;
-
-  public final native String getStringOption(String o) /*-{ return this.getOption(o) }-*/;
-
-  public final native String getValue() /*-{ return this.getValue() }-*/;
-
-  public final native void setValue(String v) /*-{ this.setValue(v) }-*/;
-
-  public final native int changeGeneration(boolean closeEvent)
-      /*-{ return this.changeGeneration(closeEvent) }-*/ ;
-
-  public final native boolean isClean(int generation) /*-{ return this.isClean(generation) }-*/;
-
-  public final native void setWidth(double w) /*-{ this.setSize(w, null) }-*/;
-
-  public final native void setHeight(double h) /*-{ this.setSize(null, h) }-*/;
-
-  public final int getHeight() {
-    return getWrapperElement().getClientHeight();
-  }
-
-  public final void adjustHeight(int localHeader) {
-    int rest = Gerrit.getHeaderFooterHeight() + localHeader + 5; // Estimate
-    setHeight(Window.getClientHeight() - rest);
-  }
-
-  public final native String getLine(int n) /*-{ return this.getLine(n) }-*/;
-
-  public final native double barHeight() /*-{ return this.display.barHeight }-*/;
-
-  public final native double barWidth() /*-{ return this.display.barWidth }-*/;
-
-  public final native int lastLine() /*-{ return this.lastLine() }-*/;
-
-  public final native void refresh() /*-{ this.refresh() }-*/;
-
-  public final native TextMarker markText(Pos from, Pos to, Configuration options) /*-{
-    return this.markText(from, to, options)
-  }-*/;
-
-  public enum LineClassWhere {
-    TEXT {
-      @Override
-      String value() {
-        return "text";
-      }
-    },
-    BACKGROUND {
-      @Override
-      String value() {
-        return "background";
-      }
-    },
-    WRAP {
-      @Override
-      String value() {
-        return "wrap";
-      }
-    };
-
-    abstract String value();
-  }
-
-  public final void addLineClass(int line, LineClassWhere where, String className) {
-    addLineClassNative(line, where.value(), className);
-  }
-
-  private native void addLineClassNative(int line, String where, String lineClass) /*-{
-    this.addLineClass(line, where, lineClass)
-  }-*/;
-
-  public final void addLineClass(LineHandle line, LineClassWhere where, String className) {
-    addLineClassNative(line, where.value(), className);
-  }
-
-  private native void addLineClassNative(LineHandle line, String where, String lineClass) /*-{
-    this.addLineClass(line, where, lineClass)
-  }-*/;
-
-  public final void removeLineClass(int line, LineClassWhere where, String className) {
-    removeLineClassNative(line, where.value(), className);
-  }
-
-  private native void removeLineClassNative(int line, String where, String lineClass) /*-{
-    this.removeLineClass(line, where, lineClass)
-  }-*/;
-
-  public final void removeLineClass(LineHandle line, LineClassWhere where, String className) {
-    removeLineClassNative(line, where.value(), className);
-  }
-
-  private native void removeLineClassNative(LineHandle line, String where, String lineClass) /*-{
-    this.removeLineClass(line, where, lineClass)
-  }-*/;
-
-  public final native void addWidget(Pos pos, Element node) /*-{
-    this.addWidget(pos, node, false)
-  }-*/;
-
-  public final native LineWidget addLineWidget(int line, Element node, Configuration options) /*-{
-    return this.addLineWidget(line, node, options)
-  }-*/;
-
-  public final native int lineAtHeight(double height) /*-{
-    return this.lineAtHeight(height)
-  }-*/;
-
-  public final native int lineAtHeight(double height, String mode) /*-{
-    return this.lineAtHeight(height, mode)
-  }-*/;
-
-  public final native double heightAtLine(int line) /*-{
-    return this.heightAtLine(line)
-  }-*/;
-
-  public final native double heightAtLine(int line, String mode) /*-{
-    return this.heightAtLine(line, mode)
-  }-*/;
-
-  public final native Rect charCoords(Pos pos, String mode) /*-{
-    return this.charCoords(pos, mode)
-  }-*/;
-
-  public final native CodeMirrorDoc getDoc() /*-{
-    return this.getDoc()
-  }-*/;
-
-  public final native void scrollTo(double x, double y) /*-{
-    this.scrollTo(x, y)
-  }-*/;
-
-  public final native void scrollToY(double y) /*-{
-    this.scrollTo(null, y)
-  }-*/;
-
-  public final void scrollToLine(int line) {
-    int height = getHeight();
-    if (lineAtHeight(height - 20) < line) {
-      scrollToY(heightAtLine(line, "local") - 0.5 * height);
-    }
-    setCursor(Pos.create(line, 0));
-  }
-
-  public final native ScrollInfo getScrollInfo() /*-{
-    return this.getScrollInfo()
-  }-*/;
-
-  public final native Viewport getViewport() /*-{
-    return this.getViewport()
-  }-*/;
-
-  public final native void operation(Runnable thunk) /*-{
-    this.operation(function() {
-      thunk.@java.lang.Runnable::run()();
-    })
-  }-*/;
-
-  public final native void off(String event, RegisteredHandler h) /*-{
-    this.off(event, h)
-  }-*/;
-
-  public final native RegisteredHandler on(String event, Runnable thunk) /*-{
-    var h = $entry(function() { thunk.@java.lang.Runnable::run()() });
-    this.on(event, h);
-    return h;
-  }-*/;
-
-  public final native void on(String event, EventHandler handler) /*-{
-    this.on(event, $entry(function(cm, e) {
-      handler.@net.codemirror.lib.CodeMirror.EventHandler::handle(
-        Lnet/codemirror/lib/CodeMirror;
-        Lcom/google/gwt/dom/client/NativeEvent;)(cm, e);
-    }))
-  }-*/;
-
-  public final native void on(String event, RenderLineHandler handler) /*-{
-    this.on(event, $entry(function(cm, h, e) {
-      handler.@net.codemirror.lib.CodeMirror.RenderLineHandler::handle(
-        Lnet/codemirror/lib/CodeMirror;
-        Lnet/codemirror/lib/CodeMirror$LineHandle;
-        Lcom/google/gwt/dom/client/Element;)(cm, h, e);
-    }))
-  }-*/;
-
-  public final native void on(String event, GutterClickHandler handler) /*-{
-    this.on(event, $entry(function(cm, l, g, e) {
-      handler.@net.codemirror.lib.CodeMirror.GutterClickHandler::handle(
-        Lnet/codemirror/lib/CodeMirror;
-        I
-        Ljava/lang/String;
-        Lcom/google/gwt/dom/client/NativeEvent;)(cm, l, g, e);
-    }))
-  }-*/;
-
-  public final native void on(String event, BeforeSelectionChangeHandler handler) /*-{
-    this.on(event, $entry(function(cm, o) {
-      var e = o.ranges[o.ranges.length-1];
-      handler.@net.codemirror.lib.CodeMirror.BeforeSelectionChangeHandler::handle(
-        Lnet/codemirror/lib/CodeMirror;
-        Lnet/codemirror/lib/Pos;
-        Lnet/codemirror/lib/Pos;)(cm, e.anchor, e.head);
-    }))
-  }-*/;
-
-  public final native void on(ChangesHandler handler) /*-{
-    this.on('changes', $entry(function(cm, o) {
-      handler.@net.codemirror.lib.CodeMirror.ChangesHandler::handle(
-        Lnet/codemirror/lib/CodeMirror;)(cm);
-    }))
-  }-*/;
-
-  public final native void setCursor(Pos p) /*-{ this.setCursor(p) }-*/;
-
-  public final native Pos getCursor() /*-{ return this.getCursor() }-*/;
-
-  public final native Pos getCursor(String start) /*-{
-    return this.getCursor(start)
-  }-*/;
-
-  public final FromTo getSelectedRange() {
-    return FromTo.create(getCursor("start"), getCursor("end"));
-  }
-
-  public final native void setSelection(Pos p) /*-{ this.setSelection(p) }-*/;
-
-  public final native void setSelection(Pos anchor, Pos head) /*-{
-    this.setSelection(anchor, head)
-  }-*/;
-
-  public final native boolean somethingSelected() /*-{
-    return this.somethingSelected()
-  }-*/;
-
-  public final native void addKeyMap(KeyMap map) /*-{ this.addKeyMap(map) }-*/;
-
-  public final native void removeKeyMap(KeyMap map) /*-{ this.removeKeyMap(map) }-*/;
-
-  public final native LineHandle getLineHandle(int line) /*-{
-    return this.getLineHandle(line)
-  }-*/;
-
-  public final native LineHandle getLineHandleVisualStart(int line) /*-{
-    return this.getLineHandleVisualStart(line)
-  }-*/;
-
-  public final native int getLineNumber(LineHandle handle) /*-{
-    return this.getLineNumber(handle)
-  }-*/;
-
-  public final native void focus() /*-{
-    this.focus()
-  }-*/;
-
-  public final native Element getWrapperElement() /*-{
-    return this.getWrapperElement()
-  }-*/;
-
-  public final native Element getGutterElement() /*-{
-    return this.getGutterElement()
-  }-*/;
-
-  public final native Element sizer() /*-{
-    return this.display.sizer
-  }-*/;
-
-  public final native Element mover() /*-{
-    return this.display.mover
-  }-*/;
-
-  public final native Element measure() /*-{
-    return this.display.measure
-  }-*/;
-
-  public final native Element scrollbarV() /*-{
-    return this.display.scrollbars.vert.node;
-  }-*/;
-
-  public final native void execCommand(String cmd) /*-{
-    this.execCommand(cmd)
-  }-*/;
-
-  public static final native KeyMap getKeyMap(String name) /*-{
-    return $wnd.CodeMirror.keyMap[name];
-  }-*/;
-
-  public static final native void addKeyMap(String name, KeyMap km) /*-{
-    $wnd.CodeMirror.keyMap[name] = km
-  }-*/;
-
-  public static final native void normalizeKeyMap(KeyMap km) /*-{
-    $wnd.CodeMirror.normalizeKeyMap(km);
-  }-*/;
-
-  public static final native void addCommand(String name, CommandRunner runner) /*-{
-    $wnd.CodeMirror.commands[name] = function(cm) {
-      runner.@net.codemirror.lib.CodeMirror.CommandRunner::run(
-        Lnet/codemirror/lib/CodeMirror;)(cm);
-    };
-  }-*/;
-
-  public final native Vim vim() /*-{
-    return this;
-  }-*/;
-
-  public final DisplaySide side() {
-    return extras().side();
-  }
-
-  public final Extras extras() {
-    return Extras.get(this);
-  }
-
-  public final native LineHandle setGutterMarker(int line, String gutterId, Element value) /*-{
-    return this.setGutterMarker(line, gutterId, value);
-  }-*/;
-
-  public final native LineHandle setGutterMarker(
-      LineHandle line, String gutterId, Element value) /*-{
-    return this.setGutterMarker(line, gutterId, value);
-  }-*/;
-
-  public final native boolean hasSearchHighlight() /*-{
-    return this.state.search && !!this.state.search.query;
-  }-*/;
-
-  protected CodeMirror() {}
-
-  public static class Viewport extends JavaScriptObject {
-    public final native int from() /*-{ return this.from }-*/;
-
-    public final native int to() /*-{ return this.to }-*/;
-
-    public final boolean contains(int line) {
-      return from() <= line && line < to();
-    }
-
-    protected Viewport() {}
-  }
-
-  public static class LineHandle extends JavaScriptObject {
-    protected LineHandle() {}
-  }
-
-  public static class RegisteredHandler extends JavaScriptObject {
-    protected RegisteredHandler() {}
-  }
-
-  public interface EventHandler {
-    void handle(CodeMirror instance, NativeEvent event);
-  }
-
-  public interface RenderLineHandler {
-    void handle(CodeMirror instance, LineHandle handle, Element element);
-  }
-
-  public interface GutterClickHandler {
-    void handle(CodeMirror instance, int line, String gutter, NativeEvent clickEvent);
-  }
-
-  public interface BeforeSelectionChangeHandler {
-    void handle(CodeMirror instance, Pos anchor, Pos head);
-  }
-
-  public interface ChangesHandler {
-    void handle(CodeMirror instance);
-  }
-
-  public interface CommandRunner {
-    void run(CodeMirror instance);
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/CodeMirrorDoc.java b/gerrit-gwtui/src/main/java/net/codemirror/lib/CodeMirrorDoc.java
deleted file mode 100644
index be1af05..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/lib/CodeMirrorDoc.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.lib;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-/** The Doc object representing the content in a CodeMirror */
-public class CodeMirrorDoc extends JavaScriptObject {
-
-  public final native void replaceRange(String replacement, Pos from, Pos to) /*-{
-    this.replaceRange(replacement, from, to);
-  }-*/;
-
-  public final native void insertText(String insertion, Pos at) /*-{
-    this.replaceRange(insertion, at);
-  }-*/;
-
-  protected CodeMirrorDoc() {}
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/Configuration.java b/gerrit-gwtui/src/main/java/net/codemirror/lib/Configuration.java
deleted file mode 100644
index d37b70b..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/lib/Configuration.java
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.lib;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-/**
- * Simple map-like structure to pass configuration to CodeMirror.
- *
- * @see <a href="http://codemirror.net/doc/manual.html#config">CodeMirror config</a>
- * @see CodeMirror#create(com.google.gwt.dom.client.Element, Configuration)
- */
-public class Configuration extends JavaScriptObject {
-  public static Configuration create() {
-    return createObject().cast();
-  }
-
-  public final native Configuration set(String name, String val)
-      /*-{ this[name] = val; return this; }-*/ ;
-
-  public final native Configuration set(String name, int val)
-      /*-{ this[name] = val; return this; }-*/ ;
-
-  public final native Configuration set(String name, double val)
-      /*-{ this[name] = val; return this; }-*/ ;
-
-  public final native Configuration set(String name, boolean val)
-      /*-{ this[name] = val; return this; }-*/ ;
-
-  public final native Configuration set(String name, JavaScriptObject val)
-      /*-{ this[name] = val; return this; }-*/ ;
-
-  protected Configuration() {}
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/Extras.java b/gerrit-gwtui/src/main/java/net/codemirror/lib/Extras.java
deleted file mode 100644
index a5af703..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/lib/Extras.java
+++ /dev/null
@@ -1,221 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.lib;
-
-import static com.google.gwt.dom.client.Style.Display.INLINE_BLOCK;
-import static com.google.gwt.dom.client.Style.Unit.PX;
-import static net.codemirror.lib.CodeMirror.LineClassWhere.WRAP;
-import static net.codemirror.lib.CodeMirror.style;
-
-import com.google.gerrit.client.FormatUtil;
-import com.google.gerrit.client.RangeInfo;
-import com.google.gerrit.client.blame.BlameInfo;
-import com.google.gerrit.client.diff.DisplaySide;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.i18n.client.DateTimeFormat;
-import com.google.gwt.user.client.DOM;
-import java.util.Date;
-import java.util.Objects;
-import net.codemirror.lib.CodeMirror.LineHandle;
-
-/** Additional features added to CodeMirror by Gerrit Code Review. */
-public class Extras {
-  private static final String ANNOTATION_GUTTER_ID = "CodeMirror-lint-markers";
-  private static final BlameConfig C = GWT.create(BlameConfig.class);
-
-  static final native Extras get(CodeMirror c) /*-{ return c.gerritExtras }-*/;
-
-  private static native void set(CodeMirror c, Extras e) /*-{ c.gerritExtras = e }-*/;
-
-  static void attach(CodeMirror c) {
-    set(c, new Extras(c));
-  }
-
-  private final CodeMirror cm;
-  private Element margin;
-  private DisplaySide side;
-  private double charWidthPx;
-  private double lineHeightPx;
-  private LineHandle activeLine;
-  private boolean annotated;
-
-  private Extras(CodeMirror cm) {
-    this.cm = cm;
-  }
-
-  public DisplaySide side() {
-    return side;
-  }
-
-  public void side(DisplaySide s) {
-    side = s;
-  }
-
-  public double charWidthPx() {
-    if (charWidthPx <= 1) {
-      int len = 100;
-      StringBuilder s = new StringBuilder();
-      for (int i = 0; i < len; i++) {
-        s.append('m');
-      }
-
-      Element e = DOM.createSpan();
-      e.getStyle().setDisplay(INLINE_BLOCK);
-      e.setInnerText(s.toString());
-
-      cm.measure().appendChild(e);
-      charWidthPx = ((double) e.getOffsetWidth()) / len;
-      e.removeFromParent();
-    }
-    return charWidthPx;
-  }
-
-  public double lineHeightPx() {
-    if (lineHeightPx <= 1) {
-      Element p = DOM.createDiv();
-      int lines = 1;
-      for (int i = 0; i < lines; i++) {
-        Element e = DOM.createDiv();
-        p.appendChild(e);
-
-        Element pre = DOM.createElement("pre");
-        pre.setInnerText("gqyŚŻŹŃ");
-        e.appendChild(pre);
-      }
-
-      cm.measure().appendChild(p);
-      lineHeightPx = ((double) p.getOffsetHeight()) / lines;
-      p.removeFromParent();
-    }
-    return lineHeightPx;
-  }
-
-  public void lineLength(int columns) {
-    if (margin == null) {
-      margin = DOM.createDiv();
-      margin.setClassName(style().margin());
-      cm.mover().appendChild(margin);
-    }
-    margin.getStyle().setMarginLeft(columns * charWidthPx(), PX);
-  }
-
-  public void showTabs(boolean show) {
-    Element e = cm.getWrapperElement();
-    if (show) {
-      e.addClassName(style().showTabs());
-    } else {
-      e.removeClassName(style().showTabs());
-    }
-  }
-
-  public final boolean hasActiveLine() {
-    return activeLine != null;
-  }
-
-  public final LineHandle activeLine() {
-    return activeLine;
-  }
-
-  public final boolean activeLine(LineHandle line) {
-    if (Objects.equals(activeLine, line)) {
-      return false;
-    }
-
-    if (activeLine != null) {
-      cm.removeLineClass(activeLine, WRAP, style().activeLine());
-    }
-    activeLine = line;
-    cm.addLineClass(activeLine, WRAP, style().activeLine());
-    return true;
-  }
-
-  public final void clearActiveLine() {
-    if (activeLine != null) {
-      cm.removeLineClass(activeLine, WRAP, style().activeLine());
-      activeLine = null;
-    }
-  }
-
-  public boolean isAnnotated() {
-    return annotated;
-  }
-
-  public final void clearAnnotations() {
-    JsArrayString gutters = ((JsArrayString) JsArrayString.createArray());
-    cm.setOption("gutters", gutters);
-    annotated = false;
-  }
-
-  public final void setAnnotations(JsArray<BlameInfo> blameInfos) {
-    if (blameInfos.length() > 0) {
-      setBlameInfo(blameInfos);
-      JsArrayString gutters = ((JsArrayString) JsArrayString.createArray());
-      gutters.push(ANNOTATION_GUTTER_ID);
-      cm.setOption("gutters", gutters);
-      annotated = true;
-      DateTimeFormat format = DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_SHORT);
-      JsArray<LintLine> annotations = JsArray.createArray().cast();
-      for (BlameInfo blameInfo : Natives.asList(blameInfos)) {
-        for (RangeInfo range : Natives.asList(blameInfo.ranges())) {
-          Date commitTime = new Date(blameInfo.time() * 1000L);
-          String shortId = blameInfo.id().substring(0, 8);
-          String shortBlame =
-              C.shortBlameMsg(shortId, format.format(commitTime), blameInfo.author());
-          String detailedBlame =
-              C.detailedBlameMsg(
-                  blameInfo.id(),
-                  blameInfo.author(),
-                  FormatUtil.mediumFormat(commitTime),
-                  blameInfo.commitMsg());
-
-          annotations.push(
-              LintLine.create(shortBlame, detailedBlame, shortId, Pos.create(range.start() - 1)));
-        }
-      }
-      cm.setOption("lint", getAnnotation(annotations));
-    }
-  }
-
-  private native JavaScriptObject getAnnotation(JsArray<LintLine> annotations) /*-{
-     return {
-        getAnnotations: function(text, options, cm) { return annotations; }
-     };
-  }-*/;
-
-  public final native JsArray<BlameInfo> getBlameInfo() /*-{
-    return this.blameInfos;
-  }-*/;
-
-  public final native void setBlameInfo(JsArray<BlameInfo> blameInfos) /*-{
-    this['blameInfos'] = blameInfos;
-  }-*/;
-
-  public final void toggleAnnotation() {
-    toggleAnnotation(getBlameInfo());
-  }
-
-  public final void toggleAnnotation(JsArray<BlameInfo> blameInfos) {
-    if (isAnnotated()) {
-      clearAnnotations();
-    } else {
-      setAnnotations(blameInfos);
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/KeyMap.java b/gerrit-gwtui/src/main/java/net/codemirror/lib/KeyMap.java
deleted file mode 100644
index be1852f..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/lib/KeyMap.java
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.lib;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-/** Object that associates a key or key combination with a handler. */
-public class KeyMap extends JavaScriptObject {
-  public static KeyMap create() {
-    return createObject().cast();
-  }
-
-  public final native KeyMap on(String key, Runnable thunk) /*-{
-    this[key] = function() { $entry(thunk.@java.lang.Runnable::run()()); };
-    return this;
-  }-*/;
-
-  /** Do not handle inside of CodeMirror; instead push up the DOM tree. */
-  public final native KeyMap propagate(String key) /*-{
-    this[key] = false;
-    return this;
-  }-*/;
-
-  /** Delegate undefined keys to another KeyMap implementation. */
-  public final native KeyMap fallthrough(KeyMap m) /*-{
-    this.fallthrough = m;
-    return this;
-  }-*/;
-
-  protected KeyMap() {}
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/Lib.java b/gerrit-gwtui/src/main/java/net/codemirror/lib/Lib.java
deleted file mode 100644
index f205ef9..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/lib/Lib.java
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.lib;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.resources.client.ClientBundle;
-import com.google.gwt.resources.client.DataResource;
-import com.google.gwt.resources.client.DataResource.DoNotEmbed;
-import com.google.gwt.resources.client.ExternalTextResource;
-
-interface Lib extends ClientBundle {
-  Lib I = GWT.create(Lib.class);
-
-  @Source("cm.css")
-  ExternalTextResource css();
-
-  @Source("cm.js")
-  @DoNotEmbed
-  DataResource js();
-
-  @Source("style.css")
-  CodeMirror.Style style();
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/LineWidget.java b/gerrit-gwtui/src/main/java/net/codemirror/lib/LineWidget.java
deleted file mode 100644
index 4a15fd3..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/lib/LineWidget.java
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.lib;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-/** LineWidget objects used within CodeMirror. */
-public class LineWidget extends JavaScriptObject {
-  public final native void clear() /*-{ this.clear() }-*/;
-
-  public final native void changed() /*-{ this.changed() }-*/;
-
-  public final native void onRedraw(Runnable thunk) /*-{
-    this.on("redraw", $entry(function() {
-      thunk.@java.lang.Runnable::run()();
-    }))
-  }-*/;
-
-  public final native void onFirstRedraw(Runnable thunk) /*-{
-    var w = this;
-    var h = $entry(function() {
-      thunk.@java.lang.Runnable::run()();
-      w.off("redraw", h);
-    });
-    w.on("redraw", h);
-  }-*/;
-
-  protected LineWidget() {}
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/LintLine.java b/gerrit-gwtui/src/main/java/net/codemirror/lib/LintLine.java
deleted file mode 100644
index b0b2ae0..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/lib/LintLine.java
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.lib;
-
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.dom.client.StyleInjector;
-
-public class LintLine extends JavaScriptObject {
-  public static LintLine create(String shortMsg, String msg, String sev, Pos line) {
-    StyleInjector.inject(
-        ".CodeMirror-lint-marker-"
-            + sev
-            + " {\n"
-            + "  visibility: hidden;\n"
-            + "  text-overflow: ellipsis;\n"
-            + "  white-space: nowrap;\n"
-            + "  overflow: hidden;\n"
-            + "  position: relative;\n"
-            + "}\n"
-            + ".CodeMirror-lint-marker-"
-            + sev
-            + ":after {\n"
-            + "  content:'"
-            + shortMsg
-            + "';\n"
-            + "  visibility: visible;\n"
-            + "}");
-    return create(msg, sev, line, null);
-  }
-
-  public static native LintLine create(String msg, String sev, Pos f, Pos t) /*-{
-    return {
-      message : msg,
-      severity : sev,
-      from : f,
-      to : t
-    };
-  }-*/;
-
-  public final native String message() /*-{ return this.message; }-*/;
-
-  public final native String detailedMessage() /*-{ return this.message; }-*/;
-
-  public final native String severity() /*-{ return this.severity; }-*/;
-
-  public final native Pos from() /*-{ return this.from; }-*/;
-
-  public final native Pos to() /*-{ return this.to; }-*/;
-
-  protected LintLine() {}
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/Loader.java b/gerrit-gwtui/src/main/java/net/codemirror/lib/Loader.java
deleted file mode 100644
index 01bc7e2..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/lib/Loader.java
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.lib;
-
-import com.google.gerrit.client.rpc.CallbackGroup;
-import com.google.gwt.core.client.Callback;
-import com.google.gwt.core.client.ScriptInjector;
-import com.google.gwt.dom.client.ScriptElement;
-import com.google.gwt.dom.client.StyleInjector;
-import com.google.gwt.resources.client.ExternalTextResource;
-import com.google.gwt.resources.client.ResourceCallback;
-import com.google.gwt.resources.client.ResourceException;
-import com.google.gwt.resources.client.TextResource;
-import com.google.gwt.safehtml.shared.SafeUri;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-public class Loader {
-  private static native boolean isLibLoaded() /*-{ return $wnd.hasOwnProperty('CodeMirror'); }-*/;
-
-  static void initLibrary(AsyncCallback<Void> cb) {
-    if (isLibLoaded()) {
-      cb.onSuccess(null);
-      return;
-    }
-
-    CallbackGroup group = new CallbackGroup();
-    injectCss(Lib.I.css(), group.<Void>addEmpty());
-    injectScript(
-        Lib.I.js().getSafeUri(),
-        group.add(
-            new AsyncCallback<Void>() {
-              @Override
-              public void onSuccess(Void result) {
-                Vim.initKeyMap();
-              }
-
-              @Override
-              public void onFailure(Throwable caught) {}
-            }));
-    group.addListener(cb);
-    group.done();
-  }
-
-  private static void injectCss(ExternalTextResource css, AsyncCallback<Void> cb) {
-    try {
-      css.getText(
-          new ResourceCallback<TextResource>() {
-            @Override
-            public void onSuccess(TextResource resource) {
-              StyleInjector.inject(resource.getText());
-              Lib.I.style().ensureInjected();
-              cb.onSuccess(null);
-            }
-
-            @Override
-            public void onError(ResourceException e) {
-              cb.onFailure(e);
-            }
-          });
-    } catch (ResourceException e) {
-      cb.onFailure(e);
-    }
-  }
-
-  public static void injectScript(SafeUri js, AsyncCallback<Void> callback) {
-    final ScriptElement[] script = new ScriptElement[1];
-    script[0] =
-        ScriptInjector.fromUrl(js.asString())
-            .setWindow(ScriptInjector.TOP_WINDOW)
-            .setCallback(
-                new Callback<Void, Exception>() {
-                  @Override
-                  public void onSuccess(Void result) {
-                    script[0].removeFromParent();
-                    callback.onSuccess(result);
-                  }
-
-                  @Override
-                  public void onFailure(Exception reason) {
-                    callback.onFailure(reason);
-                  }
-                })
-            .inject()
-            .cast();
-  }
-
-  private Loader() {}
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/MergeView.java b/gerrit-gwtui/src/main/java/net/codemirror/lib/MergeView.java
deleted file mode 100644
index 38c3906..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/lib/MergeView.java
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.lib;
-
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.dom.client.Element;
-
-/** Object that represents a text marker within CodeMirror */
-public class MergeView extends JavaScriptObject {
-  public static MergeView create(Element p, Configuration cfg) {
-    MergeView mv = newMergeView(p, cfg);
-    Extras.attach(mv.leftOriginal());
-    Extras.attach(mv.editor());
-    return mv;
-  }
-
-  private static native MergeView newMergeView(Element p, Configuration cfg) /*-{
-    return $wnd.CodeMirror.MergeView(p, cfg);
-  }-*/;
-
-  public final native CodeMirror leftOriginal() /*-{
-    return this.leftOriginal();
-  }-*/;
-
-  public final native CodeMirror editor() /*-{
-    return this.editor();
-  }-*/;
-
-  public final native void setShowDifferences(boolean b) /*-{
-    this.setShowDifferences(b);
-  }-*/;
-
-  public final native Element getGapElement() /*-{
-    return $doc.getElementsByClassName("CodeMirror-merge-gap")[0];
-  }-*/;
-
-  protected MergeView() {}
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/Pos.java b/gerrit-gwtui/src/main/java/net/codemirror/lib/Pos.java
deleted file mode 100644
index 7f83b75..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/lib/Pos.java
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.lib;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-/** Pos (or {line, ch}) objects used within CodeMirror. */
-public class Pos extends JavaScriptObject {
-  public static final native Pos create(int line) /*-{
-    return $wnd.CodeMirror.Pos(line)
-  }-*/;
-
-  public static final native Pos create(int line, int ch) /*-{
-    return $wnd.CodeMirror.Pos(line, ch)
-  }-*/;
-
-  public final native void line(int l) /*-{ this.line = l }-*/;
-
-  public final native void ch(int c) /*-{ this.ch = c }-*/;
-
-  public final native int line() /*-{ return this.line }-*/;
-
-  public final native int ch() /*-{ return this.ch || 0 }-*/;
-
-  public final boolean equals(Pos o) {
-    return this == o || (line() == o.line() && ch() == o.ch());
-  }
-
-  protected Pos() {}
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/Rect.java b/gerrit-gwtui/src/main/java/net/codemirror/lib/Rect.java
deleted file mode 100644
index 1114403..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/lib/Rect.java
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.lib;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-/** {left, right, top, bottom} objects used within CodeMirror. */
-public class Rect extends JavaScriptObject {
-  public final native double left() /*-{ return this.left }-*/;
-
-  public final native double right() /*-{ return this.right }-*/;
-
-  public final native double top() /*-{ return this.top }-*/;
-
-  public final native double bottom() /*-{ return this.bottom }-*/;
-
-  protected Rect() {}
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/ScrollInfo.java b/gerrit-gwtui/src/main/java/net/codemirror/lib/ScrollInfo.java
deleted file mode 100644
index 432a60f..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/lib/ScrollInfo.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.lib;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-/** Returned by {@link CodeMirror#getScrollInfo()}. */
-public class ScrollInfo extends JavaScriptObject {
-  public final native double left() /*-{ return this.left }-*/;
-
-  public final native double top() /*-{ return this.top }-*/;
-
-  /**
-   * Pixel height of the full content being scrolled. This may only be an estimate given by
-   * CodeMirror. Line widgets further down in the document may not be measured, so line heights can
-   * be incorrect until drawn.
-   */
-  public final native double height() /*-{ return this.height }-*/;
-
-  public final native double width() /*-{ return this.width }-*/;
-
-  /** Visible height of the viewport, excluding scrollbars. */
-  public final native double clientHeight() /*-{ return this.clientHeight }-*/;
-
-  public final native double clientWidth() /*-{ return this.clientWidth }-*/;
-
-  protected ScrollInfo() {}
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/TextMarker.java b/gerrit-gwtui/src/main/java/net/codemirror/lib/TextMarker.java
deleted file mode 100644
index c3d248a..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/lib/TextMarker.java
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.lib;
-
-import com.google.gerrit.client.diff.CommentRange;
-import com.google.gwt.core.client.JavaScriptObject;
-
-/** Object that represents a text marker within CodeMirror */
-public class TextMarker extends JavaScriptObject {
-  public final native void clear() /*-{ this.clear(); }-*/;
-
-  public final native void changed() /*-{ this.changed(); }-*/;
-
-  public final native FromTo find() /*-{ return this.find(); }-*/;
-
-  public final native void on(String event, Runnable thunk)
-      /*-{ this.on(event, function(){$entry(thunk.@java.lang.Runnable::run()())}) }-*/ ;
-
-  protected TextMarker() {}
-
-  public static class FromTo extends JavaScriptObject {
-    public static final native FromTo create(Pos f, Pos t) /*-{
-      return {from: f, to: t}
-    }-*/;
-
-    public static FromTo create(CommentRange range) {
-      return create(
-          Pos.create(range.startLine() - 1, range.startCharacter()),
-          Pos.create(range.endLine() - 1, range.endCharacter()));
-    }
-
-    public final native Pos from() /*-{ return this.from }-*/;
-
-    public final native Pos to() /*-{ return this.to }-*/;
-
-    public final native void from(Pos f) /*-{ this.from = f }-*/;
-
-    public final native void to(Pos t) /*-{ this.to = t }-*/;
-
-    protected FromTo() {}
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/Vim.java b/gerrit-gwtui/src/main/java/net/codemirror/lib/Vim.java
deleted file mode 100644
index 06016ef..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/lib/Vim.java
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.lib;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-/**
- * Glue around the Vim emulation for {@link CodeMirror}.
- *
- * <p>As an instance {@code this} is actually the {@link CodeMirror} object. Class Vim is providing
- * a new namespace for Vim related methods that are associated with an editor.
- */
-public class Vim extends JavaScriptObject {
-  static void initKeyMap() {
-    KeyMap km = KeyMap.create();
-    for (String key : new String[] {"A", "C", "I", "O", "R", "U"}) {
-      km.propagate(key);
-      km.propagate("'" + key.toLowerCase() + "'");
-    }
-    for (String key :
-        new String[] {
-          "Ctrl-C", "Ctrl-O", "Ctrl-P", "Ctrl-S", "Ctrl-F", "Ctrl-B", "Ctrl-R",
-        }) {
-      km.propagate(key);
-    }
-    for (int i = 0; i <= 9; i++) {
-      km.propagate("Ctrl-" + i);
-    }
-    km.fallthrough(CodeMirror.getKeyMap("vim"));
-    CodeMirror.addKeyMap("vim_ro", km);
-
-    mapKey("j", "gj");
-    mapKey("k", "gk");
-    mapKey("Down", "gj");
-    mapKey("Up", "gk");
-    mapKey("<PageUp>", "<C-u>");
-    mapKey("<PageDown>", "<C-d>");
-  }
-
-  public static final native void mapKey(String alias, String actual) /*-{
-    $wnd.CodeMirror.Vim.map(alias, actual)
-  }-*/;
-
-  public final native void handleKey(String key) /*-{
-    $wnd.CodeMirror.Vim.handleKey(this, key)
-  }-*/;
-
-  public final native void handleEx(String exCommand) /*-{
-    $wnd.CodeMirror.Vim.handleEx(this, exCommand);
-  }-*/;
-
-  public final native boolean hasSearchHighlight() /*-{
-    var v = this.state.vim;
-    return v && v.searchState_ && !!v.searchState_.getOverlay();
-  }-*/;
-
-  protected Vim() {}
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/style.css b/gerrit-gwtui/src/main/java/net/codemirror/lib/style.css
deleted file mode 100644
index 022a800..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/lib/style.css
+++ /dev/null
@@ -1,124 +0,0 @@
-/* Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@external .CodeMirror;
-@external .CodeMirror-lines;
-@external .CodeMirror-linenumber;
-@external .CodeMirror-lint-markers;
-@external .CodeMirror-lint-tooltip;
-@external .CodeMirror-overlayscroll-horizontal;
-@external .CodeMirror-overlayscroll-vertical;
-@external .CodeMirror-scrollbar-filler;
-@external .cm-tab;
-@external .cm-searching;
-@external .cm-trailingspace;
-@external .unifiedLineNumber;
-
-/* Reduce margins around CodeMirror to save space. */
-.CodeMirror-lines {
-  padding: 0;
-}
-.CodeMirror pre {
-  padding: 0;
-  line-height: normal;
-}
-
-/* Minimum scrollbar bubble size even on large files. */
-.CodeMirror-overlayscroll-horizontal div {
-  min-width: 25px;
-}
-.CodeMirror-overlayscroll-vertical div {
-  min-height: 25px;
-}
-/* Ensure the scrollbars are not too narrow */
-.CodeMirror-overlayscroll-horizontal {
-  min-height: 12px;
-}
-.CodeMirror-overlayscroll-vertical {
-  min-width: 12px;
-}
-.CodeMirror-scrollbar-filler {
-  min-height: 12px;
-  min-width: 12px;
-}
-/* Stack the scrollbar so annotations can receive clicks. */
-.CodeMirror-overlayscroll-vertical {
-  z-index: inherit;
-}
-.CodeMirror-overlayscroll-horizontal div,
-.CodeMirror-overlayscroll-vertical div {
-  background-color: rgba(128, 128, 128, 0.50);
-  z-index: 8;
-}
-
-/* Highlight current line number in the line gutter. */
-.activeLine .CodeMirror-linenumber,
-.activeLine .unifiedLineNumber {
-  background-color: #bcf !important;
-  color: #000;
-}
-
-.showTabs .cm-tab:before {
-  position: absolute;
-  content: "\00bb";
-  color: #f00;
-}
-
-.cm-searching {
-  background-color: #ffa !important;
-}
-
-.cm-trailingspace {
-  background-color: red !important;
-}
-
-/* Line length margin displayed at NN columns to provide
- * a visual guide for length of any single line of code.
- */
-.margin {
-  position: absolute;
-  top: 0;
-  bottom: 0;
-  width: 0;
-  border-right: 1px dashed #ffa500;
-  z-index: 2;
-  cursor: text;
-}
-
-.CodeMirror-lint-markers {
-  width: 250px;
-}
-
-.CodeMirror-lint-tooltip {
-  background-color: infobackground;
-  border: 1px solid black;
-  border-radius: 4px 4px 4px 4px;
-  color: infotext;
-  font-family: monospace;
-  font-size: 10pt;
-  overflow: hidden;
-  padding: 2px 5px;
-  position: fixed;
-  white-space: pre;
-  white-space: pre-wrap;
-  z-index: 100;
-  max-width: 600px;
-  opacity: 0;
-  transition: opacity .4s;
-  -moz-transition: opacity .4s;
-  -webkit-transition: opacity .4s;
-  -o-transition: opacity .4s;
-  -ms-transition: opacity .4s;
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/mode/ModeInfo.java b/gerrit-gwtui/src/main/java/net/codemirror/mode/ModeInfo.java
deleted file mode 100644
index 9df066d..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/mode/ModeInfo.java
+++ /dev/null
@@ -1,270 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.mode;
-
-import static java.util.Comparator.comparing;
-
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.rpc.Natives;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.resources.client.DataResource;
-import com.google.gwt.safehtml.shared.SafeUri;
-import java.util.HashMap;
-import java.util.Map;
-
-/** Description of a CodeMirror language mode. */
-public class ModeInfo extends JavaScriptObject {
-  private static NativeMap<ModeInfo> byMime;
-  private static NativeMap<ModeInfo> byExt;
-
-  /** Map of names such as "clike" to URI for code download. */
-  private static final Map<String, SafeUri> modeUris = new HashMap<>();
-
-  static {
-    indexModes(
-        new DataResource[] {
-          Modes.I.apl(),
-          Modes.I.asciiarmor(),
-          Modes.I.asn_1(),
-          Modes.I.asterisk(),
-          Modes.I.brainfuck(),
-          Modes.I.clike(),
-          Modes.I.clojure(),
-          Modes.I.cmake(),
-          Modes.I.cobol(),
-          Modes.I.coffeescript(),
-          Modes.I.commonlisp(),
-          Modes.I.crystal(),
-          Modes.I.css(),
-          Modes.I.cypher(),
-          Modes.I.d(),
-          Modes.I.dart(),
-          Modes.I.diff(),
-          Modes.I.django(),
-          Modes.I.dockerfile(),
-          Modes.I.dtd(),
-          Modes.I.dylan(),
-          Modes.I.ebnf(),
-          Modes.I.ecl(),
-          Modes.I.eiffel(),
-          Modes.I.elm(),
-          Modes.I.erlang(),
-          Modes.I.factor(),
-          Modes.I.fcl(),
-          Modes.I.forth(),
-          Modes.I.fortran(),
-          Modes.I.gas(),
-          Modes.I.gerrit_commit(),
-          Modes.I.gfm(),
-          Modes.I.gherkin(),
-          Modes.I.go(),
-          Modes.I.groovy(),
-          Modes.I.haml(),
-          Modes.I.handlebars(),
-          Modes.I.haskell_literate(),
-          Modes.I.haskell(),
-          Modes.I.haxe(),
-          Modes.I.htmlembedded(),
-          Modes.I.htmlmixed(),
-          Modes.I.http(),
-          Modes.I.idl(),
-          Modes.I.javascript(),
-          Modes.I.jinja2(),
-          Modes.I.jsx(),
-          Modes.I.julia(),
-          Modes.I.livescript(),
-          Modes.I.lua(),
-          Modes.I.markdown(),
-          Modes.I.mathematica(),
-          Modes.I.mbox(),
-          Modes.I.mirc(),
-          Modes.I.mllike(),
-          Modes.I.modelica(),
-          Modes.I.mscgen(),
-          Modes.I.mumps(),
-          Modes.I.nginx(),
-          Modes.I.nsis(),
-          Modes.I.ntriples(),
-          Modes.I.octave(),
-          Modes.I.oz(),
-          Modes.I.pascal(),
-          Modes.I.pegjs(),
-          Modes.I.perl(),
-          Modes.I.php(),
-          Modes.I.pig(),
-          Modes.I.powershell(),
-          Modes.I.properties(),
-          Modes.I.protobuf(),
-          Modes.I.pug(),
-          Modes.I.puppet(),
-          Modes.I.python(),
-          Modes.I.q(),
-          Modes.I.r(),
-          Modes.I.rpm(),
-          Modes.I.rst(),
-          Modes.I.ruby(),
-          Modes.I.rust(),
-          Modes.I.sas(),
-          Modes.I.sass(),
-          Modes.I.scheme(),
-          Modes.I.shell(),
-          Modes.I.smalltalk(),
-          Modes.I.smarty(),
-          Modes.I.solr(),
-          Modes.I.soy(),
-          Modes.I.sparql(),
-          Modes.I.spreadsheet(),
-          Modes.I.sql(),
-          Modes.I.stex(),
-          Modes.I.stylus(),
-          Modes.I.swift(),
-          Modes.I.tcl(),
-          Modes.I.textile(),
-          Modes.I.tiddlywiki(),
-          Modes.I.tiki(),
-          Modes.I.toml(),
-          Modes.I.tornado(),
-          Modes.I.troff(),
-          Modes.I.ttcn_cfg(),
-          Modes.I.ttcn(),
-          Modes.I.turtle(),
-          Modes.I.twig(),
-          Modes.I.vb(),
-          Modes.I.vbscript(),
-          Modes.I.velocity(),
-          Modes.I.verilog(),
-          Modes.I.vhdl(),
-          Modes.I.vue(),
-          Modes.I.webidl(),
-          Modes.I.xml(),
-          Modes.I.xquery(),
-          Modes.I.yacas(),
-          Modes.I.yaml_frontmatter(),
-          Modes.I.yaml(),
-          Modes.I.z80(),
-        });
-
-    alias("application/x-httpd-php-open", "application/x-httpd-php");
-    alias("application/x-javascript", "application/javascript");
-    alias("application/x-shellscript", "text/x-sh");
-    alias("application/x-tcl", "text/x-tcl");
-    alias("text/typescript", "application/typescript");
-    alias("text/x-c", "text/x-csrc");
-    alias("text/x-c++hdr", "text/x-c++src");
-    alias("text/x-chdr", "text/x-csrc");
-    alias("text/x-h", "text/x-csrc");
-    alias("text/x-ini", "text/x-properties");
-    alias("text/x-java-source", "text/x-java");
-    alias("text/x-php", "application/x-httpd-php");
-    alias("text/x-scripttcl", "text/x-tcl");
-  }
-
-  /** All supported modes. */
-  public static native JsArray<ModeInfo> all() /*-{
-    return $wnd.CodeMirror.modeInfo
-  }-*/;
-
-  private static native void setAll(JsArray<ModeInfo> m) /*-{
-    $wnd.CodeMirror.modeInfo = m
-  }-*/;
-
-  /** Look up mode by primary or alternate MIME types. */
-  public static ModeInfo findModeByMIME(String mime) {
-    return byMime.get(mime);
-  }
-
-  public static SafeUri getModeScriptUri(String mode) {
-    return modeUris.get(mode);
-  }
-
-  /** Look up mode by MIME type or file extension from a path. */
-  public static ModeInfo findMode(String mime, String path) {
-    ModeInfo m = byMime.get(mime);
-    if (m != null) {
-      return m;
-    }
-
-    int s = path.lastIndexOf('/');
-    int d = path.lastIndexOf('.');
-    if (d == -1 || s > d) {
-      return null; // punt on "foo.src/bar" type paths.
-    }
-
-    if (byExt == null) {
-      byExt = NativeMap.create();
-      for (ModeInfo mode : Natives.asList(all())) {
-        for (String ext : Natives.asList(mode.ext())) {
-          byExt.put(ext, mode);
-        }
-      }
-    }
-    return byExt.get(path.substring(d + 1));
-  }
-
-  private static void alias(String serverMime, String toMime) {
-    ModeInfo mode = byMime.get(toMime);
-    if (mode != null) {
-      byMime.put(serverMime, mode);
-    }
-  }
-
-  private static void indexModes(DataResource[] all) {
-    for (DataResource r : all) {
-      modeUris.put(r.getName(), r.getSafeUri());
-    }
-
-    JsArray<ModeInfo> modeList = all();
-    modeList.push(gerrit_commit());
-
-    byMime = NativeMap.create();
-    JsArray<ModeInfo> filtered = JsArray.createArray().cast();
-    for (ModeInfo m : Natives.asList(modeList)) {
-      if (modeUris.containsKey(m.mode())) {
-        filtered.push(m);
-
-        for (String mimeType : Natives.asList(m.mimes())) {
-          byMime.put(mimeType, m);
-        }
-        byMime.put(m.mode(), m);
-      }
-    }
-    Natives.asList(filtered).sort(comparing(m -> m.name().toLowerCase()));
-    setAll(filtered);
-  }
-
-  /** Human readable name of the mode, such as "C++". */
-  public final native String name() /*-{ return this.name }-*/;
-
-  /** Internal CodeMirror name for {@code mode.js} file to load. */
-  public final native String mode() /*-{ return this.mode }-*/;
-
-  /** Primary MIME type to activate this mode. */
-  public final native String mime() /*-{ return this.mime }-*/;
-
-  /** Primary and additional MIME types that activate this mode. */
-  public final native JsArrayString mimes() /*-{ return this.mimes || [this.mime] }-*/;
-
-  private native JsArrayString ext() /*-{ return this.ext || [] }-*/;
-
-  protected ModeInfo() {}
-
-  private static native ModeInfo gerrit_commit() /*-{
-    return {name: "Git Commit Message",
-            mime: "text/x-gerrit-commit-message",
-            mode: "gerrit_commit"}
-  }-*/;
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/mode/ModeInjector.java b/gerrit-gwtui/src/main/java/net/codemirror/mode/ModeInjector.java
deleted file mode 100644
index 5fda608..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/mode/ModeInjector.java
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.mode;
-
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import net.codemirror.lib.Loader;
-
-public class ModeInjector {
-  private static boolean canLoad(String mode) {
-    return ModeInfo.getModeScriptUri(mode) != null;
-  }
-
-  private static native boolean isModeLoaded(String n)
-      /*-{ return $wnd.CodeMirror.modes.hasOwnProperty(n); }-*/ ;
-
-  private static native boolean isMimeLoaded(String n)
-      /*-{ return $wnd.CodeMirror.mimeModes.hasOwnProperty(n); }-*/ ;
-
-  private static native JsArrayString getDependencies(String n)
-      /*-{ return $wnd.CodeMirror.modes[n].dependencies || []; }-*/ ;
-
-  private final Set<String> loading = new HashSet<>(4);
-  private int pending;
-  private AsyncCallback<Void> appCallback;
-
-  public ModeInjector add(String name) {
-    if (name == null || isModeLoaded(name) || isMimeLoaded(name)) {
-      return this;
-    }
-
-    ModeInfo m = ModeInfo.findModeByMIME(name);
-    if (m != null) {
-      name = m.mode();
-    }
-
-    if (!canLoad(name)) {
-      Logger.getLogger("net.codemirror")
-          .log(Level.WARNING, "CodeMirror mode " + name + " not configured.");
-      return this;
-    }
-
-    loading.add(name);
-    return this;
-  }
-
-  public void inject(AsyncCallback<Void> appCallback) {
-    this.appCallback = appCallback;
-    for (String mode : loading) {
-      beginLoading(mode);
-    }
-    if (pending == 0) {
-      appCallback.onSuccess(null);
-    }
-  }
-
-  private void beginLoading(String mode) {
-    pending++;
-    Loader.injectScript(
-        ModeInfo.getModeScriptUri(mode),
-        new AsyncCallback<Void>() {
-          @Override
-          public void onSuccess(Void result) {
-            pending--;
-            ensureDependenciesAreLoaded(mode);
-            if (pending == 0) {
-              appCallback.onSuccess(null);
-            }
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            if (--pending == 0) {
-              appCallback.onFailure(caught);
-            }
-          }
-        });
-  }
-
-  private void ensureDependenciesAreLoaded(String mode) {
-    JsArrayString deps = getDependencies(mode);
-    for (int i = 0; i < deps.length(); i++) {
-      String d = deps.get(i);
-      if (loading.contains(d) || isModeLoaded(d)) {
-        continue;
-      }
-
-      if (!canLoad(d)) {
-        Logger.getLogger("net.codemirror")
-            .log(Level.SEVERE, "CodeMirror mode " + d + " needs " + d);
-        continue;
-      }
-
-      loading.add(d);
-      beginLoading(d);
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/mode/Modes.java b/gerrit-gwtui/src/main/java/net/codemirror/mode/Modes.java
deleted file mode 100644
index 2b87a34..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/mode/Modes.java
+++ /dev/null
@@ -1,510 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.mode;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.resources.client.ClientBundle;
-import com.google.gwt.resources.client.DataResource;
-import com.google.gwt.resources.client.DataResource.DoNotEmbed;
-
-public interface Modes extends ClientBundle {
-  Modes I = GWT.create(Modes.class);
-
-  @Source("apl.js")
-  @DoNotEmbed
-  DataResource apl();
-
-  @Source("asciiarmor.js")
-  @DoNotEmbed
-  DataResource asciiarmor();
-
-  @Source("asn.1.js")
-  @DoNotEmbed
-  DataResource asn_1();
-
-  @Source("asterisk.js")
-  @DoNotEmbed
-  DataResource asterisk();
-
-  @Source("brainfuck.js")
-  @DoNotEmbed
-  DataResource brainfuck();
-
-  @Source("clike.js")
-  @DoNotEmbed
-  DataResource clike();
-
-  @Source("clojure.js")
-  @DoNotEmbed
-  DataResource clojure();
-
-  @Source("cmake.js")
-  @DoNotEmbed
-  DataResource cmake();
-
-  @Source("cobol.js")
-  @DoNotEmbed
-  DataResource cobol();
-
-  @Source("coffeescript.js")
-  @DoNotEmbed
-  DataResource coffeescript();
-
-  @Source("commonlisp.js")
-  @DoNotEmbed
-  DataResource commonlisp();
-
-  @Source("crystal.js")
-  @DoNotEmbed
-  DataResource crystal();
-
-  @Source("css.js")
-  @DoNotEmbed
-  DataResource css();
-
-  @Source("cypher.js")
-  @DoNotEmbed
-  DataResource cypher();
-
-  @Source("d.js")
-  @DoNotEmbed
-  DataResource d();
-
-  @Source("dart.js")
-  @DoNotEmbed
-  DataResource dart();
-
-  @Source("diff.js")
-  @DoNotEmbed
-  DataResource diff();
-
-  @Source("django.js")
-  @DoNotEmbed
-  DataResource django();
-
-  @Source("dockerfile.js")
-  @DoNotEmbed
-  DataResource dockerfile();
-
-  @Source("dtd.js")
-  @DoNotEmbed
-  DataResource dtd();
-
-  @Source("dylan.js")
-  @DoNotEmbed
-  DataResource dylan();
-
-  @Source("ebnf.js")
-  @DoNotEmbed
-  DataResource ebnf();
-
-  @Source("ecl.js")
-  @DoNotEmbed
-  DataResource ecl();
-
-  @Source("eiffel.js")
-  @DoNotEmbed
-  DataResource eiffel();
-
-  @Source("elm.js")
-  @DoNotEmbed
-  DataResource elm();
-
-  @Source("erlang.js")
-  @DoNotEmbed
-  DataResource erlang();
-
-  @Source("factor.js")
-  @DoNotEmbed
-  DataResource factor();
-
-  @Source("fcl.js")
-  @DoNotEmbed
-  DataResource fcl();
-
-  @Source("forth.js")
-  @DoNotEmbed
-  DataResource forth();
-
-  @Source("fortran.js")
-  @DoNotEmbed
-  DataResource fortran();
-
-  @Source("gas.js")
-  @DoNotEmbed
-  DataResource gas();
-
-  @Source("gerrit/commit.js")
-  @DoNotEmbed
-  DataResource gerrit_commit();
-
-  @Source("gfm.js")
-  @DoNotEmbed
-  DataResource gfm();
-
-  @Source("gherkin.js")
-  @DoNotEmbed
-  DataResource gherkin();
-
-  @Source("go.js")
-  @DoNotEmbed
-  DataResource go();
-
-  @Source("groovy.js")
-  @DoNotEmbed
-  DataResource groovy();
-
-  @Source("haml.js")
-  @DoNotEmbed
-  DataResource haml();
-
-  @Source("handlebars.js")
-  @DoNotEmbed
-  DataResource handlebars();
-
-  @Source("haskell-literate.js")
-  @DoNotEmbed
-  DataResource haskell_literate();
-
-  @Source("haskell.js")
-  @DoNotEmbed
-  DataResource haskell();
-
-  @Source("haxe.js")
-  @DoNotEmbed
-  DataResource haxe();
-
-  @Source("htmlembedded.js")
-  @DoNotEmbed
-  DataResource htmlembedded();
-
-  @Source("htmlmixed.js")
-  @DoNotEmbed
-  DataResource htmlmixed();
-
-  @Source("http.js")
-  @DoNotEmbed
-  DataResource http();
-
-  @Source("idl.js")
-  @DoNotEmbed
-  DataResource idl();
-
-  @Source("javascript.js")
-  @DoNotEmbed
-  DataResource javascript();
-
-  @Source("jinja2.js")
-  @DoNotEmbed
-  DataResource jinja2();
-
-  @Source("jsx.js")
-  @DoNotEmbed
-  DataResource jsx();
-
-  @Source("julia.js")
-  @DoNotEmbed
-  DataResource julia();
-
-  @Source("livescript.js")
-  @DoNotEmbed
-  DataResource livescript();
-
-  @Source("lua.js")
-  @DoNotEmbed
-  DataResource lua();
-
-  @Source("markdown.js")
-  @DoNotEmbed
-  DataResource markdown();
-
-  @Source("mathematica.js")
-  @DoNotEmbed
-  DataResource mathematica();
-
-  @Source("mbox.js")
-  @DoNotEmbed
-  DataResource mbox();
-
-  @Source("mirc.js")
-  @DoNotEmbed
-  DataResource mirc();
-
-  @Source("mllike.js")
-  @DoNotEmbed
-  DataResource mllike();
-
-  @Source("modelica.js")
-  @DoNotEmbed
-  DataResource modelica();
-
-  @Source("mscgen.js")
-  @DoNotEmbed
-  DataResource mscgen();
-
-  @Source("mumps.js")
-  @DoNotEmbed
-  DataResource mumps();
-
-  @Source("nginx.js")
-  @DoNotEmbed
-  DataResource nginx();
-
-  @Source("nsis.js")
-  @DoNotEmbed
-  DataResource nsis();
-
-  @Source("ntriples.js")
-  @DoNotEmbed
-  DataResource ntriples();
-
-  @Source("octave.js")
-  @DoNotEmbed
-  DataResource octave();
-
-  @Source("oz.js")
-  @DoNotEmbed
-  DataResource oz();
-
-  @Source("pascal.js")
-  @DoNotEmbed
-  DataResource pascal();
-
-  @Source("pegjs.js")
-  @DoNotEmbed
-  DataResource pegjs();
-
-  @Source("perl.js")
-  @DoNotEmbed
-  DataResource perl();
-
-  @Source("php.js")
-  @DoNotEmbed
-  DataResource php();
-
-  @Source("pig.js")
-  @DoNotEmbed
-  DataResource pig();
-
-  @Source("powershell.js")
-  @DoNotEmbed
-  DataResource powershell();
-
-  @Source("properties.js")
-  @DoNotEmbed
-  DataResource properties();
-
-  @Source("protobuf.js")
-  @DoNotEmbed
-  DataResource protobuf();
-
-  @Source("pug.js")
-  @DoNotEmbed
-  DataResource pug();
-
-  @Source("puppet.js")
-  @DoNotEmbed
-  DataResource puppet();
-
-  @Source("python.js")
-  @DoNotEmbed
-  DataResource python();
-
-  @Source("q.js")
-  @DoNotEmbed
-  DataResource q();
-
-  @Source("r.js")
-  @DoNotEmbed
-  DataResource r();
-
-  @Source("rpm.js")
-  @DoNotEmbed
-  DataResource rpm();
-
-  @Source("rst.js")
-  @DoNotEmbed
-  DataResource rst();
-
-  @Source("ruby.js")
-  @DoNotEmbed
-  DataResource ruby();
-
-  @Source("rust.js")
-  @DoNotEmbed
-  DataResource rust();
-
-  @Source("sas.js")
-  @DoNotEmbed
-  DataResource sas();
-
-  @Source("sass.js")
-  @DoNotEmbed
-  DataResource sass();
-
-  @Source("scheme.js")
-  @DoNotEmbed
-  DataResource scheme();
-
-  @Source("shell.js")
-  @DoNotEmbed
-  DataResource shell();
-
-  @Source("sieve.js")
-  @DoNotEmbed
-  DataResource sieve();
-
-  @Source("slim.js")
-  @DoNotEmbed
-  DataResource slim();
-
-  @Source("smalltalk.js")
-  @DoNotEmbed
-  DataResource smalltalk();
-
-  @Source("smarty.js")
-  @DoNotEmbed
-  DataResource smarty();
-
-  @Source("solr.js")
-  @DoNotEmbed
-  DataResource solr();
-
-  @Source("soy.js")
-  @DoNotEmbed
-  DataResource soy();
-
-  @Source("sparql.js")
-  @DoNotEmbed
-  DataResource sparql();
-
-  @Source("spreadsheet.js")
-  @DoNotEmbed
-  DataResource spreadsheet();
-
-  @Source("sql.js")
-  @DoNotEmbed
-  DataResource sql();
-
-  @Source("stex.js")
-  @DoNotEmbed
-  DataResource stex();
-
-  @Source("stylus.js")
-  @DoNotEmbed
-  DataResource stylus();
-
-  @Source("swift.js")
-  @DoNotEmbed
-  DataResource swift();
-
-  @Source("tcl.js")
-  @DoNotEmbed
-  DataResource tcl();
-
-  @Source("textile.js")
-  @DoNotEmbed
-  DataResource textile();
-
-  @Source("tiddlywiki.js")
-  @DoNotEmbed
-  DataResource tiddlywiki();
-
-  @Source("tiki.js")
-  @DoNotEmbed
-  DataResource tiki();
-
-  @Source("toml.js")
-  @DoNotEmbed
-  DataResource toml();
-
-  @Source("tornado.js")
-  @DoNotEmbed
-  DataResource tornado();
-
-  @Source("troff.js")
-  @DoNotEmbed
-  DataResource troff();
-
-  @Source("ttcn-cfg.js")
-  @DoNotEmbed
-  DataResource ttcn_cfg();
-
-  @Source("ttcn.js")
-  @DoNotEmbed
-  DataResource ttcn();
-
-  @Source("turtle.js")
-  @DoNotEmbed
-  DataResource turtle();
-
-  @Source("twig.js")
-  @DoNotEmbed
-  DataResource twig();
-
-  @Source("vb.js")
-  @DoNotEmbed
-  DataResource vb();
-
-  @Source("vbscript.js")
-  @DoNotEmbed
-  DataResource vbscript();
-
-  @Source("velocity.js")
-  @DoNotEmbed
-  DataResource velocity();
-
-  @Source("verilog.js")
-  @DoNotEmbed
-  DataResource verilog();
-
-  @Source("vhdl.js")
-  @DoNotEmbed
-  DataResource vhdl();
-
-  @Source("vue.js")
-  @DoNotEmbed
-  DataResource vue();
-
-  @Source("webidl.js")
-  @DoNotEmbed
-  DataResource webidl();
-
-  @Source("xml.js")
-  @DoNotEmbed
-  DataResource xml();
-
-  @Source("xquery.js")
-  @DoNotEmbed
-  DataResource xquery();
-
-  @Source("yacas.js")
-  @DoNotEmbed
-  DataResource yacas();
-
-  @Source("yaml-frontmatter.js")
-  @DoNotEmbed
-  DataResource yaml_frontmatter();
-
-  @Source("yaml.js")
-  @DoNotEmbed
-  DataResource yaml();
-
-  @Source("z80.js")
-  @DoNotEmbed
-  DataResource z80();
-
-  // When adding a resource, update static initializer in ModeInfo.
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/mode/gerrit/commit.js b/gerrit-gwtui/src/main/java/net/codemirror/mode/gerrit/commit.js
deleted file mode 100644
index e1fe898..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/mode/gerrit/commit.js
+++ /dev/null
@@ -1,26 +0,0 @@
-CodeMirror.defineMode('gerrit_commit', function() {
-  var header = /^(Parent|Author|AuthorDate|Commit|CommitDate):/;
-  var id = /^Change-Id: I[0-9a-f]{40}/;
-  var footer = /^[A-Z][A-Za-z0-9-]+:/;
-  var sha1 = /\b[0-9a-f]{6,40}/;
-
-  return {
-    token: function(stream) {
-      if (stream.sol()) {
-        if (stream.match(header))
-          return 'keyword';
-        if (stream.match(id) || stream.match(footer))
-          return 'builtin';
-      }
-
-      stream.eatSpace();
-      if (stream.match(sha1))
-        return 'variable-2';
-      if (stream.match(/".*"/))
-        return 'string';
-      stream.next();
-      return null;
-    }
-  };
-});
-CodeMirror.defineMIME('text/x-gerrit-commit-message', 'gerrit_commit');
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/theme/ThemeLoader.java b/gerrit-gwtui/src/main/java/net/codemirror/theme/ThemeLoader.java
deleted file mode 100644
index 23039d4..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/theme/ThemeLoader.java
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.theme;
-
-import com.google.gerrit.extensions.client.Theme;
-import com.google.gwt.dom.client.StyleInjector;
-import com.google.gwt.resources.client.ExternalTextResource;
-import com.google.gwt.resources.client.ResourceCallback;
-import com.google.gwt.resources.client.ResourceException;
-import com.google.gwt.resources.client.TextResource;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import java.util.EnumSet;
-
-/** Dynamically loads a known CodeMirror theme's CSS */
-public class ThemeLoader {
-  private static final ExternalTextResource[] THEMES = {
-    Themes.I.day_3024(),
-    Themes.I.night_3024(),
-    Themes.I.abcdef(),
-    Themes.I.ambiance(),
-    Themes.I.base16_dark(),
-    Themes.I.base16_light(),
-    Themes.I.bespin(),
-    Themes.I.blackboard(),
-    Themes.I.cobalt(),
-    Themes.I.colorforth(),
-    Themes.I.dracula(),
-    Themes.I.eclipse(),
-    Themes.I.elegant(),
-    Themes.I.erlang_dark(),
-    Themes.I.hopscotch(),
-    Themes.I.icecoder(),
-    Themes.I.isotope(),
-    Themes.I.lesser_dark(),
-    Themes.I.liquibyte(),
-    Themes.I.material(),
-    Themes.I.mbo(),
-    Themes.I.mdn_like(),
-    Themes.I.midnight(),
-    Themes.I.monokai(),
-    Themes.I.neat(),
-    Themes.I.neo(),
-    Themes.I.night(),
-    Themes.I.paraiso_dark(),
-    Themes.I.paraiso_light(),
-    Themes.I.pastel_on_dark(),
-    Themes.I.railscasts(),
-    Themes.I.rubyblue(),
-    Themes.I.seti(),
-    Themes.I.solarized(),
-    Themes.I.the_matrix(),
-    Themes.I.tomorrow_night_bright(),
-    Themes.I.tomorrow_night_eighties(),
-    Themes.I.ttcn(),
-    Themes.I.twilight(),
-    Themes.I.vibrant_ink(),
-    Themes.I.xq_dark(),
-    Themes.I.xq_light(),
-    Themes.I.yeti(),
-    Themes.I.zenburn(),
-  };
-
-  private static final EnumSet<Theme> loaded = EnumSet.of(Theme.DEFAULT);
-
-  public static final void loadTheme(Theme theme, AsyncCallback<Void> cb) {
-    if (loaded.contains(theme)) {
-      cb.onSuccess(null);
-      return;
-    }
-
-    ExternalTextResource resource = findTheme(theme);
-    if (resource == null) {
-      cb.onFailure(new Exception("unknown theme " + theme));
-      return;
-    }
-
-    try {
-      resource.getText(
-          new ResourceCallback<TextResource>() {
-            @Override
-            public void onSuccess(TextResource resource) {
-              StyleInjector.inject(resource.getText());
-              loaded.add(theme);
-              cb.onSuccess(null);
-            }
-
-            @Override
-            public void onError(ResourceException e) {
-              cb.onFailure(e);
-            }
-          });
-    } catch (ResourceException e) {
-      cb.onFailure(e);
-    }
-  }
-
-  private static ExternalTextResource findTheme(Theme theme) {
-    for (ExternalTextResource r : THEMES) {
-      if (theme.name().toLowerCase().equals(r.getName())) {
-        return r;
-      }
-    }
-    return null;
-  }
-
-  private ThemeLoader() {}
-}
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/theme/Themes.java b/gerrit-gwtui/src/main/java/net/codemirror/theme/Themes.java
deleted file mode 100644
index cfe853f..0000000
--- a/gerrit-gwtui/src/main/java/net/codemirror/theme/Themes.java
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package net.codemirror.theme;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.resources.client.ClientBundle;
-import com.google.gwt.resources.client.ExternalTextResource;
-
-public interface Themes extends ClientBundle {
-  Themes I = GWT.create(Themes.class);
-
-  @Source("3024-day.css")
-  ExternalTextResource day_3024();
-
-  @Source("3024-night.css")
-  ExternalTextResource night_3024();
-
-  @Source("abcdef.css")
-  ExternalTextResource abcdef();
-
-  @Source("ambiance.css")
-  ExternalTextResource ambiance();
-
-  @Source("base16-dark.css")
-  ExternalTextResource base16_dark();
-
-  @Source("base16-light.css")
-  ExternalTextResource base16_light();
-
-  @Source("bespin.css")
-  ExternalTextResource bespin();
-
-  @Source("blackboard.css")
-  ExternalTextResource blackboard();
-
-  @Source("cobalt.css")
-  ExternalTextResource cobalt();
-
-  @Source("colorforth.css")
-  ExternalTextResource colorforth();
-
-  @Source("dracula.css")
-  ExternalTextResource dracula();
-
-  @Source("duotone-dark.css")
-  ExternalTextResource duotone_dark();
-
-  @Source("duotone-light.css")
-  ExternalTextResource duotone_light();
-
-  @Source("eclipse.css")
-  ExternalTextResource eclipse();
-
-  @Source("elegant.css")
-  ExternalTextResource elegant();
-
-  @Source("erlang-dark.css")
-  ExternalTextResource erlang_dark();
-
-  @Source("hopscotch.css")
-  ExternalTextResource hopscotch();
-
-  @Source("icecoder.css")
-  ExternalTextResource icecoder();
-
-  @Source("isotope.css")
-  ExternalTextResource isotope();
-
-  @Source("lesser-dark.css")
-  ExternalTextResource lesser_dark();
-
-  @Source("liquibyte.css")
-  ExternalTextResource liquibyte();
-
-  @Source("material.css")
-  ExternalTextResource material();
-
-  @Source("mbo.css")
-  ExternalTextResource mbo();
-
-  @Source("mdn-like.css")
-  ExternalTextResource mdn_like();
-
-  @Source("midnight.css")
-  ExternalTextResource midnight();
-
-  @Source("monokai.css")
-  ExternalTextResource monokai();
-
-  @Source("neat.css")
-  ExternalTextResource neat();
-
-  @Source("neo.css")
-  ExternalTextResource neo();
-
-  @Source("night.css")
-  ExternalTextResource night();
-
-  @Source("paraiso-dark.css")
-  ExternalTextResource paraiso_dark();
-
-  @Source("paraiso-light.css")
-  ExternalTextResource paraiso_light();
-
-  @Source("pastel-on-dark.css")
-  ExternalTextResource pastel_on_dark();
-
-  @Source("railscasts.css")
-  ExternalTextResource railscasts();
-
-  @Source("rubyblue.css")
-  ExternalTextResource rubyblue();
-
-  @Source("seti.css")
-  ExternalTextResource seti();
-
-  @Source("solarized.css")
-  ExternalTextResource solarized();
-
-  @Source("the-matrix.css")
-  ExternalTextResource the_matrix();
-
-  @Source("tomorrow-night-bright.css")
-  ExternalTextResource tomorrow_night_bright();
-
-  @Source("tomorrow-night-eighties.css")
-  ExternalTextResource tomorrow_night_eighties();
-
-  @Source("ttcn.css")
-  ExternalTextResource ttcn();
-
-  @Source("twilight.css")
-  ExternalTextResource twilight();
-
-  @Source("vibrant-ink.css")
-  ExternalTextResource vibrant_ink();
-
-  @Source("xq-dark.css")
-  ExternalTextResource xq_dark();
-
-  @Source("xq-light.css")
-  ExternalTextResource xq_light();
-
-  @Source("yeti.css")
-  ExternalTextResource yeti();
-
-  @Source("zenburn.css")
-  ExternalTextResource zenburn();
-
-  // When adding a resource, update:
-  // - static initializer in ThemeLoader
-  // - enum value in com.google.gerrit.extensions.common.Theme
-}
diff --git a/gerrit-gwtui/src/test/java/com/google/gerrit/client/change/ProjectChangeIdTest.java b/gerrit-gwtui/src/test/java/com/google/gerrit/client/change/ProjectChangeIdTest.java
deleted file mode 100644
index 1d47a82..0000000
--- a/gerrit-gwtui/src/test/java/com/google/gerrit/client/change/ProjectChangeIdTest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (C) 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.change;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-public class ProjectChangeIdTest {
-
-  @Rule public ExpectedException exception = ExpectedException.none();
-
-  @Test
-  public void emptyStringThrowsException() {
-    exception.expect(IllegalArgumentException.class);
-    exception.expectMessage(" is not a valid change identifier");
-    ProjectChangeId.create("");
-  }
-
-  @Test
-  public void noChangeIdThrowsException() {
-    exception.expect(IllegalArgumentException.class);
-    exception.expectMessage("some/path is not a valid change identifier");
-    ProjectChangeId.create("some/path");
-  }
-
-  @Test
-  public void noChangeButProjectIdThrowsException() {
-    exception.expect(IllegalArgumentException.class);
-    exception.expectMessage("some/+/path is not a valid change identifier");
-    ProjectChangeId.create("some/+/path");
-  }
-
-  @Test
-  public void project() {
-    assertThat(ProjectChangeId.create("test/+/123/some/path")).isEqualTo(result("test", 123));
-    assertThat(ProjectChangeId.create("test/+/123/some/path/")).isEqualTo(result("test", 123));
-    assertThat(ProjectChangeId.create("test/+/123/")).isEqualTo(result("test", 123));
-    assertThat(ProjectChangeId.create("test/+/123")).isEqualTo(result("test", 123));
-    // Numeric Project.NameKey
-    assertThat(ProjectChangeId.create("123/+/123")).isEqualTo(result("123", 123));
-    // Numeric Project.NameKey with ,edit as part of the name
-    assertThat(ProjectChangeId.create("123,edit/+/123")).isEqualTo(result("123,edit", 123));
-  }
-
-  @Test
-  public void noProject() {
-    assertThat(ProjectChangeId.create("123/some/path")).isEqualTo(result(null, 123));
-    assertThat(ProjectChangeId.create("123/some/path/")).isEqualTo(result(null, 123));
-    assertThat(ProjectChangeId.create("123/")).isEqualTo(result(null, 123));
-    assertThat(ProjectChangeId.create("123")).isEqualTo(result(null, 123));
-  }
-
-  @Test
-  public void editSuffix() {
-    assertThat(ProjectChangeId.create("123,edit/some/path")).isEqualTo(result(null, 123));
-    assertThat(ProjectChangeId.create("123,edit/")).isEqualTo(result(null, 123));
-    assertThat(ProjectChangeId.create("123,edit")).isEqualTo(result(null, 123));
-
-    assertThat(ProjectChangeId.create("test/+/123,edit/some/path")).isEqualTo(result("test", 123));
-    assertThat(ProjectChangeId.create("test/+/123,edit/")).isEqualTo(result("test", 123));
-    assertThat(ProjectChangeId.create("test/+/123,edit")).isEqualTo(result("test", 123));
-  }
-
-  private static ProjectChangeId result(@Nullable String project, int id) {
-    return new ProjectChangeId(
-        project == null ? null : new Project.NameKey(project), new Change.Id(id));
-  }
-}
diff --git a/gerrit-gwtui/src/test/java/com/google/gerrit/client/diff/LineMapperTest.java b/gerrit-gwtui/src/test/java/com/google/gerrit/client/diff/LineMapperTest.java
deleted file mode 100644
index fcc214e..0000000
--- a/gerrit-gwtui/src/test/java/com/google/gerrit/client/diff/LineMapperTest.java
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.diff;
-
-import static org.junit.Assert.assertEquals;
-
-import com.google.gerrit.client.diff.LineMapper.LineOnOtherInfo;
-import org.junit.Test;
-
-/** Unit tests for LineMapper */
-public class LineMapperTest {
-
-  @Test
-  public void appendCommon() {
-    LineMapper mapper = new LineMapper();
-    mapper.appendCommon(10);
-    assertEquals(10, mapper.getLineA());
-    assertEquals(10, mapper.getLineB());
-  }
-
-  @Test
-  public void appendInsert() {
-    LineMapper mapper = new LineMapper();
-    mapper.appendInsert(10);
-    assertEquals(0, mapper.getLineA());
-    assertEquals(10, mapper.getLineB());
-  }
-
-  @Test
-  public void appendDelete() {
-    LineMapper mapper = new LineMapper();
-    mapper.appendDelete(10);
-    assertEquals(10, mapper.getLineA());
-    assertEquals(0, mapper.getLineB());
-  }
-
-  @Test
-  public void findInCommon() {
-    LineMapper mapper = new LineMapper();
-    mapper.appendCommon(10);
-    assertEquals(new LineOnOtherInfo(9, true), mapper.lineOnOther(DisplaySide.A, 9));
-    assertEquals(new LineOnOtherInfo(9, true), mapper.lineOnOther(DisplaySide.B, 9));
-  }
-
-  @Test
-  public void findAfterCommon() {
-    LineMapper mapper = new LineMapper();
-    mapper.appendCommon(10);
-    assertEquals(new LineOnOtherInfo(10, true), mapper.lineOnOther(DisplaySide.A, 10));
-    assertEquals(new LineOnOtherInfo(10, true), mapper.lineOnOther(DisplaySide.B, 10));
-  }
-
-  @Test
-  public void findInInsertGap() {
-    LineMapper mapper = new LineMapper();
-    mapper.appendInsert(10);
-    assertEquals(new LineOnOtherInfo(-1, false), mapper.lineOnOther(DisplaySide.B, 9));
-  }
-
-  @Test
-  public void findAfterInsertGap() {
-    LineMapper mapper = new LineMapper();
-    mapper.appendInsert(10);
-    assertEquals(new LineOnOtherInfo(0, true), mapper.lineOnOther(DisplaySide.B, 10));
-    assertEquals(new LineOnOtherInfo(10, true), mapper.lineOnOther(DisplaySide.A, 0));
-  }
-
-  @Test
-  public void findInDeleteGap() {
-    LineMapper mapper = new LineMapper();
-    mapper.appendDelete(10);
-    assertEquals(new LineOnOtherInfo(-1, false), mapper.lineOnOther(DisplaySide.A, 9));
-  }
-
-  @Test
-  public void findAfterDeleteGap() {
-    LineMapper mapper = new LineMapper();
-    mapper.appendDelete(10);
-    assertEquals(new LineOnOtherInfo(0, true), mapper.lineOnOther(DisplaySide.A, 10));
-    assertEquals(new LineOnOtherInfo(10, true), mapper.lineOnOther(DisplaySide.B, 0));
-  }
-
-  @Test
-  public void replaceWithInsertInB() {
-    // 0 c c
-    // 1 a b
-    // 2 a b
-    // 3 - b
-    // 4 - b
-    // 5 c c
-    LineMapper mapper = new LineMapper();
-    mapper.appendCommon(1);
-    mapper.appendReplace(2, 4);
-    mapper.appendCommon(1);
-
-    assertEquals(4, mapper.getLineA());
-    assertEquals(6, mapper.getLineB());
-
-    assertEquals(new LineOnOtherInfo(1, true), mapper.lineOnOther(DisplaySide.B, 1));
-    assertEquals(new LineOnOtherInfo(3, true), mapper.lineOnOther(DisplaySide.B, 5));
-
-    assertEquals(new LineOnOtherInfo(2, true), mapper.lineOnOther(DisplaySide.B, 2));
-    assertEquals(new LineOnOtherInfo(2, false), mapper.lineOnOther(DisplaySide.B, 3));
-  }
-}
diff --git a/gerrit-plugin-gwtui/BUILD b/gerrit-plugin-gwtui/BUILD
deleted file mode 100644
index bfd977d..0000000
--- a/gerrit-plugin-gwtui/BUILD
+++ /dev/null
@@ -1,84 +0,0 @@
-package(default_visibility = ["//visibility:public"])
-
-load("//tools/bzl:java.bzl", "java_library2")
-
-SRCS = glob(["src/main/java/com/google/gerrit/**/*.java"])
-
-DEPS = ["//lib/gwt:user-neverlink"]
-
-java_binary(
-    name = "gwtui-api",
-    main_class = "Dummy",
-    runtime_deps = [
-        ":gwtui-api-lib",
-        "//gerrit-gwtui-common:client-lib",
-    ],
-)
-
-java_library2(
-    name = "gwtui-api-lib",
-    srcs = SRCS,
-    exported_deps = ["//gerrit-gwtui-common:client-lib"],
-    resources = glob(["src/main/**/*"]),
-    deps = DEPS + [
-        "//java/org/eclipse/jgit:libclient-src.jar",
-        "//java/org/eclipse/jgit:libEdit-src.jar",
-        "//java/com/google/gerrit/common:libclient-src.jar",
-        "//java/com/google/gerrit/extensions:libapi-src.jar",
-        "//java/com/google/gwtexpui/clippy:libclippy-src.jar",
-        "//java/com/google/gwtexpui/globalkey:libglobalkey-src.jar",
-        "//java/com/google/gwtexpui/progress:libprogress-src.jar",
-        "//java/com/google/gwtexpui/safehtml:libsafehtml-src.jar",
-        "//java/com/google/gwtexpui/user:libagent-src.jar",
-        "//gerrit-gwtui-common:libclient-src.jar",
-        "//java/com/google/gerrit/prettify:libclient-src.jar",
-        "//java/com/google/gerrit/reviewdb:libclient-src.jar",
-        "//lib/gwt:dev-neverlink",
-    ],
-)
-
-java_library2(
-    name = "gwtui-api-lib-neverlink",
-    srcs = SRCS,
-    exported_deps = ["//gerrit-gwtui-common:client-lib"],
-    neverlink = 1,  # we want this to be exported deps
-    resources = glob(["src/main/**/*"]),
-    deps = DEPS + ["//lib/gwt:dev"],
-)
-
-java_binary(
-    name = "gwtui-api-source",
-    main_class = "Dummy",
-    runtime_deps = [
-        ":libgwtui-api-lib-src.jar",
-        "//gerrit-gwtui-common:libclient-lib-src.jar",
-        "//java/com/google/gwtexpui/clippy:libclippy-src.jar",
-        "//java/com/google/gwtexpui/globalkey:libglobalkey-src.jar",
-        "//java/com/google/gwtexpui/progress:libprogress-src.jar",
-        "//java/com/google/gwtexpui/safehtml:libsafehtml-src.jar",
-        "//java/com/google/gwtexpui/user:libagent-src.jar",
-    ],
-)
-
-load("//tools/bzl:javadoc.bzl", "java_doc")
-
-java_doc(
-    name = "gwtui-api-javadoc",
-    libs = DEPS + [
-        ":gwtui-api-lib",
-        "//lib:gwtjsonrpc",
-        "//lib:gwtorm-client",
-        "//lib/gwt:dev",
-        "//gerrit-gwtui-common:client-lib",
-        "//java/com/google/gerrit/common:client",
-        "//java/com/google/gerrit/reviewdb:client",
-    ],
-    pkgs = [
-        "com.google.gerrit.plugin",
-        "com.google.gwtexpui.clippy",
-        "com.google.gwtexpui.globalkey",
-        "com.google.gwtexpui.safehtml",
-        "com.google.gwtexpui.user",
-    ],
-    title = "Gerrit Review GWT Extension API Documentation",
-)
diff --git a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/Plugin.gwt.xml b/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/Plugin.gwt.xml
deleted file mode 100644
index e0b0833..0000000
--- a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/Plugin.gwt.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<!--
- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<module>
-  <inherits name="com.google.gwt.json.JSON"/>
-  <inherits name='com.google.gerrit.GerritGwtUICommon'/>
-
-  <define-linker name="gerrit_plugin" class="com.google.gerrit.plugin.linker.GerritPluginLinker"/>
-  <add-linker name="gerrit_plugin"/>
-  <generate-with class="com.google.gerrit.plugin.rebind.PluginGenerator">
-    <when-type-assignable class="com.google.gerrit.plugin.client.Plugin"/>
-  </generate-with>
-  <source path="plugin/client"/>
-</module>
diff --git a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/FormatUtil.java b/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/FormatUtil.java
deleted file mode 100644
index 85bc9c3..0000000
--- a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/FormatUtil.java
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.plugin.client;
-
-import com.google.gerrit.client.AccountFormatter;
-import com.google.gerrit.client.DateFormatter;
-import com.google.gerrit.client.RelativeDateFormatter;
-import com.google.gerrit.client.info.AccountInfo;
-import java.util.Date;
-
-public class FormatUtil {
-  private static final AccountFormatter accountFormatter =
-      new AccountFormatter(Plugin.get().getServerInfo().user().anonymousCowardName());
-
-  /** Format a date using a really short format. */
-  public static String shortFormat(Date dt) {
-    return createDateFormatter().shortFormat(dt);
-  }
-
-  /** Format a date using a really short format. */
-  public static String shortFormatDayTime(Date dt) {
-    return createDateFormatter().shortFormatDayTime(dt);
-  }
-
-  /** Format a date using the locale's medium length format. */
-  public static String mediumFormat(Date dt) {
-    return createDateFormatter().mediumFormat(dt);
-  }
-
-  private static DateFormatter createDateFormatter() {
-    return new DateFormatter(Plugin.get().getUserPreferences());
-  }
-
-  /** Format a date using git log's relative date format. */
-  public static String relativeFormat(Date dt) {
-    return RelativeDateFormatter.format(dt);
-  }
-
-  /**
-   * Formats an account as a name and an email address.
-   *
-   * <p>Example output:
-   *
-   * <ul>
-   *   <li>{@code A U. Thor &lt;author@example.com&gt;}: full populated
-   *   <li>{@code A U. Thor (12)}: missing email address
-   *   <li>{@code Anonymous Coward &lt;author@example.com&gt;}: missing name
-   *   <li>{@code Anonymous Coward (12)}: missing name and email address
-   * </ul>
-   */
-  public static String nameEmail(AccountInfo info) {
-    return accountFormatter.nameEmail(info);
-  }
-
-  /**
-   * Formats an account name.
-   *
-   * <p>If the account has a full name, it returns only the full name. Otherwise it returns a longer
-   * form that includes the email address.
-   */
-  public static String name(AccountInfo info) {
-    return accountFormatter.name(info);
-  }
-}
diff --git a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/Plugin.java b/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/Plugin.java
deleted file mode 100644
index bfcb3d6..0000000
--- a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/Plugin.java
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.plugin.client;
-
-import com.google.gerrit.client.GerritUiExtensionPoint;
-import com.google.gerrit.client.info.AccountInfo;
-import com.google.gerrit.client.info.GeneralPreferences;
-import com.google.gerrit.client.info.ServerInfo;
-import com.google.gerrit.plugin.client.extension.Panel;
-import com.google.gerrit.plugin.client.screen.Screen;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JavaScriptObject;
-
-/**
- * Wrapper around the plugin instance exposed by Gerrit.
- *
- * <p>Listeners for events generated by the main UI must be registered through this instance.
- */
-public final class Plugin extends JavaScriptObject {
-  private static final Plugin self =
-      install(GWT.getModuleBaseURL() + GWT.getModuleName() + ".nocache.js");
-
-  /** Obtain the plugin instance wrapper. */
-  public static Plugin get() {
-    return self;
-  }
-
-  /** Installed name of the plugin. */
-  public String getName() {
-    return getPluginName();
-  }
-
-  /** Installed name of the plugin. */
-  public native String getPluginName() /*-{ return this.getPluginName() }-*/;
-
-  /** Navigate the UI to the screen identified by the token. */
-  public native void go(String token) /*-{ return this.go(token) }-*/;
-
-  /** Refresh the current UI. */
-  public native void refresh() /*-{ return this.refresh() }-*/;
-
-  /** Refresh Gerrit's menu bar. */
-  public native void refreshMenuBar() /*-{ return this.refreshMenuBar() }-*/;
-
-  /**
-   * @return the preferences of the currently signed in user, the default preferences if not signed
-   *     in
-   */
-  public native GeneralPreferences getUserPreferences() /*-{ return this.getUserPreferences() }-*/;
-
-  /** Refresh the user preferences of the current user. */
-  public native void refreshUserPreferences() /*-{ return this.refreshUserPreferences() }-*/;
-
-  /** @return the server info */
-  public native ServerInfo getServerInfo() /*-{ return this.getServerInfo() }-*/;
-
-  /** @return the current user */
-  public native AccountInfo getCurrentUser() /*-{ return this.getCurrentUser() }-*/;
-
-  /** Check if user is signed in. */
-  public native boolean isSignedIn() /*-{ return this.isSignedIn() }-*/;
-
-  /** Show message in Gerrit's ErrorDialog. */
-  public native void showError(String message) /*-{ return this.showError(message) }-*/;
-
-  /**
-   * Register a screen displayed at {@code /#/x/plugin/token}.
-   *
-   * @param token literal anchor token appearing after the plugin name. For regular expression
-   *     matching use {@code screenRegex()} .
-   * @param entry callback function invoked to create the screen widgets.
-   */
-  public void screen(String token, Screen.EntryPoint entry) {
-    screen(token, wrap(entry));
-  }
-
-  private native void screen(String t, JavaScriptObject e) /*-{ this.screen(t, e) }-*/;
-
-  /**
-   * Register a screen displayed at {@code /#/x/plugin/regex}.
-   *
-   * @param regex JavaScript {@code RegExp} expression to match the anchor token after the plugin
-   *     name. Matching groups are exposed through the {@code Screen} object passed into the {@code
-   *     Screen.EntryPoint}.
-   * @param entry callback function invoked to create the screen widgets.
-   */
-  public void screenRegex(String regex, Screen.EntryPoint entry) {
-    screenRegex(regex, wrap(entry));
-  }
-
-  private native void screenRegex(String p, JavaScriptObject e)
-      /*-{ this.screen(new $wnd.RegExp(p), e) }-*/ ;
-
-  /**
-   * Register a settings screen displayed at {@code /#/settings/x/plugin/token}.
-   *
-   * @param token literal anchor token appearing after the plugin name.
-   * @param entry callback function invoked to create the settings screen widgets.
-   */
-  public void settingsScreen(String token, String menu, Screen.EntryPoint entry) {
-    settingsScreen(token, menu, wrap(entry));
-  }
-
-  private native void settingsScreen(String t, String m, JavaScriptObject e)
-      /*-{ this.settingsScreen(t, m, e) }-*/ ;
-
-  /**
-   * Register a panel for a UI extension point.
-   *
-   * @param extensionPoint the UI extension point for which the panel should be registered.
-   * @param entry callback function invoked to create the panel widgets.
-   * @param name the name of the panel which can be used to specify panel ordering via project
-   *     config
-   */
-  public final void panel(
-      GerritUiExtensionPoint extensionPoint, Panel.EntryPoint entry, String name) {
-    panel(extensionPoint.name(), wrap(entry), name);
-  }
-
-  private native void panel(String i, JavaScriptObject e, String n) /*-{ this.panel(i, e, n) }-*/;
-
-  protected Plugin() {}
-
-  native void _initialized() /*-{ this._success = true }-*/;
-
-  native void _loaded() /*-{ this._loadedGwt() }-*/;
-
-  private static native Plugin install(String u) /*-{ return $wnd.Gerrit.installGwt(u) }-*/;
-
-  private static native JavaScriptObject wrap(Screen.EntryPoint b) /*-{
-    return $entry(function(c){
-      b.@com.google.gerrit.plugin.client.screen.Screen.EntryPoint::onLoad(Lcom/google/gerrit/plugin/client/screen/Screen;)(
-        @com.google.gerrit.plugin.client.screen.Screen::new(Lcom/google/gerrit/plugin/client/screen/Screen$Context;)(c));
-    });
-  }-*/;
-
-  private static native JavaScriptObject wrap(Panel.EntryPoint b) /*-{
-    return $entry(function(c){
-      b.@com.google.gerrit.plugin.client.extension.Panel.EntryPoint::onLoad(Lcom/google/gerrit/plugin/client/extension/Panel;)(
-        @com.google.gerrit.plugin.client.extension.Panel::new(Lcom/google/gerrit/plugin/client/extension/Panel$Context;)(c));
-    });
-  }-*/;
-}
diff --git a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/PluginEntryPoint.java b/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/PluginEntryPoint.java
deleted file mode 100644
index 808cda3..0000000
--- a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/PluginEntryPoint.java
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.plugin.client;
-
-import com.google.gwt.core.client.EntryPoint;
-
-/**
- * Base class for writing Gerrit Web UI plugins
- *
- * <p>Writing a plugin:
- *
- * <ol>
- *   <li>Declare subtype of Plugin
- *   <li>Bind WebUiPlugin to GwtPlugin implementation in Gerrit-Module
- * </ol>
- */
-public abstract class PluginEntryPoint implements EntryPoint {
-  /**
-   * The plugin entry point method, called automatically by loading a module that declares an
-   * implementing class as an entry point.
-   */
-  public abstract void onPluginLoad();
-
-  @Override
-  public final void onModuleLoad() {
-    Plugin self = Plugin.get();
-    try {
-      onPluginLoad();
-      self._initialized();
-    } finally {
-      self._loaded();
-    }
-  }
-}
diff --git a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/extension/Panel.java b/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/extension/Panel.java
deleted file mode 100644
index 8ee6d0e..0000000
--- a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/extension/Panel.java
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.plugin.client.extension;
-
-import com.google.gerrit.client.GerritUiExtensionPoint;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.user.client.ui.SimplePanel;
-
-/**
- * Panel that extends a Gerrit core screen contributed by this plugin.
- *
- * <p>Panel should be registered early at module load:
- *
- * <pre>
- * &#064;Override
- * public void onModuleLoad() {
- *   Plugin.get().panel(GerritUiExtensionPoint.CHANGE_SCREEN_BELOW_CHANGE_INFO_BLOCK,
- *       new Panel.EntryPoint() {
- *         &#064;Override
- *         public void onLoad(Panel panel) {
- *           panel.setWidget(new Label(&quot;World&quot;));
- *         }
- *       });
- * }
- * </pre>
- */
-public class Panel extends SimplePanel {
-  /** Initializes a panel for display. */
-  public interface EntryPoint {
-    /**
-     * Invoked when the panel has been created.
-     *
-     * <p>The implementation should create a single widget to define the content of this panel and
-     * add it to the passed panel instance.
-     *
-     * <p>To use multiple widgets, compose them in panels such as {@code FlowPanel} and add only the
-     * top level widget to the panel.
-     *
-     * <p>The panel is already attached to the browser DOM. Any widgets added to the screen will
-     * immediately receive {@code onLoad()}. GWT will fire {@code onUnload()} when the panel is
-     * removed from the UI, generally caused by the user navigating to another screen.
-     *
-     * @param panel panel that will contain the panel widget.
-     */
-    void onLoad(Panel panel);
-  }
-
-  static final class Context extends JavaScriptObject {
-    native Element body() /*-{ return this.body }-*/;
-
-    native String get(String k) /*-{ return this.p[k]; }-*/;
-
-    native int getInt(String k, int d) /*-{
-      return this.p.hasOwnProperty(k) ? this.p[k] : d
-    }-*/;
-
-    native int getBoolean(String k, boolean d) /*-{
-      return this.p.hasOwnProperty(k) ? this.p[k] : d
-    }-*/;
-
-    native JavaScriptObject getObject(String k) /*-{ return this.p[k]; }-*/;
-
-    native void detach(Panel p) /*-{
-      this.onUnload($entry(function(){
-        p.@com.google.gwt.user.client.ui.Widget::onDetach()();
-      }));
-    }-*/;
-
-    protected Context() {}
-  }
-
-  private final Context ctx;
-
-  Panel(Context ctx) {
-    super(ctx.body());
-    this.ctx = ctx;
-    onAttach();
-    ctx.detach(this);
-  }
-
-  public String get(GerritUiExtensionPoint.Key key) {
-    return ctx.get(key.name());
-  }
-
-  public int getInt(GerritUiExtensionPoint.Key key, int defaultValue) {
-    return ctx.getInt(key.name(), defaultValue);
-  }
-
-  public int getBoolean(GerritUiExtensionPoint.Key key, boolean defaultValue) {
-    return ctx.getBoolean(key.name(), defaultValue);
-  }
-
-  public JavaScriptObject getObject(GerritUiExtensionPoint.Key key) {
-    return ctx.getObject(key.name());
-  }
-}
diff --git a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/rpc/NoContent.java b/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/rpc/NoContent.java
deleted file mode 100644
index 9ff4fed..0000000
--- a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/rpc/NoContent.java
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.plugin.client.rpc;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-public class NoContent extends JavaScriptObject {
-  protected NoContent() {}
-}
diff --git a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/rpc/RestApi.java b/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/rpc/RestApi.java
deleted file mode 100644
index 86791f8..0000000
--- a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/rpc/RestApi.java
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.plugin.client.rpc;
-
-import com.google.gerrit.client.rpc.NativeString;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.http.client.URL;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-public class RestApi {
-  private final StringBuilder path;
-  private boolean hasQueryParams;
-
-  public RestApi(String name) {
-    path = new StringBuilder();
-    path.append(name);
-  }
-
-  public RestApi view(String name) {
-    return idRaw(name);
-  }
-
-  public RestApi view(String pluginName, String name) {
-    return idRaw(pluginName + "~" + name);
-  }
-
-  public RestApi id(String id) {
-    return idRaw(URL.encodePathSegment(id));
-  }
-
-  public RestApi id(int id) {
-    return idRaw(Integer.toString(id));
-  }
-
-  public RestApi idRaw(String name) {
-    if (hasQueryParams) {
-      throw new IllegalStateException();
-    }
-    if (path.charAt(path.length() - 1) != '/') {
-      path.append('/');
-    }
-    path.append(name);
-    return this;
-  }
-
-  public RestApi addParameter(String name, String value) {
-    return addParameterRaw(name, URL.encodeQueryString(value));
-  }
-
-  public RestApi addParameter(String name, String... value) {
-    for (String val : value) {
-      addParameter(name, val);
-    }
-    return this;
-  }
-
-  public RestApi addParameterTrue(String name) {
-    return addParameterRaw(name, null);
-  }
-
-  public RestApi addParameter(String name, boolean value) {
-    return addParameterRaw(name, value ? "t" : "f");
-  }
-
-  public RestApi addParameter(String name, int value) {
-    return addParameterRaw(name, String.valueOf(value));
-  }
-
-  public RestApi addParameter(String name, Enum<?> value) {
-    return addParameterRaw(name, value.name());
-  }
-
-  public RestApi addParameterRaw(String name, String value) {
-    if (hasQueryParams) {
-      path.append("&");
-    } else {
-      path.append("?");
-      hasQueryParams = true;
-    }
-    path.append(name);
-    if (value != null) {
-      path.append("=").append(value);
-    }
-    return this;
-  }
-
-  public String path() {
-    return path.toString();
-  }
-
-  public <T extends JavaScriptObject> void get(AsyncCallback<T> cb) {
-    get(path(), wrap(cb));
-  }
-
-  public void getString(AsyncCallback<String> cb) {
-    get(NativeString.unwrap(cb));
-  }
-
-  private static native void get(String p, JavaScriptObject r) /*-{ $wnd.Gerrit.get_raw(p, r) }-*/;
-
-  public <T extends JavaScriptObject> void put(AsyncCallback<T> cb) {
-    put(path(), wrap(cb));
-  }
-
-  private static native void put(String p, JavaScriptObject r) /*-{ $wnd.Gerrit.put_raw(p, r) }-*/;
-
-  public <T extends JavaScriptObject> void put(String content, AsyncCallback<T> cb) {
-    put(path(), content, wrap(cb));
-  }
-
-  private static native void put(String p, String c, JavaScriptObject r)
-      /*-{ $wnd.Gerrit.put_raw(p, c, r) }-*/ ;
-
-  public <T extends JavaScriptObject> void put(JavaScriptObject content, AsyncCallback<T> cb) {
-    put(path(), content, wrap(cb));
-  }
-
-  private static native void put(String p, JavaScriptObject c, JavaScriptObject r)
-      /*-{ $wnd.Gerrit.put_raw(p, c, r) }-*/ ;
-
-  public <T extends JavaScriptObject> void post(String content, AsyncCallback<T> cb) {
-    post(path(), content, wrap(cb));
-  }
-
-  private static native void post(String p, String c, JavaScriptObject r)
-      /*-{ $wnd.Gerrit.post_raw(p, c, r) }-*/ ;
-
-  public <T extends JavaScriptObject> void post(JavaScriptObject content, AsyncCallback<T> cb) {
-    post(path(), content, wrap(cb));
-  }
-
-  private static native void post(String p, JavaScriptObject c, JavaScriptObject r)
-      /*-{ $wnd.Gerrit.post_raw(p, c, r) }-*/ ;
-
-  public void delete(AsyncCallback<NoContent> cb) {
-    delete(path(), wrap(cb));
-  }
-
-  private static native void delete(String p, JavaScriptObject r)
-      /*-{ $wnd.Gerrit.del_raw(p, r) }-*/ ;
-
-  private static native <T extends JavaScriptObject> JavaScriptObject wrap(
-      AsyncCallback<T> b) /*-{
-    return function(r) {
-      b.@com.google.gwt.user.client.rpc.AsyncCallback::onSuccess(Ljava/lang/Object;)(r)
-    }
-  }-*/;
-}
diff --git a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/screen/Screen.java b/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/screen/Screen.java
deleted file mode 100644
index 226ac48..0000000
--- a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/screen/Screen.java
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.plugin.client.screen;
-
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.user.client.ui.SimplePanel;
-import com.google.gwt.user.client.ui.Widget;
-
-/**
- * Screen contributed by this plugin.
- *
- * <p>Screens should be registered early at module load:
- *
- * <pre>
- * &#064;Override
- * public void onModuleLoad() {
- *   Plugin.get().screen(&quot;hi&quot;, new Screen.EntryPoint() {
- *     &#064;Override
- *     public void onLoad(Screen screen) {
- *       screen.setPageTitle(&quot;Hi&quot;);
- *       screen.show(new Label(&quot;World&quot;));
- *     }
- *   });
- * }
- * </pre>
- */
-public final class Screen extends SimplePanel {
-  /** Initializes a screen for display. */
-  public interface EntryPoint {
-    /**
-     * Invoked when the screen has been created, but not yet displayed.
-     *
-     * <p>The implementation should create a single widget to define the content of this screen and
-     * added it to the passed screen instance. When the screen is ready to be displayed, call {@link
-     * Screen#show()}.
-     *
-     * <p>To use multiple widgets, compose them in panels such as {@code FlowPanel} and add only the
-     * top level widget to the screen.
-     *
-     * <p>The screen is already attached to the browser DOM in an invisible area. Any widgets added
-     * to the screen will immediately receive {@code onLoad()}. GWT will fire {@code onUnload()}
-     * when the screen is removed from the UI, generally caused by the user navigating to another
-     * screen.
-     *
-     * @param screen panel that will contain the screen widget.
-     */
-    void onLoad(Screen screen);
-  }
-
-  static final class Context extends JavaScriptObject {
-    native Element body() /*-{ return this.body }-*/;
-
-    native JsArrayString token_match() /*-{ return this.token_match }-*/;
-
-    native void show() /*-{ this.show() }-*/;
-
-    native void setTitle(String t) /*-{ this.setTitle(t) }-*/;
-
-    native void setWindowTitle(String t) /*-{ this.setWindowTitle(t) }-*/;
-
-    native void detach(Screen s) /*-{
-      this.onUnload($entry(function(){
-        s.@com.google.gwt.user.client.ui.Widget::onDetach()();
-      }));
-    }-*/;
-
-    protected Context() {}
-  }
-
-  private final Context ctx;
-
-  Screen(Context ctx) {
-    super(ctx.body());
-    this.ctx = ctx;
-    onAttach();
-    ctx.detach(this);
-  }
-
-  /** @return the token suffix after {@code "/#/x/plugin-name/"}. */
-  public String getToken() {
-    return getToken(0);
-  }
-
-  /**
-   * @param group groups range from 1 to {@code getTokenGroups() - 1}. Token group 0 is the entire
-   *     token, see {@link #getToken()}.
-   * @return the token from the regex match group.
-   */
-  public String getToken(int group) {
-    return ctx.token_match().get(group);
-  }
-
-  /** @return total number of token groups. */
-  public int getTokenGroups() {
-    return ctx.token_match().length();
-  }
-
-  /**
-   * Set the page title text; appears above the widget.
-   *
-   * @param titleText text to display above the widget.
-   */
-  public void setPageTitle(String titleText) {
-    ctx.setTitle(titleText);
-  }
-
-  /**
-   * Set the window title text; appears in the browser window title bar.
-   *
-   * @param titleText text to display in the window title bar.
-   */
-  public void setWindowTitle(String titleText) {
-    ctx.setWindowTitle(titleText);
-  }
-
-  /**
-   * Add the widget and immediately show the screen.
-   *
-   * @param w child containing the content.
-   */
-  public void show(Widget w) {
-    setWidget(w);
-    ctx.show();
-  }
-
-  /** Show this screen in the web interface. */
-  public void show() {
-    ctx.show();
-  }
-}
diff --git a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/ui/GroupSuggestOracle.java b/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/ui/GroupSuggestOracle.java
deleted file mode 100644
index df5be2c..0000000
--- a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/client/ui/GroupSuggestOracle.java
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.plugin.client.ui;
-
-import com.google.gerrit.client.rpc.NativeMap;
-import com.google.gerrit.client.ui.HighlightSuggestion;
-import com.google.gerrit.plugin.client.rpc.RestApi;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.SuggestOracle;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/** A {@code SuggestOracle} for groups. */
-public class GroupSuggestOracle extends SuggestOracle {
-
-  private final int chars;
-
-  /** @param chars minimum chars to start suggesting. */
-  public GroupSuggestOracle(int chars) {
-    this.chars = chars;
-  }
-
-  @Override
-  public boolean isDisplayStringHTML() {
-    return true;
-  }
-
-  @Override
-  public void requestSuggestions(Request req, Callback done) {
-    if (req.getQuery().length() < chars) {
-      responseEmptySuggestion(req, done);
-      return;
-    }
-    RestApi rest = new RestApi("/groups/").addParameter("suggest", req.getQuery());
-    if (req.getLimit() > 0) {
-      rest.addParameter("n", req.getLimit());
-    }
-    rest.get(
-        new AsyncCallback<NativeMap<JavaScriptObject>>() {
-          @Override
-          public void onSuccess(NativeMap<JavaScriptObject> result) {
-            List<String> keys = result.sortedKeys();
-            List<Suggestion> suggestions = new ArrayList<>(keys.size());
-            for (String g : keys) {
-              suggestions.add(new HighlightSuggestion(req.getQuery(), g));
-            }
-            done.onSuggestionsReady(req, new Response(suggestions));
-          }
-
-          @Override
-          public void onFailure(Throwable caught) {
-            responseEmptySuggestion(req, done);
-          }
-        });
-  }
-
-  private static void responseEmptySuggestion(Request req, Callback done) {
-    List<Suggestion> empty = Collections.emptyList();
-    done.onSuggestionsReady(req, new Response(empty));
-  }
-}
diff --git a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/linker/GerritPluginLinker.java b/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/linker/GerritPluginLinker.java
deleted file mode 100644
index 18f6e54..0000000
--- a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/linker/GerritPluginLinker.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.plugin.linker;
-
-import com.google.gwt.core.ext.LinkerContext;
-import com.google.gwt.core.linker.CrossSiteIframeLinker;
-
-/** Finalizes the module manifest file with the selection script. */
-public final class GerritPluginLinker extends CrossSiteIframeLinker {
-  @Override
-  public String getDescription() {
-    return "Gerrit GWT UI plugin";
-  }
-
-  @Override
-  protected String getJsComputeUrlForResource(LinkerContext context) {
-    return "com/google/gerrit/linker/computeUrlForPluginResource.js";
-  }
-}
diff --git a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/rebind/PluginGenerator.java b/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/rebind/PluginGenerator.java
deleted file mode 100644
index ba14556..0000000
--- a/gerrit-plugin-gwtui/src/main/java/com/google/gerrit/plugin/rebind/PluginGenerator.java
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-// Copyright 2008 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.plugin.rebind;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.ext.Generator;
-import com.google.gwt.core.ext.GeneratorContext;
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.typeinfo.JClassType;
-import com.google.gwt.core.ext.typeinfo.TypeOracle;
-import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
-import com.google.gwt.user.rebind.SourceWriter;
-import java.io.PrintWriter;
-
-/**
- * Write the top layer in the Gadget bootstrap sandwich and generate a stub manifest that will be
- * completed by the linker.
- *
- * <p>Based on gwt-gadgets GadgetGenerator class
- */
-public class PluginGenerator extends Generator {
-  @Override
-  public String generate(TreeLogger logger, GeneratorContext context, String typeName)
-      throws UnableToCompleteException {
-
-    // The TypeOracle knows about all types in the type system
-    TypeOracle typeOracle = context.getTypeOracle();
-
-    // Get a reference to the type that the generator should implement
-    JClassType sourceType = typeOracle.findType(typeName);
-
-    // Ensure that the requested type exists
-    if (sourceType == null) {
-      logger.log(TreeLogger.ERROR, "Could not find requested typeName", null);
-      throw new UnableToCompleteException();
-    }
-
-    // Make sure the Gadget type is correctly defined
-    validateType(logger, sourceType);
-
-    // Pick a name for the generated class to not conflict.
-    String generatedSimpleSourceName = sourceType.getSimpleSourceName() + "PluginImpl";
-
-    // Begin writing the generated source.
-    ClassSourceFileComposerFactory f =
-        new ClassSourceFileComposerFactory(
-            sourceType.getPackage().getName(), generatedSimpleSourceName);
-    f.addImport(GWT.class.getName());
-    f.setSuperclass(typeName);
-
-    // All source gets written through this Writer
-    PrintWriter out =
-        context.tryCreate(logger, sourceType.getPackage().getName(), generatedSimpleSourceName);
-
-    // If an implementation already exists, we don't need to do any work
-    if (out != null) {
-
-      // We really use a SourceWriter since it's convenient
-      SourceWriter sw = f.createSourceWriter(context, out);
-      sw.commit(logger);
-    }
-
-    return f.getCreatedClassName();
-  }
-
-  protected void validateType(TreeLogger logger, JClassType type) throws UnableToCompleteException {
-    if (!type.isDefaultInstantiable()) {
-      logger.log(TreeLogger.ERROR, "Plugin types must be default instantiable", null);
-      throw new UnableToCompleteException();
-    }
-  }
-}
diff --git a/gerrit-plugin-gwtui/src/main/resources/com/google/gerrit/linker/computeUrlForPluginResource.js b/gerrit-plugin-gwtui/src/main/resources/com/google/gerrit/linker/computeUrlForPluginResource.js
deleted file mode 100644
index 3e20e94..0000000
--- a/gerrit-plugin-gwtui/src/main/resources/com/google/gerrit/linker/computeUrlForPluginResource.js
+++ /dev/null
@@ -1,3 +0,0 @@
-function computeUrlForResource(resource) {
-  return __MODULE_FUNC__.__moduleBase + resource;
-}
diff --git a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index a4b5a94..8c64aa9 100644
--- a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -40,7 +40,6 @@
 import com.google.gerrit.acceptance.testsuite.account.TestSshKeys;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.common.data.AccessSection;
-import com.google.gerrit.common.data.ContributorAgreement;
 import com.google.gerrit.common.data.GroupDescription;
 import com.google.gerrit.common.data.GroupReference;
 import com.google.gerrit.common.data.LabelFunction;
@@ -50,11 +49,10 @@
 import com.google.gerrit.common.data.PermissionRule;
 import com.google.gerrit.common.data.PermissionRule.Action;
 import com.google.gerrit.extensions.api.GerritApi;
+import com.google.gerrit.extensions.api.changes.RelatedChangeAndCommitInfo;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
 import com.google.gerrit.extensions.api.changes.RevisionApi;
 import com.google.gerrit.extensions.api.changes.SubmittedTogetherInfo;
-import com.google.gerrit.extensions.api.groups.GroupApi;
-import com.google.gerrit.extensions.api.groups.GroupInput;
 import com.google.gerrit.extensions.api.projects.BranchApi;
 import com.google.gerrit.extensions.api.projects.BranchInput;
 import com.google.gerrit.extensions.api.projects.ProjectInput;
@@ -254,6 +252,7 @@
   @Inject protected MetaDataUpdate.Server metaDataUpdateFactory;
   @Inject protected PatchSetUtil psUtil;
   @Inject protected ProjectCache projectCache;
+  @Inject protected ProjectConfig.Factory projectConfigFactory;
   @Inject protected ProjectResetter.Builder.Factory projectResetter;
   @Inject protected Provider<InternalChangeQuery> queryProvider;
   @Inject protected PushOneCommit.Factory pushFactory;
@@ -270,6 +269,7 @@
   protected Project.NameKey project;
   protected RestSession adminRestSession;
   protected RestSession userRestSession;
+  protected RestSession anonymousRestSession;
   protected ReviewDb db;
   protected SshSession adminSshSession;
   protected SshSession userSshSession;
@@ -426,11 +426,12 @@
 
     db = reviewDbProvider.open();
 
-    // All groups which were added during the server start (e.g. in SchemaCreator) aren't contained
-    // in the instance of the group index which is available here and in tests. There are two
-    // reasons:
-    // 1) No group index is available in SchemaCreator when using an in-memory database. (This could
-    // be fixed by using the IndexManagerOnInit in InMemoryDatabase similar as BaseInit uses it.)
+    // All groups which were added during the server start (e.g. in ReviewDbSchemaCreator) aren't
+    // contained in the instance of the group index which is available here and in tests. There are
+    // two reasons:
+    // 1) No group index is available in ReviewDbSchemaCreator when using an in-memory database.
+    // (This could be fixed by using the IndexManagerOnInit in InMemoryDatabase similar as BaseInit
+    // uses it.)
     // 2) During the on-init part of the server start, we use another instance of the index than
     // later on. As test indexes are non-permanent, closing an instance and opening another one
     // removes all indexed data.
@@ -446,6 +447,7 @@
 
     adminRestSession = new RestSession(server, admin);
     userRestSession = new RestSession(server, user);
+    anonymousRestSession = new RestSession(server, null);
 
     initSsh();
 
@@ -997,18 +999,9 @@
     }
   }
 
-  protected void setUseContributorAgreements(InheritableBoolean value) throws Exception {
-    try (MetaDataUpdate md = metaDataUpdateFactory.create(project)) {
-      ProjectConfig config = ProjectConfig.read(md);
-      config.getProject().setBooleanConfig(BooleanProjectConfig.USE_CONTRIBUTOR_AGREEMENTS, value);
-      config.commit(md);
-      projectCache.evict(config.getProject());
-    }
-  }
-
   protected void setUseSignedOffBy(InheritableBoolean value) throws Exception {
     try (MetaDataUpdate md = metaDataUpdateFactory.create(project)) {
-      ProjectConfig config = ProjectConfig.read(md);
+      ProjectConfig config = projectConfigFactory.read(md);
       config.getProject().setBooleanConfig(BooleanProjectConfig.USE_SIGNED_OFF_BY, value);
       config.commit(md);
       projectCache.evict(config.getProject());
@@ -1017,7 +1010,7 @@
 
   protected void setRequireChangeId(InheritableBoolean value) throws Exception {
     try (MetaDataUpdate md = metaDataUpdateFactory.create(project)) {
-      ProjectConfig config = ProjectConfig.read(md);
+      ProjectConfig config = projectConfigFactory.read(md);
       config.getProject().setBooleanConfig(BooleanProjectConfig.REQUIRE_CHANGE_ID, value);
       config.commit(md);
       projectCache.evict(config.getProject());
@@ -1079,7 +1072,7 @@
       throws RepositoryNotFoundException, IOException, ConfigInvalidException {
     try (MetaDataUpdate md = metaDataUpdateFactory.create(project)) {
       md.setMessage(String.format("Grant %s on %s", permission, ref));
-      ProjectConfig config = ProjectConfig.read(md);
+      ProjectConfig config = projectConfigFactory.read(md);
       AccessSection s = config.getAccessSection(ref, true);
       Permission p = s.getPermission(permission, true);
       PermissionRule rule = Util.newRule(config, groupUUID);
@@ -1103,7 +1096,7 @@
     String permission = Permission.LABEL + label;
     try (MetaDataUpdate md = metaDataUpdateFactory.create(project)) {
       md.setMessage(String.format("Grant %s on %s", permission, ref));
-      ProjectConfig config = ProjectConfig.read(md);
+      ProjectConfig config = projectConfigFactory.read(md);
       AccessSection s = config.getAccessSection(ref, true);
       Permission p = s.getPermission(permission, true);
       p.setExclusiveGroup(exclusive);
@@ -1121,7 +1114,7 @@
       throws IOException, ConfigInvalidException {
     try (MetaDataUpdate md = metaDataUpdateFactory.create(project)) {
       md.setMessage(String.format("Remove %s on %s", permission, ref));
-      ProjectConfig config = ProjectConfig.read(md);
+      ProjectConfig config = projectConfigFactory.read(md);
       AccessSection s = config.getAccessSection(ref, true);
       Permission p = s.getPermission(permission, true);
       p.clearRules();
@@ -1191,27 +1184,7 @@
     return changeResourceFactory.create(notes.get(0), atrScope.get().getUser());
   }
 
-  protected String createGroup(String name) throws Exception {
-    return createGroup(name, "Administrators");
-  }
-
-  protected String createGroupWithRealName(String name) throws Exception {
-    GroupInput in = new GroupInput();
-    in.name = name;
-    in.ownerId = "Administrators";
-    gApi.groups().create(in);
-    return name;
-  }
-
-  protected String createGroup(String name, String owner) throws Exception {
-    name = name(name);
-    GroupInput in = new GroupInput();
-    in.name = name;
-    in.ownerId = owner;
-    gApi.groups().create(in);
-    return name;
-  }
-
+  @Nullable
   protected RevCommit getHead(Repository repo, String name) throws Exception {
     try (RevWalk rw = new RevWalk(repo)) {
       Ref r = repo.exactRef(name);
@@ -1223,16 +1196,19 @@
     return getHead(repo, "HEAD");
   }
 
+  @Nullable
   protected RevCommit getRemoteHead(Project.NameKey project, String branch) throws Exception {
     try (Repository repo = repoManager.openRepository(project)) {
       return getHead(repo, branch.startsWith(Constants.R_REFS) ? branch : "refs/heads/" + branch);
     }
   }
 
+  @Nullable
   protected RevCommit getRemoteHead(String project, String branch) throws Exception {
     return getRemoteHead(new Project.NameKey(project), branch);
   }
 
+  @Nullable
   protected RevCommit getRemoteHead() throws Exception {
     return getRemoteHead(project, "master");
   }
@@ -1243,33 +1219,6 @@
     assertThat(replyTo.getString()).contains(email);
   }
 
-  protected ContributorAgreement configureContributorAgreement(boolean autoVerify)
-      throws Exception {
-    ContributorAgreement ca;
-    if (autoVerify) {
-      String g = createGroup("cla-test-group");
-      GroupApi groupApi = gApi.groups().id(g);
-      groupApi.description("CLA test group");
-      InternalGroup caGroup = group(new AccountGroup.UUID(groupApi.detail().id));
-      GroupReference groupRef = new GroupReference(caGroup.getGroupUUID(), caGroup.getName());
-      PermissionRule rule = new PermissionRule(groupRef);
-      rule.setAction(PermissionRule.Action.ALLOW);
-      ca = new ContributorAgreement("cla-test");
-      ca.setAutoVerify(groupRef);
-      ca.setAccepted(ImmutableList.of(rule));
-    } else {
-      ca = new ContributorAgreement("cla-test-no-auto-verify");
-    }
-    ca.setDescription("description");
-    ca.setAgreementUrl("agreement-url");
-
-    try (ProjectConfigUpdate u = updateProject(allProjects)) {
-      u.getConfig().replace(ca);
-      u.save();
-      return ca;
-    }
-  }
-
   protected Map<Branch.NameKey, ObjectId> fetchFromSubmitPreview(String changeId) throws Exception {
     try (BinaryResult result = gApi.changes().id(changeId).current().submitPreview()) {
       return fetchFromBundles(result);
@@ -1669,7 +1618,7 @@
 
     private ProjectConfigUpdate(Project.NameKey projectName) throws Exception {
       metaDataUpdate = metaDataUpdateFactory.create(projectName);
-      projectConfig = ProjectConfig.read(metaDataUpdate);
+      projectConfig = projectConfigFactory.read(metaDataUpdate);
     }
 
     public ProjectConfig getConfig() {
@@ -1716,4 +1665,13 @@
     comments.sort(Comparator.comparing(c -> c.id));
     return comments;
   }
+
+  protected List<RelatedChangeAndCommitInfo> getRelated(PatchSet.Id ps) throws Exception {
+    return getRelated(ps.getParentKey(), ps.get());
+  }
+
+  protected List<RelatedChangeAndCommitInfo> getRelated(Change.Id changeId, int ps)
+      throws Exception {
+    return gApi.changes().id(changeId.get()).revision(ps).related().changes;
+  }
 }
diff --git a/java/com/google/gerrit/acceptance/HttpSession.java b/java/com/google/gerrit/acceptance/HttpSession.java
index fe446f4..fdd1fce 100644
--- a/java/com/google/gerrit/acceptance/HttpSession.java
+++ b/java/com/google/gerrit/acceptance/HttpSession.java
@@ -19,8 +19,10 @@
 import java.io.IOException;
 import java.net.URI;
 import org.apache.http.HttpHost;
+import org.apache.http.client.HttpClient;
 import org.apache.http.client.fluent.Executor;
 import org.apache.http.client.fluent.Request;
+import org.apache.http.impl.client.HttpClientBuilder;
 
 public class HttpSession {
   protected TestAccount account;
@@ -30,7 +32,8 @@
   public HttpSession(GerritServer server, @Nullable TestAccount account) {
     this.url = CharMatcher.is('/').trimTrailingFrom(server.getUrl());
     URI uri = URI.create(url);
-    this.executor = Executor.newInstance();
+    HttpClient noRedirectClient = HttpClientBuilder.create().disableRedirectHandling().build();
+    this.executor = Executor.newInstance(noRedirectClient);
     this.account = account;
     if (account != null) {
       executor.auth(
diff --git a/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java b/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java
index 6ee5c09..0bbf9f1 100644
--- a/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java
+++ b/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java
@@ -34,8 +34,8 @@
 import com.google.gerrit.server.schema.DataSourceType;
 import com.google.gerrit.server.schema.NotesMigrationSchemaFactory;
 import com.google.gerrit.server.schema.ReviewDbFactory;
-import com.google.gerrit.server.schema.SchemaModule;
-import com.google.gerrit.server.schema.SchemaVersion;
+import com.google.gerrit.server.schema.ReviewDbSchemaModule;
+import com.google.gerrit.server.schema.ReviewDbSchemaVersion;
 import com.google.gerrit.testing.InMemoryDatabase;
 import com.google.gerrit.testing.InMemoryH2Type;
 import com.google.gerrit.testing.InMemoryRepositoryManager;
@@ -101,8 +101,8 @@
     bind(SitePaths.class);
     bind(TrackingFooters.class).toProvider(TrackingFootersProvider.class).in(SINGLETON);
 
-    install(new SchemaModule());
-    bind(SchemaVersion.class).to(SchemaVersion.C);
+    install(new ReviewDbSchemaModule());
+    bind(ReviewDbSchemaVersion.class).to(ReviewDbSchemaVersion.C);
 
     install(new SshdModule());
   }
diff --git a/java/com/google/gerrit/acceptance/RestResponse.java b/java/com/google/gerrit/acceptance/RestResponse.java
index da08215..e8de5c6 100644
--- a/java/com/google/gerrit/acceptance/RestResponse.java
+++ b/java/com/google/gerrit/acceptance/RestResponse.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.acceptance;
 
+import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 import static com.google.gerrit.httpd.restapi.RestApiServlet.JSON_MAGIC;
 import static java.nio.charset.StandardCharsets.UTF_8;
@@ -21,6 +22,7 @@
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.net.URI;
 import org.apache.http.HttpStatus;
 
 public class RestResponse extends HttpResponse {
@@ -83,4 +85,9 @@
   public void assertPreconditionFailed() throws Exception {
     assertStatus(HttpStatus.SC_PRECONDITION_FAILED);
   }
+
+  public void assertTemporaryRedirect(String path) throws Exception {
+    assertStatus(HttpStatus.SC_MOVED_TEMPORARILY);
+    assertThat(URI.create(getHeader("Location")).getPath()).isEqualTo(path);
+  }
 }
diff --git a/java/com/google/gerrit/common/BUILD b/java/com/google/gerrit/common/BUILD
index 2122ebb..fc04bd3 100644
--- a/java/com/google/gerrit/common/BUILD
+++ b/java/com/google/gerrit/common/BUILD
@@ -1,5 +1,4 @@
 load("//tools/bzl:genrule2.bzl", "genrule2")
-load("//tools/bzl:gwt.bzl", "gwt_module")
 
 ANNOTATIONS = [
     "Nullable.java",
@@ -13,24 +12,6 @@
     visibility = ["//visibility:public"],
 )
 
-gwt_module(
-    name = "client",
-    srcs = glob(["**/*.java"]),
-    exported_deps = [
-        "//java/com/google/gerrit/extensions:api",
-        "//java/com/google/gerrit/prettify:client",
-        "//lib:guava",
-        "//lib:gwtorm-client",
-        "//lib:servlet-api-3_1",
-        "//lib/auto:auto-value",
-        "//lib/auto:auto-value-annotations",
-        "//lib/flogger:api",
-        "//lib/jgit/org.eclipse.jgit:jgit",
-    ],
-    gwt_xml = "Common.gwt.xml",
-    visibility = ["//visibility:public"],
-)
-
 java_library(
     name = "server",
     srcs = glob(
diff --git a/java/com/google/gerrit/common/Common.gwt.xml b/java/com/google/gerrit/common/Common.gwt.xml
deleted file mode 100644
index 56bbb84..0000000
--- a/java/com/google/gerrit/common/Common.gwt.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<module>
-  <inherits name='com.google.gerrit.reviewdb.ReviewDB' />
-  <inherits name='com.google.gwtjsonrpc.GWTJSONRPC'/>
-  <inherits name="com.google.gwt.logging.Logging"/>
-  <source path="">
-    <exclude name='**/testing/**/*.java'/>
-    <include name='**/*.java'/>
-  </source>
-</module>
diff --git a/java/com/google/gerrit/common/data/AccessSection.java b/java/com/google/gerrit/common/data/AccessSection.java
index 49948f8f..c8d8d41 100644
--- a/java/com/google/gerrit/common/data/AccessSection.java
+++ b/java/com/google/gerrit/common/data/AccessSection.java
@@ -16,6 +16,7 @@
 
 import static java.util.Objects.requireNonNull;
 
+import com.google.common.collect.ImmutableList;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.reviewdb.client.Project;
 import java.util.ArrayList;
@@ -36,12 +37,8 @@
     super(refPattern);
   }
 
-  // TODO(ekempin): Make this method return an ImmutableList once the GWT UI is gone.
   public List<Permission> getPermissions() {
-    if (permissions == null) {
-      return new ArrayList<>();
-    }
-    return new ArrayList<>(permissions);
+    return permissions == null ? ImmutableList.of() : ImmutableList.copyOf(permissions);
   }
 
   public void setPermissions(List<Permission> list) {
diff --git a/java/com/google/gerrit/common/data/ContributorAgreement.java b/java/com/google/gerrit/common/data/ContributorAgreement.java
index b43dbfa..a6e8cdd 100644
--- a/java/com/google/gerrit/common/data/ContributorAgreement.java
+++ b/java/com/google/gerrit/common/data/ContributorAgreement.java
@@ -25,6 +25,8 @@
   protected List<PermissionRule> accepted;
   protected GroupReference autoVerify;
   protected String agreementUrl;
+  protected List<String> excludeProjectsRegexes;
+  protected List<String> matchProjectsRegexes;
 
   protected ContributorAgreement() {}
 
@@ -75,6 +77,28 @@
     this.agreementUrl = agreementUrl;
   }
 
+  public List<String> getExcludeProjectsRegexes() {
+    if (excludeProjectsRegexes == null) {
+      excludeProjectsRegexes = new ArrayList<>();
+    }
+    return excludeProjectsRegexes;
+  }
+
+  public void setExcludeProjectsRegexes(List<String> excludeProjectsRegexes) {
+    this.excludeProjectsRegexes = excludeProjectsRegexes;
+  }
+
+  public List<String> getMatchProjectsRegexes() {
+    if (matchProjectsRegexes == null) {
+      matchProjectsRegexes = new ArrayList<>();
+    }
+    return matchProjectsRegexes;
+  }
+
+  public void setMatchProjectsRegexes(List<String> matchProjectsRegexes) {
+    this.matchProjectsRegexes = matchProjectsRegexes;
+  }
+
   @Override
   public int compareTo(ContributorAgreement o) {
     return getName().compareTo(o.getName());
diff --git a/java/com/google/gerrit/common/data/HostPageData.java b/java/com/google/gerrit/common/data/HostPageData.java
index 517c520..bf58ff4 100644
--- a/java/com/google/gerrit/common/data/HostPageData.java
+++ b/java/com/google/gerrit/common/data/HostPageData.java
@@ -14,11 +14,7 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.extensions.client.DiffPreferencesInfo;
-import java.util.Date;
-import java.util.List;
-
-/** Data sent as part of the host page, to bootstrap the UI. */
+/** XSRF Constants. */
 public class HostPageData {
   /**
    * Name of the cookie in which the XSRF token is sent from the server to the client during host
@@ -31,30 +27,4 @@
    * request.
    */
   public static final String XSRF_HEADER_NAME = "X-Gerrit-Auth";
-
-  public String version;
-  public DiffPreferencesInfo accountDiffPref;
-  public Theme theme;
-  public List<String> plugins;
-  public List<Message> messages;
-  public Integer pluginsLoadTimeout;
-  public boolean isNoteDbEnabled;
-  public boolean canLoadInIFrame;
-
-  public static class Theme {
-    public String backgroundColor;
-    public String topMenuColor;
-    public String textColor;
-    public String trimColor;
-    public String selectionColor;
-    public String changeTableOutdatedColor;
-    public String tableOddRowColor;
-    public String tableEvenRowColor;
-  }
-
-  public static class Message {
-    public String id;
-    public Date redisplay;
-    public String html;
-  }
 }
diff --git a/java/com/google/gerrit/common/data/Permission.java b/java/com/google/gerrit/common/data/Permission.java
index de6108e..a30d412 100644
--- a/java/com/google/gerrit/common/data/Permission.java
+++ b/java/com/google/gerrit/common/data/Permission.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.common.data;
 
+import com.google.common.collect.ImmutableList;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -157,12 +158,8 @@
     exclusiveGroup = newExclusiveGroup;
   }
 
-  // TODO(ekempin): Make this method return an ImmutableList once the GWT UI is gone.
   public List<PermissionRule> getRules() {
-    if (rules == null) {
-      return new ArrayList<>();
-    }
-    return new ArrayList<>(rules);
+    return rules == null ? ImmutableList.of() : ImmutableList.copyOf(rules);
   }
 
   public void setRules(List<PermissionRule> list) {
diff --git a/java/com/google/gerrit/extensions/BUILD b/java/com/google/gerrit/extensions/BUILD
index 1780ce9..5f9220e 100644
--- a/java/com/google/gerrit/extensions/BUILD
+++ b/java/com/google/gerrit/extensions/BUILD
@@ -1,15 +1,5 @@
 load("//lib:guava.bzl", "GUAVA_DOC_URL")
 load("//lib/jgit:jgit.bzl", "JGIT_DOC_URL")
-load("//tools/bzl:gwt.bzl", "gwt_module")
-
-EXT_API_SRCS = glob(["client/*.java"])
-
-gwt_module(
-    name = "client",
-    srcs = EXT_API_SRCS,
-    gwt_xml = "Extensions.gwt.xml",
-    visibility = ["//visibility:public"],
-)
 
 java_binary(
     name = "extension-api",
diff --git a/java/com/google/gerrit/extensions/Extensions.gwt.xml b/java/com/google/gerrit/extensions/Extensions.gwt.xml
deleted file mode 100644
index c857b60..0000000
--- a/java/com/google/gerrit/extensions/Extensions.gwt.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<!--
- Copyright (C) 2013 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<module>
-  <source path='client' />
-</module>
diff --git a/java/com/google/gerrit/extensions/api/changes/ChangeApi.java b/java/com/google/gerrit/extensions/api/changes/ChangeApi.java
index 0150e1e..eb27260 100644
--- a/java/com/google/gerrit/extensions/api/changes/ChangeApi.java
+++ b/java/com/google/gerrit/extensions/api/changes/ChangeApi.java
@@ -49,17 +49,21 @@
    * @return API for accessing the revision.
    * @throws RestApiException if an error occurred.
    */
-  RevisionApi current() throws RestApiException;
+  default RevisionApi current() throws RestApiException {
+    return revision("current");
+  }
 
   /**
    * Look up a revision of a change by number.
    *
    * @see #current()
    */
-  RevisionApi revision(int id) throws RestApiException;
+  default RevisionApi revision(int id) throws RestApiException {
+    return revision(Integer.toString(id));
+  }
 
   /**
-   * Look up a revision of a change by commit SHA-1.
+   * Look up a revision of a change by commit SHA-1 or other supported revision string.
    *
    * @see #current()
    */
@@ -79,15 +83,23 @@
    */
   ReviewerApi reviewer(String id) throws RestApiException;
 
-  void abandon() throws RestApiException;
+  default void abandon() throws RestApiException {
+    abandon(new AbandonInput());
+  }
 
   void abandon(AbandonInput in) throws RestApiException;
 
-  void restore() throws RestApiException;
+  default void restore() throws RestApiException {
+    restore(new RestoreInput());
+  }
 
   void restore(RestoreInput in) throws RestApiException;
 
-  void move(String destination) throws RestApiException;
+  default void move(String destination) throws RestApiException {
+    MoveInput in = new MoveInput();
+    in.destinationBranch = destination;
+    move(in);
+  }
 
   void move(MoveInput in) throws RestApiException;
 
@@ -132,7 +144,9 @@
    *
    * @see Changes#id(int)
    */
-  ChangeApi revert() throws RestApiException;
+  default ChangeApi revert() throws RestApiException {
+    return revert(new RevertInput());
+  }
 
   /**
    * Create a new change that reverts this change.
@@ -144,10 +158,17 @@
   /** Create a merge patch set for the change. */
   ChangeInfo createMergePatchSet(MergePatchSetInput in) throws RestApiException;
 
-  List<ChangeInfo> submittedTogether() throws RestApiException;
+  default List<ChangeInfo> submittedTogether() throws RestApiException {
+    SubmittedTogetherInfo info =
+        submittedTogether(
+            EnumSet.noneOf(ListChangesOption.class), EnumSet.noneOf(SubmittedTogetherOption.class));
+    return info.changes;
+  }
 
-  SubmittedTogetherInfo submittedTogether(EnumSet<SubmittedTogetherOption> options)
-      throws RestApiException;
+  default SubmittedTogetherInfo submittedTogether(EnumSet<SubmittedTogetherOption> options)
+      throws RestApiException {
+    return submittedTogether(EnumSet.noneOf(ListChangesOption.class), options);
+  }
 
   SubmittedTogetherInfo submittedTogether(
       EnumSet<ListChangesOption> listOptions, EnumSet<SubmittedTogetherOption> submitOptions)
@@ -155,10 +176,14 @@
 
   /** Publishes a draft change. */
   @Deprecated
-  void publish() throws RestApiException;
+  default void publish() {
+    throw new UnsupportedOperationException("draft workflow is discontinued");
+  }
 
   /** Rebase the current revision of a change using default options. */
-  void rebase() throws RestApiException;
+  default void rebase() throws RestApiException {
+    rebase(new RebaseInput());
+  }
 
   /** Rebase the current revision of a change. */
   void rebase(RebaseInput in) throws RestApiException;
@@ -172,13 +197,19 @@
 
   IncludedInInfo includedIn() throws RestApiException;
 
-  AddReviewerResult addReviewer(AddReviewerInput in) throws RestApiException;
+  default AddReviewerResult addReviewer(String reviewer) throws RestApiException {
+    AddReviewerInput in = new AddReviewerInput();
+    in.reviewer = reviewer;
+    return addReviewer(in);
+  }
 
-  AddReviewerResult addReviewer(String in) throws RestApiException;
+  AddReviewerResult addReviewer(AddReviewerInput in) throws RestApiException;
 
   SuggestedReviewersRequest suggestReviewers() throws RestApiException;
 
-  SuggestedReviewersRequest suggestReviewers(String query) throws RestApiException;
+  default SuggestedReviewersRequest suggestReviewers(String query) throws RestApiException {
+    return suggestReviewers().withQuery(query);
+  }
 
   ChangeInfo get(EnumSet<ListChangesOption> options) throws RestApiException;
 
@@ -198,10 +229,16 @@
    *   <li>{@code SKIP_MERGEABLE} is omitted, so the {@code mergeable} bit <em>is</em> set.
    * </ul>
    */
-  ChangeInfo get() throws RestApiException;
+  default ChangeInfo get() throws RestApiException {
+    return get(
+        EnumSet.complementOf(
+            EnumSet.of(ListChangesOption.CHECK, ListChangesOption.SKIP_MERGEABLE)));
+  }
 
   /** {@link #get(ListChangesOption...)} with no options included. */
-  ChangeInfo info() throws RestApiException;
+  default ChangeInfo info() throws RestApiException {
+    return get(EnumSet.noneOf(ListChangesOption.class));
+  }
 
   /**
    * Retrieve change edit when exists.
@@ -210,7 +247,9 @@
    *     ChangeEditApi#get()}.
    */
   @Deprecated
-  EditInfo getEdit() throws RestApiException;
+  default EditInfo getEdit() throws RestApiException {
+    return edit().get().orElse(null);
+  }
 
   /**
    * Provides access to an API regarding the change edit of this change.
@@ -221,7 +260,11 @@
   ChangeEditApi edit() throws RestApiException;
 
   /** Create a new patch set with a new commit message. */
-  void setMessage(String message) throws RestApiException;
+  default void setMessage(String message) throws RestApiException {
+    CommitMessageInput in = new CommitMessageInput();
+    in.message = message;
+    setMessage(in);
+  }
 
   /** Create a new patch set with a new commit message. */
   void setMessage(CommitMessageInput in) throws RestApiException;
@@ -347,16 +390,6 @@
     }
 
     @Override
-    public RevisionApi current() throws RestApiException {
-      throw new NotImplementedException();
-    }
-
-    @Override
-    public RevisionApi revision(int id) throws RestApiException {
-      throw new NotImplementedException();
-    }
-
-    @Override
     public ReviewerApi reviewer(String id) throws RestApiException {
       throw new NotImplementedException();
     }
@@ -367,31 +400,16 @@
     }
 
     @Override
-    public void abandon() throws RestApiException {
-      throw new NotImplementedException();
-    }
-
-    @Override
     public void abandon(AbandonInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void restore() throws RestApiException {
-      throw new NotImplementedException();
-    }
-
-    @Override
     public void restore(RestoreInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void move(String destination) throws RestApiException {
-      throw new NotImplementedException();
-    }
-
-    @Override
     public void move(MoveInput in) throws RestApiException {
       throw new NotImplementedException();
     }
@@ -412,27 +430,11 @@
     }
 
     @Override
-    public ChangeApi revert() throws RestApiException {
-      throw new NotImplementedException();
-    }
-
-    @Override
     public ChangeApi revert(RevertInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void publish() throws RestApiException {
-      throw new NotImplementedException();
-    }
-
-    @Deprecated
-    @Override
-    public void rebase() throws RestApiException {
-      throw new NotImplementedException();
-    }
-
-    @Override
     public void rebase(RebaseInput in) throws RestApiException {
       throw new NotImplementedException();
     }
@@ -463,51 +465,21 @@
     }
 
     @Override
-    public AddReviewerResult addReviewer(String in) throws RestApiException {
-      throw new NotImplementedException();
-    }
-
-    @Override
     public SuggestedReviewersRequest suggestReviewers() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public SuggestedReviewersRequest suggestReviewers(String query) throws RestApiException {
-      throw new NotImplementedException();
-    }
-
-    @Override
     public ChangeInfo get(EnumSet<ListChangesOption> options) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ChangeInfo get() throws RestApiException {
-      throw new NotImplementedException();
-    }
-
-    @Override
-    public ChangeInfo info() throws RestApiException {
-      throw new NotImplementedException();
-    }
-
-    @Override
-    public void setMessage(String message) throws RestApiException {
-      throw new NotImplementedException();
-    }
-
-    @Override
     public void setMessage(CommitMessageInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public EditInfo getEdit() throws RestApiException {
-      throw new NotImplementedException();
-    }
-
-    @Override
     public ChangeEditApi edit() throws RestApiException {
       throw new NotImplementedException();
     }
diff --git a/java/com/google/gerrit/extensions/api/changes/RelatedChangeAndCommitInfo.java b/java/com/google/gerrit/extensions/api/changes/RelatedChangeAndCommitInfo.java
new file mode 100644
index 0000000..5bf22aa
--- /dev/null
+++ b/java/com/google/gerrit/extensions/api/changes/RelatedChangeAndCommitInfo.java
@@ -0,0 +1,43 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.extensions.api.changes;
+
+import com.google.common.base.MoreObjects;
+import com.google.gerrit.extensions.common.CommitInfo;
+
+public class RelatedChangeAndCommitInfo {
+  public String project;
+  public String changeId;
+  public CommitInfo commit;
+  public Integer _changeNumber;
+  public Integer _revisionNumber;
+  public Integer _currentRevisionNumber;
+  public String status;
+
+  public RelatedChangeAndCommitInfo() {}
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("project", project)
+        .add("changeId", changeId)
+        .add("commit", commit)
+        .add("_changeNumber", _changeNumber)
+        .add("_revisionNumber", _revisionNumber)
+        .add("_currentRevisionNumber", _currentRevisionNumber)
+        .add("status", status)
+        .toString();
+  }
+}
diff --git a/java/com/google/gerrit/extensions/api/changes/RelatedChangesInfo.java b/java/com/google/gerrit/extensions/api/changes/RelatedChangesInfo.java
new file mode 100644
index 0000000..e1e70f3
--- /dev/null
+++ b/java/com/google/gerrit/extensions/api/changes/RelatedChangesInfo.java
@@ -0,0 +1,21 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.extensions.api.changes;
+
+import java.util.List;
+
+public class RelatedChangesInfo {
+  public List<RelatedChangeAndCommitInfo> changes;
+}
diff --git a/java/com/google/gerrit/extensions/api/changes/RevisionApi.java b/java/com/google/gerrit/extensions/api/changes/RevisionApi.java
index 4658eb3..a6df45f 100644
--- a/java/com/google/gerrit/extensions/api/changes/RevisionApi.java
+++ b/java/com/google/gerrit/extensions/api/changes/RevisionApi.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.extensions.api.changes;
 
+import com.google.gerrit.common.Nullable;
 import com.google.gerrit.extensions.client.SubmitType;
 import com.google.gerrit.extensions.common.ActionInfo;
 import com.google.gerrit.extensions.common.CherryPickChangeInfo;
@@ -34,7 +35,9 @@
 
 public interface RevisionApi {
   @Deprecated
-  void delete() throws RestApiException;
+  default void delete() {
+    throw new UnsupportedOperationException("draft workflow is discontinued");
+  }
 
   String description() throws RestApiException;
 
@@ -42,22 +45,32 @@
 
   ReviewResult review(ReviewInput in) throws RestApiException;
 
-  void submit() throws RestApiException;
+  default void submit() throws RestApiException {
+    SubmitInput in = new SubmitInput();
+    submit(in);
+  }
 
   void submit(SubmitInput in) throws RestApiException;
 
-  BinaryResult submitPreview() throws RestApiException;
+  default BinaryResult submitPreview() throws RestApiException {
+    return submitPreview("zip");
+  }
 
   BinaryResult submitPreview(String format) throws RestApiException;
 
   @Deprecated
-  void publish() throws RestApiException;
+  default void publish() {
+    throw new UnsupportedOperationException("draft workflow is discontinued");
+  }
 
   ChangeApi cherryPick(CherryPickInput in) throws RestApiException;
 
   CherryPickChangeInfo cherryPickAsInfo(CherryPickInput in) throws RestApiException;
 
-  ChangeApi rebase() throws RestApiException;
+  default ChangeApi rebase() throws RestApiException {
+    RebaseInput in = new RebaseInput();
+    return rebase(in);
+  }
 
   ChangeApi rebase(RebaseInput in) throws RestApiException;
 
@@ -69,9 +82,11 @@
 
   Set<String> reviewed() throws RestApiException;
 
-  Map<String, FileInfo> files() throws RestApiException;
+  default Map<String, FileInfo> files() throws RestApiException {
+    return files(null);
+  }
 
-  Map<String, FileInfo> files(String base) throws RestApiException;
+  Map<String, FileInfo> files(@Nullable String base) throws RestApiException;
 
   Map<String, FileInfo> files(int parentNum) throws RestApiException;
 
@@ -133,6 +148,8 @@
 
   MergeListRequest getMergeList() throws RestApiException;
 
+  RelatedChangesInfo related() throws RestApiException;
+
   abstract class MergeListRequest {
     private boolean addLinks;
     private int uninterestingParent = 1;
@@ -163,33 +180,16 @@
    * interface.
    */
   class NotImplemented implements RevisionApi {
-    @Deprecated
-    @Override
-    public void delete() throws RestApiException {
-      throw new NotImplementedException();
-    }
-
     @Override
     public ReviewResult review(ReviewInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void submit() throws RestApiException {
-      throw new NotImplementedException();
-    }
-
-    @Override
     public void submit(SubmitInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
-    @Deprecated
-    @Override
-    public void publish() throws RestApiException {
-      throw new NotImplementedException();
-    }
-
     @Override
     public ChangeApi cherryPick(CherryPickInput in) throws RestApiException {
       throw new NotImplementedException();
@@ -201,11 +201,6 @@
     }
 
     @Override
-    public ChangeApi rebase() throws RestApiException {
-      throw new NotImplementedException();
-    }
-
-    @Override
     public ChangeApi rebase(RebaseInput in) throws RestApiException {
       throw new NotImplementedException();
     }
@@ -251,11 +246,6 @@
     }
 
     @Override
-    public Map<String, FileInfo> files() throws RestApiException {
-      throw new NotImplementedException();
-    }
-
-    @Override
     public List<String> queryFiles(String query) throws RestApiException {
       throw new NotImplementedException();
     }
@@ -346,11 +336,6 @@
     }
 
     @Override
-    public BinaryResult submitPreview() throws RestApiException {
-      throw new NotImplementedException();
-    }
-
-    @Override
     public BinaryResult submitPreview(String format) throws RestApiException {
       throw new NotImplementedException();
     }
@@ -371,6 +356,11 @@
     }
 
     @Override
+    public RelatedChangesInfo related() throws RestApiException {
+      throw new NotImplementedException();
+    }
+
+    @Override
     public void description(String description) throws RestApiException {
       throw new NotImplementedException();
     }
diff --git a/java/com/google/gerrit/extensions/api/projects/RefInfo.java b/java/com/google/gerrit/extensions/api/projects/RefInfo.java
index c573600..d5695fd 100644
--- a/java/com/google/gerrit/extensions/api/projects/RefInfo.java
+++ b/java/com/google/gerrit/extensions/api/projects/RefInfo.java
@@ -14,8 +14,15 @@
 
 package com.google.gerrit.extensions.api.projects;
 
+import com.google.common.base.MoreObjects;
+
 public class RefInfo {
   public String ref;
   public String revision;
   public Boolean canDelete;
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this).add("ref", ref).add("revision", revision).toString();
+  }
 }
diff --git a/java/com/google/gerrit/extensions/common/ChangeInfo.java b/java/com/google/gerrit/extensions/common/ChangeInfo.java
index 945c239..9a739ef 100644
--- a/java/com/google/gerrit/extensions/common/ChangeInfo.java
+++ b/java/com/google/gerrit/extensions/common/ChangeInfo.java
@@ -46,6 +46,7 @@
   public Boolean submittable;
   public Integer insertions;
   public Integer deletions;
+  public Integer totalCommentCount;
   public Integer unresolvedCommentCount;
   public Boolean isPrivate;
   public Boolean workInProgress;
diff --git a/java/com/google/gerrit/extensions/common/CommitInfo.java b/java/com/google/gerrit/extensions/common/CommitInfo.java
index 213b366..1fd8755 100644
--- a/java/com/google/gerrit/extensions/common/CommitInfo.java
+++ b/java/com/google/gerrit/extensions/common/CommitInfo.java
@@ -16,6 +16,8 @@
 
 import static java.util.stream.Collectors.joining;
 
+import com.google.common.base.MoreObjects;
+import com.google.common.base.MoreObjects.ToStringHelper;
 import java.util.List;
 import java.util.Objects;
 
@@ -50,17 +52,18 @@
 
   @Override
   public String toString() {
-    // Using something like the raw commit format might be nice, but we can't depend on JGit here.
-    StringBuilder sb = new StringBuilder().append(getClass().getSimpleName()).append('{');
-    sb.append(commit);
-    sb.append(", parents=").append(parents.stream().map(p -> p.commit).collect(joining(", ")));
-    sb.append(", author=").append(author);
-    sb.append(", committer=").append(committer);
-    sb.append(", subject=").append(subject);
-    sb.append(", message=").append(message);
-    if (webLinks != null) {
-      sb.append(", webLinks=").append(webLinks);
+    ToStringHelper helper = MoreObjects.toStringHelper(this).addValue(commit);
+    if (parents != null) {
+      helper.add("parents", parents.stream().map(p -> p.commit).collect(joining(", ")));
     }
-    return sb.append('}').toString();
+    helper
+        .add("author", author)
+        .add("committer", committer)
+        .add("subject", subject)
+        .add("message", message);
+    if (webLinks != null) {
+      helper.add("webLinks", webLinks);
+    }
+    return helper.toString();
   }
 }
diff --git a/java/com/google/gerrit/extensions/webui/GwtPlugin.java b/java/com/google/gerrit/extensions/webui/GwtPlugin.java
deleted file mode 100644
index e8041c4..0000000
--- a/java/com/google/gerrit/extensions/webui/GwtPlugin.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.extensions.webui;
-
-/** Configures a web UI plugin compiled using GWT. */
-public class GwtPlugin extends WebUiPlugin {
-  private final String moduleName;
-
-  /**
-   * @param moduleName name of GWT module. The resource {@code static/$MODULE/$MODULE.nocache.js}
-   *     will be used.
-   */
-  public GwtPlugin(String moduleName) {
-    this.moduleName = moduleName;
-  }
-
-  @Override
-  public String getJavaScriptResourcePath() {
-    return String.format("static/%s/%s.nocache.js", moduleName, moduleName);
-  }
-}
diff --git a/java/com/google/gerrit/extensions/webui/WebUiPlugin.java b/java/com/google/gerrit/extensions/webui/WebUiPlugin.java
index 051d336..2d49e1c 100644
--- a/java/com/google/gerrit/extensions/webui/WebUiPlugin.java
+++ b/java/com/google/gerrit/extensions/webui/WebUiPlugin.java
@@ -34,15 +34,10 @@
  * }
  * </pre>
  *
- * @see GwtPlugin
  * @see JavaScriptPlugin
  */
 @ExtensionPoint
 public abstract class WebUiPlugin {
-  public static final GwtPlugin gwt(String moduleName) {
-    return new GwtPlugin(moduleName);
-  }
-
   public static final JavaScriptPlugin js(String scriptName) {
     return new JavaScriptPlugin(scriptName);
   }
diff --git a/java/com/google/gerrit/git/BUILD b/java/com/google/gerrit/git/BUILD
new file mode 100644
index 0000000..f0c01de
--- /dev/null
+++ b/java/com/google/gerrit/git/BUILD
@@ -0,0 +1,9 @@
+java_library(
+    name = "git",
+    srcs = glob(["*.java"]),
+    visibility = ["//visibility:public"],
+    deps = [
+        "//lib:guava",
+        "//lib/jgit/org.eclipse.jgit:jgit",
+    ],
+)
diff --git a/java/com/google/gerrit/git/LockFailureException.java b/java/com/google/gerrit/git/LockFailureException.java
new file mode 100644
index 0000000..b249749
--- /dev/null
+++ b/java/com/google/gerrit/git/LockFailureException.java
@@ -0,0 +1,51 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.git;
+
+import static com.google.common.collect.ImmutableList.toImmutableList;
+
+import com.google.common.collect.ImmutableList;
+import java.io.IOException;
+import org.eclipse.jgit.lib.BatchRefUpdate;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.transport.ReceiveCommand;
+
+/** Thrown when updating a ref in Git fails with LOCK_FAILURE. */
+public class LockFailureException extends IOException {
+  private static final long serialVersionUID = 1L;
+
+  private final ImmutableList<String> refs;
+
+  public LockFailureException(String message, RefUpdate refUpdate) {
+    super(message);
+    refs = ImmutableList.of(refUpdate.getName());
+  }
+
+  public LockFailureException(String message, BatchRefUpdate batchRefUpdate) {
+    super(message);
+    refs =
+        batchRefUpdate
+            .getCommands()
+            .stream()
+            .filter(c -> c.getResult() == ReceiveCommand.Result.LOCK_FAILURE)
+            .map(ReceiveCommand::getRefName)
+            .collect(toImmutableList());
+  }
+
+  /** Subset of ref names that caused the lock failure. */
+  public ImmutableList<String> getFailedRefs() {
+    return refs;
+  }
+}
diff --git a/java/com/google/gerrit/git/RefUpdateUtil.java b/java/com/google/gerrit/git/RefUpdateUtil.java
new file mode 100644
index 0000000..520d0f2
--- /dev/null
+++ b/java/com/google/gerrit/git/RefUpdateUtil.java
@@ -0,0 +1,182 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.git;
+
+import com.google.common.annotations.VisibleForTesting;
+import java.io.IOException;
+import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.lib.BatchRefUpdate;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.transport.ReceiveCommand;
+
+/** Static utilities for working with JGit's ref update APIs. */
+public class RefUpdateUtil {
+  /**
+   * Execute a batch ref update, throwing a checked exception if not all updates succeeded.
+   *
+   * <p>Creates a new {@link RevWalk} used only for this operation.
+   *
+   * @param bru batch update; should already have been executed.
+   * @param repo repository that created {@code bru}.
+   * @throws LockFailureException if the transaction was aborted due to lock failure; see {@link
+   *     #checkResults(BatchRefUpdate)} for details.
+   * @throws IOException if any result was not {@code OK}.
+   */
+  public static void executeChecked(BatchRefUpdate bru, Repository repo) throws IOException {
+    try (RevWalk rw = new RevWalk(repo)) {
+      executeChecked(bru, rw);
+    }
+  }
+
+  /**
+   * Execute a batch ref update, throwing a checked exception if not all updates succeeded.
+   *
+   * @param bru batch update; should already have been executed.
+   * @param rw walk for executing the update.
+   * @throws LockFailureException if the transaction was aborted due to lock failure; see {@link
+   *     #checkResults(BatchRefUpdate)} for details.
+   * @throws IOException if any result was not {@code OK}.
+   */
+  public static void executeChecked(BatchRefUpdate bru, RevWalk rw) throws IOException {
+    bru.execute(rw, NullProgressMonitor.INSTANCE);
+    checkResults(bru);
+  }
+
+  /**
+   * Check results of all commands in the update batch, reducing to a single exception if there was
+   * a failure.
+   *
+   * <p>Throws {@link LockFailureException} if at least one command failed with {@code
+   * LOCK_FAILURE}, and the entire transaction was aborted, i.e. any non-{@code LOCK_FAILURE}
+   * results, if there were any, failed with "transaction aborted".
+   *
+   * <p>In particular, if the underlying ref database does not {@link
+   * org.eclipse.jgit.lib.RefDatabase#performsAtomicTransactions() perform atomic transactions},
+   * then a combination of {@code LOCK_FAILURE} on one ref and {@code OK} or another result on other
+   * refs will <em>not</em> throw {@code LockFailureException}.
+   *
+   * @param bru batch update; should already have been executed.
+   * @throws LockFailureException if the transaction was aborted due to lock failure.
+   * @throws IOException if any result was not {@code OK}.
+   */
+  @VisibleForTesting
+  static void checkResults(BatchRefUpdate bru) throws IOException {
+    if (bru.getCommands().isEmpty()) {
+      return;
+    }
+
+    int lockFailure = 0;
+    int aborted = 0;
+    int failure = 0;
+
+    for (ReceiveCommand cmd : bru.getCommands()) {
+      if (cmd.getResult() != ReceiveCommand.Result.OK) {
+        failure++;
+      }
+      if (cmd.getResult() == ReceiveCommand.Result.LOCK_FAILURE) {
+        lockFailure++;
+      } else if (cmd.getResult() == ReceiveCommand.Result.REJECTED_OTHER_REASON
+          && JGitText.get().transactionAborted.equals(cmd.getMessage())) {
+        aborted++;
+      }
+    }
+
+    if (lockFailure + aborted == bru.getCommands().size()) {
+      throw new LockFailureException("Update aborted with one or more lock failures: " + bru, bru);
+    } else if (failure > 0) {
+      throw new IOException("Update failed: " + bru);
+    }
+  }
+
+  /**
+   * Check results of a single ref update, throwing an exception if there was a failure.
+   *
+   * @param ru ref update; must already have been executed.
+   * @throws IllegalArgumentException if the result was {@code NOT_ATTEMPTED}.
+   * @throws LockFailureException if the result was {@code LOCK_FAILURE}.
+   * @throws IOException if the result failed for another reason.
+   */
+  public static void checkResult(RefUpdate ru) throws IOException {
+    RefUpdate.Result result = ru.getResult();
+    switch (result) {
+      case NOT_ATTEMPTED:
+        throw new IllegalArgumentException("Not attempted: " + ru.getName());
+      case NEW:
+      case FORCED:
+      case NO_CHANGE:
+      case FAST_FORWARD:
+      case RENAMED:
+        return;
+      case LOCK_FAILURE:
+        throw new LockFailureException("Failed to update " + ru.getName() + ": " + result, ru);
+      default:
+      case IO_FAILURE:
+      case REJECTED:
+      case REJECTED_CURRENT_BRANCH:
+      case REJECTED_MISSING_OBJECT:
+      case REJECTED_OTHER_REASON:
+        throw new IOException("Failed to update " + ru.getName() + ": " + ru.getResult());
+    }
+  }
+
+  /**
+   * Delete a single ref, throwing a checked exception on failure.
+   *
+   * <p>Does not require that the ref have any particular old value. Succeeds as a no-op if the ref
+   * did not exist.
+   *
+   * @param repo repository.
+   * @param refName ref name to delete.
+   * @throws LockFailureException if a low-level lock failure (e.g. compare-and-swap failure)
+   *     occurs.
+   * @throws IOException if an error occurred.
+   */
+  public static void deleteChecked(Repository repo, String refName) throws IOException {
+    RefUpdate ru = repo.updateRef(refName);
+    ru.setForceUpdate(true);
+    switch (ru.delete()) {
+      case FORCED:
+        // Ref was deleted.
+        return;
+
+      case NEW:
+        // Ref didn't exist (yes, really).
+        return;
+
+      case LOCK_FAILURE:
+        throw new LockFailureException("Failed to delete " + refName + ": " + ru.getResult(), ru);
+
+        // Not really failures, but should not be the result of a deletion, so the best option is to
+        // throw.
+      case NO_CHANGE:
+      case FAST_FORWARD:
+      case RENAMED:
+      case NOT_ATTEMPTED:
+
+      case IO_FAILURE:
+      case REJECTED:
+      case REJECTED_CURRENT_BRANCH:
+      case REJECTED_MISSING_OBJECT:
+      case REJECTED_OTHER_REASON:
+      default:
+        throw new IOException("Failed to delete " + refName + ": " + ru.getResult());
+    }
+  }
+
+  private RefUpdateUtil() {}
+}
diff --git a/java/com/google/gerrit/httpd/BUILD b/java/com/google/gerrit/httpd/BUILD
index 2294d0e..82547385 100644
--- a/java/com/google/gerrit/httpd/BUILD
+++ b/java/com/google/gerrit/httpd/BUILD
@@ -11,6 +11,7 @@
         "//java/com/google/gerrit/common:annotations",
         "//java/com/google/gerrit/common:server",
         "//java/com/google/gerrit/extensions:api",
+        "//java/com/google/gerrit/git",
         "//java/com/google/gerrit/launcher",
         "//java/com/google/gerrit/lifecycle",
         "//java/com/google/gerrit/metrics",
diff --git a/java/com/google/gerrit/httpd/GwtCacheControlFilter.java b/java/com/google/gerrit/httpd/GwtCacheControlFilter.java
deleted file mode 100644
index 5ac3d2f..0000000
--- a/java/com/google/gerrit/httpd/GwtCacheControlFilter.java
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.httpd;
-
-import com.google.gerrit.util.http.CacheHeaders;
-import com.google.inject.Singleton;
-import java.io.IOException;
-import java.util.concurrent.TimeUnit;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * Forces GWT resources to cache for a very long time.
- *
- * <p>GWT compiled JavaScript and ImageBundles can be cached indefinitely by a browser and/or an
- * edge proxy, as they never contain user-specific data and are named by a unique checksum. If their
- * content is ever modified then the URL changes, so user agents would request a different resource.
- * We force these resources to have very long expiration times.
- *
- * <p>To use, add the following block to your {@code web.xml}:
- *
- * <pre>
- * &lt;filter&gt;
- *     &lt;filter-name&gt;CacheControl&lt;/filter-name&gt;
- *     &lt;filter-class&gt;com.google.gwtexpui.server.CacheControlFilter&lt;/filter-class&gt;
- *   &lt;/filter&gt;
- *   &lt;filter-mapping&gt;
- *     &lt;filter-name&gt;CacheControl&lt;/filter-name&gt;
- *     &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
- *   &lt;/filter-mapping&gt;
- * </pre>
- */
-@Singleton
-class GwtCacheControlFilter implements Filter {
-  @Override
-  public void init(FilterConfig config) {}
-
-  @Override
-  public void destroy() {}
-
-  @Override
-  public void doFilter(final ServletRequest sreq, ServletResponse srsp, FilterChain chain)
-      throws IOException, ServletException {
-    final HttpServletRequest req = (HttpServletRequest) sreq;
-    final HttpServletResponse rsp = (HttpServletResponse) srsp;
-    final String pathInfo = pathInfo(req);
-
-    if (cacheForever(pathInfo, req)) {
-      CacheHeaders.setCacheable(req, rsp, 365, TimeUnit.DAYS);
-    } else if (nocache(pathInfo)) {
-      CacheHeaders.setNotCacheable(rsp);
-    }
-
-    chain.doFilter(req, rsp);
-  }
-
-  private static boolean cacheForever(String pathInfo, HttpServletRequest req) {
-    if (pathInfo.endsWith(".cache.html")
-        || pathInfo.endsWith(".cache.gif")
-        || pathInfo.endsWith(".cache.png")
-        || pathInfo.endsWith(".cache.css")
-        || pathInfo.endsWith(".cache.jar")
-        || pathInfo.endsWith(".cache.swf")
-        || pathInfo.endsWith(".cache.txt")
-        || pathInfo.endsWith(".cache.js")) {
-      return true;
-    } else if (pathInfo.endsWith(".nocache.js")) {
-      final String v = req.getParameter("content");
-      return v != null && v.length() > 20;
-    }
-    return false;
-  }
-
-  private static boolean nocache(String pathInfo) {
-    if (pathInfo.endsWith(".nocache.js")) {
-      return true;
-    }
-    return false;
-  }
-
-  private static String pathInfo(HttpServletRequest req) {
-    final String uri = req.getRequestURI();
-    final String ctx = req.getContextPath();
-    return uri.startsWith(ctx) ? uri.substring(ctx.length()) : uri;
-  }
-}
diff --git a/java/com/google/gerrit/httpd/NumericChangeIdRedirectServlet.java b/java/com/google/gerrit/httpd/NumericChangeIdRedirectServlet.java
new file mode 100644
index 0000000..164f957
--- /dev/null
+++ b/java/com/google/gerrit/httpd/NumericChangeIdRedirectServlet.java
@@ -0,0 +1,71 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.httpd;
+
+import com.google.gerrit.common.PageLinks;
+import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.server.change.ChangeResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
+import com.google.gerrit.server.restapi.change.ChangesCollection;
+import com.google.gwtorm.server.OrmException;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import java.io.IOException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/** Redirects {@code domain.tld/123} to {@code domain.tld/c/project/+/123}. */
+@Singleton
+public class NumericChangeIdRedirectServlet extends HttpServlet {
+  private static final long serialVersionUID = 1L;
+
+  private final ChangesCollection changesCollection;
+
+  @Inject
+  NumericChangeIdRedirectServlet(ChangesCollection changesCollection) {
+    this.changesCollection = changesCollection;
+  }
+
+  @Override
+  protected void doGet(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
+    String idString = req.getPathInfo();
+    if (idString.endsWith("/")) {
+      idString = idString.substring(0, idString.length() - 1);
+    }
+    Change.Id id;
+    try {
+      id = Change.Id.parse(idString);
+    } catch (IllegalArgumentException e) {
+      rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
+      return;
+    }
+
+    ChangeResource changeResource;
+    try {
+      changeResource = changesCollection.parse(id);
+    } catch (ResourceConflictException | ResourceNotFoundException e) {
+      rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
+      return;
+    } catch (OrmException | PermissionBackendException e) {
+      throw new IOException("Unable to lookup change " + id.id, e);
+    }
+    String path =
+        PageLinks.toChange(changeResource.getProject(), changeResource.getChange().getId());
+    UrlModule.toGerrit(path, req, rsp);
+  }
+}
diff --git a/java/com/google/gerrit/httpd/UrlModule.java b/java/com/google/gerrit/httpd/UrlModule.java
index 1dd176a..21ae9fb 100644
--- a/java/com/google/gerrit/httpd/UrlModule.java
+++ b/java/com/google/gerrit/httpd/UrlModule.java
@@ -20,8 +20,6 @@
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.extensions.client.AuthType;
 import com.google.gerrit.httpd.raw.CatServlet;
-import com.google.gerrit.httpd.raw.HostPageServlet;
-import com.google.gerrit.httpd.raw.LegacyGerritServlet;
 import com.google.gerrit.httpd.raw.SshInfoServlet;
 import com.google.gerrit.httpd.raw.ToolServlet;
 import com.google.gerrit.httpd.restapi.AccessRestApiServlet;
@@ -33,7 +31,6 @@
 import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.config.AuthConfig;
-import com.google.gerrit.server.config.GerritOptions;
 import com.google.inject.Key;
 import com.google.inject.Provider;
 import com.google.inject.internal.UniqueAnnotations;
@@ -45,27 +42,14 @@
 import org.eclipse.jgit.lib.Constants;
 
 class UrlModule extends ServletModule {
-  private GerritOptions options;
   private AuthConfig authConfig;
 
-  UrlModule(GerritOptions options, AuthConfig authConfig) {
-    this.options = options;
+  UrlModule(AuthConfig authConfig) {
     this.authConfig = authConfig;
   }
 
   @Override
   protected void configureServlets() {
-    filter("/*").through(GwtCacheControlFilter.class);
-
-    if (options.enableGwtUi()) {
-      filter("/").through(XsrfCookieFilter.class);
-      filter("/accounts/self/detail").through(XsrfCookieFilter.class);
-      serve("/").with(HostPageServlet.class);
-      serve("/Gerrit").with(LegacyGerritServlet.class);
-      serve("/Gerrit/*").with(legacyGerritScreen());
-      // Forward PolyGerrit URLs to their respective GWT equivalents.
-      serveRegex("^/(c|q|x|admin|dashboard|settings)/(.*)").with(gerritUrl());
-    }
     serve("/cat/*").with(CatServlet.class);
 
     if (authConfig.getAuthType() != AuthType.OAUTH && authConfig.getAuthType() != AuthType.OPENID) {
@@ -87,7 +71,7 @@
     serveRegex("^/settings/?$").with(screen(PageLinks.SETTINGS));
     serveRegex("^/register$").with(registerScreen(false));
     serveRegex("^/register/(.+)$").with(registerScreen(true));
-    serveRegex("^/([1-9][0-9]*)/?$").with(directChangeById());
+    serveRegex("^/([1-9][0-9]*)/?$").with(NumericChangeIdRedirectServlet.class);
     serveRegex("^/p/(.*)$").with(queryProjectNew());
     serveRegex("^/r/(.+)/?$").with(DirectChangeByCommit.class);
 
@@ -127,18 +111,6 @@
         });
   }
 
-  private Key<HttpServlet> gerritUrl() {
-    return key(
-        new HttpServlet() {
-          private static final long serialVersionUID = 1L;
-
-          @Override
-          protected void doGet(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
-            toGerrit(req.getRequestURI().substring(req.getContextPath().length()), req, rsp);
-          }
-        });
-  }
-
   private Key<HttpServlet> screen(String target) {
     return key(
         new HttpServlet() {
@@ -151,43 +123,6 @@
         });
   }
 
-  private Key<HttpServlet> legacyGerritScreen() {
-    return key(
-        new HttpServlet() {
-          private static final long serialVersionUID = 1L;
-
-          @Override
-          protected void doGet(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
-            final String token = req.getPathInfo().substring(1);
-            toGerrit(token, req, rsp);
-          }
-        });
-  }
-
-  private Key<HttpServlet> directChangeById() {
-    return key(
-        new HttpServlet() {
-          private static final long serialVersionUID = 1L;
-
-          @Override
-          protected void doGet(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
-            try {
-              String idString = req.getPathInfo();
-              if (idString.endsWith("/")) {
-                idString = idString.substring(0, idString.length() - 1);
-              }
-              Change.Id id = Change.Id.parse(idString);
-              // User accessed Gerrit with /1234, so we have no project yet.
-              // TODO(hiesel) Replace with a preflight request to obtain project before we deprecate
-              // the numeric change id.
-              toGerrit(PageLinks.toChange(null, id), req, rsp);
-            } catch (IllegalArgumentException err) {
-              rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
-            }
-          }
-        });
-  }
-
   private Key<HttpServlet> queryProjectNew() {
     return key(
         new HttpServlet() {
diff --git a/java/com/google/gerrit/httpd/WebModule.java b/java/com/google/gerrit/httpd/WebModule.java
index d115f43..e416075 100644
--- a/java/com/google/gerrit/httpd/WebModule.java
+++ b/java/com/google/gerrit/httpd/WebModule.java
@@ -21,7 +21,6 @@
 import com.google.gerrit.httpd.auth.container.HttpsClientSslCertModule;
 import com.google.gerrit.httpd.auth.ldap.LdapAuthModule;
 import com.google.gerrit.httpd.gitweb.GitwebModule;
-import com.google.gerrit.httpd.rpc.UiRpcModule;
 import com.google.gerrit.lifecycle.LifecycleModule;
 import com.google.gerrit.server.RemotePeer;
 import com.google.gerrit.server.config.AuthConfig;
@@ -55,10 +54,7 @@
 
     installAuthModule();
     if (options.enableMasterFeatures()) {
-      install(new UrlModule(options, authConfig));
-      if (options.enableGwtUi()) {
-        install(new UiRpcModule());
-      }
+      install(new UrlModule(authConfig));
     }
     install(new GerritRequestModule());
     install(new GitOverHttpServlet.Module(options.enableMasterFeatures()));
diff --git a/java/com/google/gerrit/httpd/auth/container/HttpAuthFilter.java b/java/com/google/gerrit/httpd/auth/container/HttpAuthFilter.java
index 0b3c29d..a1f44a8 100644
--- a/java/com/google/gerrit/httpd/auth/container/HttpAuthFilter.java
+++ b/java/com/google/gerrit/httpd/auth/container/HttpAuthFilter.java
@@ -25,7 +25,6 @@
 import com.google.gerrit.httpd.HtmlDomUtil;
 import com.google.gerrit.httpd.RemoteUserUtil;
 import com.google.gerrit.httpd.WebSession;
-import com.google.gerrit.httpd.raw.HostPageServlet;
 import com.google.gerrit.server.account.externalids.ExternalId;
 import com.google.gerrit.server.config.AuthConfig;
 import com.google.gerrit.util.http.CacheHeaders;
@@ -49,10 +48,10 @@
  * Watches request for the host page and requires login if not yet signed in.
  *
  * <p>If HTTP authentication has been enabled on this server this filter is bound in front of the
- * {@link HostPageServlet} and redirects users who are not yet signed in to visit {@code /login/},
- * so the web container can force login. This redirect is performed with JavaScript, such that any
- * existing anchor token in the URL can be rewritten and preserved through the authentication
- * process of any enterprise single sign-on solutions.
+ * Gerrit and redirects users who are not yet signed in to visit {@code /login/}, so the web
+ * container can force login. This redirect is performed with JavaScript, such that any existing
+ * anchor token in the URL can be rewritten and preserved through the authentication process of any
+ * enterprise single sign-on solutions.
  */
 @Singleton
 class HttpAuthFilter implements Filter {
diff --git a/java/com/google/gerrit/httpd/init/WebAppInitializer.java b/java/com/google/gerrit/httpd/init/WebAppInitializer.java
index 624b307..8870d1d 100644
--- a/java/com/google/gerrit/httpd/init/WebAppInitializer.java
+++ b/java/com/google/gerrit/httpd/init/WebAppInitializer.java
@@ -90,8 +90,8 @@
 import com.google.gerrit.server.schema.DataSourceType;
 import com.google.gerrit.server.schema.DatabaseModule;
 import com.google.gerrit.server.schema.JdbcAccountPatchReviewStore;
-import com.google.gerrit.server.schema.SchemaModule;
-import com.google.gerrit.server.schema.SchemaVersionCheck;
+import com.google.gerrit.server.schema.ReviewDbSchemaModule;
+import com.google.gerrit.server.schema.ReviewDbSchemaVersionCheck;
 import com.google.gerrit.server.securestore.SecureStoreClassName;
 import com.google.gerrit.server.ssh.NoSshModule;
 import com.google.gerrit.server.ssh.SshAddressesModule;
@@ -309,8 +309,8 @@
 
   private Injector createCfgInjector() {
     final List<Module> modules = new ArrayList<>();
-    modules.add(new SchemaModule());
-    modules.add(SchemaVersionCheck.module());
+    modules.add(new ReviewDbSchemaModule());
+    modules.add(ReviewDbSchemaVersionCheck.module());
     modules.add(new AuthConfigModule());
     return dbInjector.createChildInjector(modules);
   }
@@ -377,7 +377,7 @@
         new AbstractModule() {
           @Override
           protected void configure() {
-            bind(GerritOptions.class).toInstance(new GerritOptions(config, false, false, false));
+            bind(GerritOptions.class).toInstance(new GerritOptions(false, false, false));
             bind(GerritRuntime.class).toInstance(GerritRuntime.DAEMON);
           }
         });
diff --git a/java/com/google/gerrit/httpd/raw/BazelBuild.java b/java/com/google/gerrit/httpd/raw/BazelBuild.java
index 430f0b5..a13078d 100644
--- a/java/com/google/gerrit/httpd/raw/BazelBuild.java
+++ b/java/com/google/gerrit/httpd/raw/BazelBuild.java
@@ -147,11 +147,6 @@
     return sourceRoot.resolve("bazel-bin").resolve(l.pkg).resolve(l.name);
   }
 
-  /** Label for the agent specific GWT zip. */
-  public Label gwtZipLabel(String agent) {
-    return new Label("gerrit-gwtui", "ui_" + agent + ".zip");
-  }
-
   /** Label for the polygerrit component zip. */
   public Label polygerritComponents() {
     return new Label("polygerrit-ui", "polygerrit_components.bower_components.zip");
diff --git a/java/com/google/gerrit/httpd/raw/DirectoryGwtUiServlet.java b/java/com/google/gerrit/httpd/raw/DirectoryGwtUiServlet.java
deleted file mode 100644
index 8ac1601..0000000
--- a/java/com/google/gerrit/httpd/raw/DirectoryGwtUiServlet.java
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.httpd.raw;
-
-import com.google.common.cache.Cache;
-import com.google.gerrit.server.util.time.TimeUtil;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.attribute.FileTime;
-
-class DirectoryGwtUiServlet extends ResourceServlet {
-  private static final long serialVersionUID = 1L;
-
-  private static final FileTime NOW = FileTime.fromMillis(TimeUtil.nowMs());
-
-  private final Path ui;
-
-  DirectoryGwtUiServlet(Cache<Path, Resource> cache, Path unpackedWar, boolean dev)
-      throws IOException {
-    super(cache, false);
-    ui = unpackedWar.resolve("gerrit_ui");
-    if (!Files.exists(ui)) {
-      Files.createDirectory(ui);
-    }
-    if (dev) {
-      ui.toFile().deleteOnExit();
-    }
-  }
-
-  @Override
-  protected Path getResourcePath(String pathInfo) {
-    return ui.resolve(pathInfo);
-  }
-
-  @Override
-  protected FileTime getLastModifiedTime(Path p) {
-    // Return initialization time of this class, since the GWT outputs from the
-    // build process all have mtimes of 1980/1/1.
-    return NOW;
-  }
-}
diff --git a/java/com/google/gerrit/httpd/raw/HostPageServlet.java b/java/com/google/gerrit/httpd/raw/HostPageServlet.java
deleted file mode 100644
index 160732e..0000000
--- a/java/com/google/gerrit/httpd/raw/HostPageServlet.java
+++ /dev/null
@@ -1,410 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.httpd.raw;
-
-import static com.google.gerrit.common.FileUtil.lastModified;
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import com.google.common.base.Strings;
-import com.google.common.flogger.FluentLogger;
-import com.google.common.hash.Hasher;
-import com.google.common.hash.Hashing;
-import com.google.common.primitives.Bytes;
-import com.google.gerrit.common.Version;
-import com.google.gerrit.common.data.HostPageData;
-import com.google.gerrit.extensions.client.DiffPreferencesInfo;
-import com.google.gerrit.extensions.registration.DynamicSet;
-import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.systemstatus.MessageOfTheDay;
-import com.google.gerrit.extensions.webui.WebUiPlugin;
-import com.google.gerrit.httpd.HtmlDomUtil;
-import com.google.gerrit.server.CurrentUser;
-import com.google.gerrit.server.IdentifiedUser;
-import com.google.gerrit.server.account.AccountResource;
-import com.google.gerrit.server.config.ConfigUtil;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.gerrit.server.notedb.NotesMigration;
-import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gerrit.server.restapi.account.GetDiffPreferences;
-import com.google.gerrit.util.http.CacheHeaders;
-import com.google.gwtjsonrpc.server.JsonServlet;
-import com.google.gwtjsonrpc.server.RPCServletUtils;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.google.inject.Singleton;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.StringWriter;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.Config;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-/** Sends the Gerrit host page to clients. */
-@SuppressWarnings("serial")
-@Singleton
-public class HostPageServlet extends HttpServlet {
-  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
-  private static final String HPD_ID = "gerrit_hostpagedata";
-  private static final int DEFAULT_JS_LOAD_TIMEOUT = 5000;
-
-  private final Provider<CurrentUser> currentUser;
-  private final DynamicSet<WebUiPlugin> plugins;
-  private final DynamicSet<MessageOfTheDay> messages;
-  private final HostPageData.Theme signedOutTheme;
-  private final HostPageData.Theme signedInTheme;
-  private final SitePaths site;
-  private final Document template;
-  private final String noCacheName;
-  private final boolean refreshHeaderFooter;
-  private final SiteStaticDirectoryServlet staticServlet;
-  private final boolean isNoteDbEnabled;
-  private final Integer pluginsLoadTimeout;
-  private final boolean canLoadInIFrame;
-  private final GetDiffPreferences getDiff;
-  private volatile Page page;
-
-  @Inject
-  HostPageServlet(
-      Provider<CurrentUser> cu,
-      SitePaths sp,
-      ThemeFactory themeFactory,
-      ServletContext servletContext,
-      DynamicSet<WebUiPlugin> webUiPlugins,
-      DynamicSet<MessageOfTheDay> motd,
-      @GerritServerConfig Config cfg,
-      SiteStaticDirectoryServlet ss,
-      NotesMigration migration,
-      GetDiffPreferences diffPref)
-      throws IOException, ServletException {
-    currentUser = cu;
-    plugins = webUiPlugins;
-    messages = motd;
-    signedOutTheme = themeFactory.getSignedOutTheme();
-    signedInTheme = themeFactory.getSignedInTheme();
-    site = sp;
-    refreshHeaderFooter = cfg.getBoolean("site", "refreshHeaderFooter", true);
-    staticServlet = ss;
-    isNoteDbEnabled = migration.readChanges();
-    pluginsLoadTimeout = getPluginsLoadTimeout(cfg);
-    canLoadInIFrame = cfg.getBoolean("gerrit", "canLoadInIFrame", false);
-    getDiff = diffPref;
-
-    String pageName = "HostPage.html";
-    template = HtmlDomUtil.parseFile(getClass(), pageName);
-    if (template == null) {
-      throw new FileNotFoundException("No " + pageName + " in webapp");
-    }
-
-    if (HtmlDomUtil.find(template, "gerrit_module") == null) {
-      throw new ServletException("No gerrit_module in " + pageName);
-    }
-    if (HtmlDomUtil.find(template, HPD_ID) == null) {
-      throw new ServletException("No " + HPD_ID + " in " + pageName);
-    }
-
-    String src = "gerrit_ui/gerrit_ui.nocache.js";
-    try (InputStream in = servletContext.getResourceAsStream("/" + src)) {
-      if (in != null) {
-        Hasher md = Hashing.murmur3_128().newHasher();
-        byte[] buf = new byte[1024];
-        int n;
-        while ((n = in.read(buf)) > 0) {
-          md.putBytes(buf, 0, n);
-        }
-        src += "?content=" + md.hash().toString();
-      } else {
-        logger.atFine().log("No %s in webapp root; keeping noncache.js URL", src);
-      }
-    } catch (IOException e) {
-      throw new IOException("Failed reading " + src, e);
-    }
-
-    noCacheName = src;
-    page = new Page();
-  }
-
-  private static int getPluginsLoadTimeout(Config cfg) {
-    long cfgValue =
-        ConfigUtil.getTimeUnit(
-            cfg, "plugins", null, "jsLoadTimeout", DEFAULT_JS_LOAD_TIMEOUT, TimeUnit.MILLISECONDS);
-    if (cfgValue < 0) {
-      return 0;
-    }
-    return (int) cfgValue;
-  }
-
-  private void json(Object data, StringWriter w) {
-    JsonServlet.defaultGsonBuilder().create().toJson(data, w);
-  }
-
-  private Page get() {
-    Page p = page;
-    try {
-      if (refreshHeaderFooter && p.isStale()) {
-        p = new Page();
-        page = p;
-      }
-    } catch (IOException e) {
-      logger.atSevere().withCause(e).log("Cannot refresh site header/footer");
-    }
-    return p;
-  }
-
-  @Override
-  protected void doGet(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
-    Page.Content page = select(req);
-    StringWriter w = new StringWriter();
-    CurrentUser user = currentUser.get();
-    if (user.isIdentifiedUser()) {
-      w.write(HPD_ID + ".accountDiffPref=");
-      json(getDiffPreferences(user.asIdentifiedUser()), w);
-      w.write(";");
-
-      w.write(HPD_ID + ".theme=");
-      json(signedInTheme, w);
-      w.write(";");
-    } else {
-      w.write(HPD_ID + ".theme=");
-      json(signedOutTheme, w);
-      w.write(";");
-    }
-    plugins(w);
-    messages(w);
-
-    byte[] hpd = w.toString().getBytes(UTF_8);
-    byte[] raw = Bytes.concat(page.part1, hpd, page.part2);
-    byte[] tosend;
-    if (RPCServletUtils.acceptsGzipEncoding(req)) {
-      rsp.setHeader("Content-Encoding", "gzip");
-      tosend = HtmlDomUtil.compress(raw);
-    } else {
-      tosend = raw;
-    }
-
-    CacheHeaders.setNotCacheable(rsp);
-    rsp.setContentType("text/html");
-    rsp.setCharacterEncoding(HtmlDomUtil.ENC.name());
-    rsp.setContentLength(tosend.length);
-    try (OutputStream out = rsp.getOutputStream()) {
-      out.write(tosend);
-    }
-  }
-
-  private DiffPreferencesInfo getDiffPreferences(IdentifiedUser user) {
-    try {
-      return getDiff.apply(new AccountResource(user));
-    } catch (RestApiException
-        | ConfigInvalidException
-        | IOException
-        | PermissionBackendException e) {
-      logger.atWarning().withCause(e).log("Cannot query account diff preferences");
-    }
-    return DiffPreferencesInfo.defaults();
-  }
-
-  private void plugins(StringWriter w) {
-    List<String> urls = new ArrayList<>();
-    for (WebUiPlugin u : plugins) {
-      urls.add(String.format("plugins/%s/%s", u.getPluginName(), u.getJavaScriptResourcePath()));
-    }
-    if (!urls.isEmpty()) {
-      w.write(HPD_ID + ".plugins=");
-      json(urls, w);
-      w.write(";");
-    }
-  }
-
-  private void messages(StringWriter w) {
-    List<HostPageData.Message> list = new ArrayList<>(2);
-    for (MessageOfTheDay motd : messages) {
-      String html = motd.getHtmlMessage();
-      if (!Strings.isNullOrEmpty(html)) {
-        HostPageData.Message m = new HostPageData.Message();
-        m.id = motd.getMessageId();
-        m.redisplay = motd.getRedisplay();
-        m.html = html;
-        list.add(m);
-      }
-    }
-    if (!list.isEmpty()) {
-      w.write(HPD_ID + ".messages=");
-      json(list, w);
-      w.write(";");
-    }
-  }
-
-  private Page.Content select(HttpServletRequest req) {
-    Page pg = get();
-    if ("1".equals(req.getParameter("dbg"))) {
-      return pg.debug;
-    }
-    return pg.opt;
-  }
-
-  private void insertETags(Element e) {
-    if ("img".equalsIgnoreCase(e.getTagName()) || "script".equalsIgnoreCase(e.getTagName())) {
-      String src = e.getAttribute("src");
-      if (src != null && src.startsWith("static/")) {
-        String name = src.substring("static/".length());
-        ResourceServlet.Resource r = staticServlet.getResource(name);
-        if (r != null) {
-          e.setAttribute("src", src + "?e=" + r.etag);
-        }
-      }
-    }
-
-    for (Node n = e.getFirstChild(); n != null; n = n.getNextSibling()) {
-      if (n instanceof Element) {
-        insertETags((Element) n);
-      }
-    }
-  }
-
-  private static class FileInfo {
-    private final Path path;
-    private final long time;
-
-    FileInfo(Path p) {
-      path = p;
-      time = lastModified(path);
-    }
-
-    boolean isStale() {
-      return time != lastModified(path);
-    }
-  }
-
-  private class Page {
-    private final FileInfo css;
-    private final FileInfo header;
-    private final FileInfo footer;
-    private final Content opt;
-    private final Content debug;
-
-    Page() throws IOException {
-      Document hostDoc = HtmlDomUtil.clone(template);
-
-      css = injectCssFile(hostDoc, "gerrit_sitecss", site.site_css);
-      header = injectXmlFile(hostDoc, "gerrit_header", site.site_header);
-      footer = injectXmlFile(hostDoc, "gerrit_footer", site.site_footer);
-
-      HostPageData pageData = new HostPageData();
-      pageData.version = Version.getVersion();
-      pageData.isNoteDbEnabled = isNoteDbEnabled;
-      pageData.pluginsLoadTimeout = pluginsLoadTimeout;
-      pageData.canLoadInIFrame = canLoadInIFrame;
-
-      StringWriter w = new StringWriter();
-      w.write("var " + HPD_ID + "=");
-      json(pageData, w);
-      w.write(";");
-
-      Element data = HtmlDomUtil.find(hostDoc, HPD_ID);
-      asScript(data);
-      data.appendChild(hostDoc.createTextNode(w.toString()));
-      data.appendChild(hostDoc.createComment(HPD_ID));
-
-      Element nocache = HtmlDomUtil.find(hostDoc, "gerrit_module");
-      asScript(nocache);
-      nocache.removeAttribute("id");
-      nocache.setAttribute("src", noCacheName);
-      opt = new Content(hostDoc);
-
-      nocache.setAttribute("src", "gerrit_ui/dbg_gerrit_ui.nocache.js");
-      debug = new Content(hostDoc);
-    }
-
-    boolean isStale() {
-      return css.isStale() || header.isStale() || footer.isStale();
-    }
-
-    private void asScript(Element scriptNode) {
-      scriptNode.setAttribute("type", "text/javascript");
-      scriptNode.setAttribute("language", "javascript");
-    }
-
-    class Content {
-      final byte[] part1;
-      final byte[] part2;
-
-      Content(Document hostDoc) throws IOException {
-        String raw = HtmlDomUtil.toString(hostDoc);
-        int p = raw.indexOf("<!--" + HPD_ID);
-        if (p < 0) {
-          throw new IOException("No tag in transformed host page HTML");
-        }
-        part1 = raw.substring(0, p).getBytes(UTF_8);
-        part2 = raw.substring(raw.indexOf('>', p) + 1).getBytes(UTF_8);
-      }
-    }
-
-    private FileInfo injectCssFile(Document hostDoc, String id, Path src) throws IOException {
-      FileInfo info = new FileInfo(src);
-      Element banner = HtmlDomUtil.find(hostDoc, id);
-      if (banner == null) {
-        return info;
-      }
-
-      while (banner.getFirstChild() != null) {
-        banner.removeChild(banner.getFirstChild());
-      }
-
-      String css = HtmlDomUtil.readFile(src.getParent(), src.getFileName().toString());
-      if (css == null) {
-        return info;
-      }
-
-      banner.appendChild(hostDoc.createCDATASection("\n" + css + "\n"));
-      return info;
-    }
-
-    private FileInfo injectXmlFile(Document hostDoc, String id, Path src) throws IOException {
-      FileInfo info = new FileInfo(src);
-      Element banner = HtmlDomUtil.find(hostDoc, id);
-      if (banner == null) {
-        return info;
-      }
-
-      while (banner.getFirstChild() != null) {
-        banner.removeChild(banner.getFirstChild());
-      }
-
-      Document html = HtmlDomUtil.parseFile(src);
-      if (html == null) {
-        return info;
-      }
-
-      Element content = html.getDocumentElement();
-      insertETags(content);
-      banner.appendChild(hostDoc.importNode(content, true));
-      return info;
-    }
-  }
-}
diff --git a/java/com/google/gerrit/httpd/raw/RecompileGwtUiFilter.java b/java/com/google/gerrit/httpd/raw/RecompileGwtUiFilter.java
deleted file mode 100644
index c6c3367..0000000
--- a/java/com/google/gerrit/httpd/raw/RecompileGwtUiFilter.java
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.httpd.raw;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-class RecompileGwtUiFilter implements Filter {
-  private final boolean gwtuiRecompile =
-      System.getProperty("gerrit.disable-gwtui-recompile") == null;
-  private final UserAgentRule rule = new UserAgentRule();
-  private final Set<String> uaInitialized = new HashSet<>();
-  private final Path unpackedWar;
-  private final BazelBuild builder;
-
-  private String lastAgent;
-  private long lastTime;
-
-  RecompileGwtUiFilter(BazelBuild builder, Path unpackedWar) {
-    this.builder = builder;
-    this.unpackedWar = unpackedWar;
-  }
-
-  @Override
-  public void doFilter(ServletRequest request, ServletResponse res, FilterChain chain)
-      throws IOException, ServletException {
-    String agent = rule.select((HttpServletRequest) request);
-    if (unpackedWar != null && (gwtuiRecompile || !uaInitialized.contains(agent))) {
-      BazelBuild.Label label = builder.gwtZipLabel(agent);
-      File zip = builder.targetPath(label).toFile();
-
-      synchronized (this) {
-        try {
-          builder.build(label);
-        } catch (BazelBuild.BuildFailureException e) {
-          e.display(label.toString(), (HttpServletResponse) res);
-          return;
-        }
-
-        if (!agent.equals(lastAgent) || lastTime != zip.lastModified()) {
-          lastAgent = agent;
-          lastTime = zip.lastModified();
-          unpack(zip, unpackedWar.toFile());
-        }
-      }
-      uaInitialized.add(agent);
-    }
-    chain.doFilter(request, res);
-  }
-
-  @Override
-  public void init(FilterConfig config) {}
-
-  @Override
-  public void destroy() {}
-
-  private static void unpack(File srcwar, File dstwar) throws IOException {
-    try (ZipFile zf = new ZipFile(srcwar)) {
-      final Enumeration<? extends ZipEntry> e = zf.entries();
-      while (e.hasMoreElements()) {
-        final ZipEntry ze = e.nextElement();
-        final String name = ze.getName();
-
-        if (ze.isDirectory()
-            || name.startsWith("WEB-INF/")
-            || name.startsWith("META-INF/")
-            || name.startsWith("com/google/gerrit/launcher/")
-            || name.equals("Main.class")) {
-          continue;
-        }
-
-        final File rawtmp = new File(dstwar, name);
-        mkdir(rawtmp.getParentFile());
-        rawtmp.deleteOnExit();
-
-        try (OutputStream rawout = Files.newOutputStream(rawtmp.toPath());
-            InputStream in = zf.getInputStream(ze)) {
-          final byte[] buf = new byte[4096];
-          int n;
-          while ((n = in.read(buf, 0, buf.length)) > 0) {
-            rawout.write(buf, 0, n);
-          }
-        }
-      }
-    }
-  }
-
-  private static void mkdir(File dir) throws IOException {
-    if (!dir.isDirectory()) {
-      mkdir(dir.getParentFile());
-      if (!dir.mkdir()) {
-        throw new IOException("Cannot mkdir " + dir.getAbsolutePath());
-      }
-      dir.deleteOnExit();
-    }
-  }
-}
diff --git a/java/com/google/gerrit/httpd/raw/StaticModule.java b/java/com/google/gerrit/httpd/raw/StaticModule.java
index 062d776..a950ac9 100644
--- a/java/com/google/gerrit/httpd/raw/StaticModule.java
+++ b/java/com/google/gerrit/httpd/raw/StaticModule.java
@@ -22,7 +22,6 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.flogger.FluentLogger;
 import com.google.gerrit.common.Nullable;
-import com.google.gerrit.extensions.client.UiType;
 import com.google.gerrit.httpd.XsrfCookieFilter;
 import com.google.gerrit.httpd.raw.ResourceServlet.Resource;
 import com.google.gerrit.launcher.GerritLauncher;
@@ -51,7 +50,6 @@
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
-import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequestWrapper;
@@ -102,12 +100,9 @@
 
   private static final String DOC_SERVLET = "DocServlet";
   private static final String FAVICON_SERVLET = "FaviconServlet";
-  private static final String GWT_UI_SERVLET = "GwtUiServlet";
   private static final String POLYGERRIT_INDEX_SERVLET = "PolyGerritUiIndexServlet";
   private static final String ROBOTS_TXT_SERVLET = "RobotsTxtServlet";
 
-  private static final int GERRIT_UI_COOKIE_MAX_AGE = 60 * 60 * 24 * 365;
-
   private final GerritOptions options;
   private Paths paths;
 
@@ -145,10 +140,6 @@
     }
 
     install(new PolyGerritModule());
-
-    if (options.enableGwtUi()) {
-      install(new GwtUiModule());
-    }
   }
 
   @Provides
@@ -221,38 +212,11 @@
     }
   }
 
-  private class GwtUiModule extends ServletModule {
-    @Override
-    public void configureServlets() {
-      serveRegex("^/gerrit_ui/(?!rpc/)(.*)$")
-          .with(Key.get(HttpServlet.class, Names.named(GWT_UI_SERVLET)));
-      Paths p = getPaths();
-      if (p.isDev()) {
-        filter("/").through(new RecompileGwtUiFilter(p.builder, p.unpackedWar));
-      }
-    }
-
-    @Provides
-    @Singleton
-    @Named(GWT_UI_SERVLET)
-    HttpServlet getGwtUiServlet(@Named(CACHE) Cache<Path, Resource> cache) throws IOException {
-      Paths p = getPaths();
-      if (p.warFs != null) {
-        return new WarGwtUiServlet(cache, p.warFs);
-      }
-      return new DirectoryGwtUiServlet(cache, p.unpackedWar, p.isDev());
-    }
-  }
-
   private class PolyGerritModule extends ServletModule {
     @Override
     public void configureServlets() {
       for (String p : POLYGERRIT_INDEX_PATHS) {
-        // Skip XsrfCookieFilter for /, since that is already done in the GWT UI
-        // path (UrlModule).
-        if (!p.equals("/")) {
-          filter(p).through(XsrfCookieFilter.class);
-        }
+        filter(p).through(XsrfCookieFilter.class);
       }
       filter("/*").through(PolyGerritFilter.class);
     }
@@ -414,7 +378,6 @@
 
   @Singleton
   private static class PolyGerritFilter implements Filter {
-    private final GerritOptions options;
     private final Paths paths;
     private final HttpServlet polyGerritIndex;
     private final PolyGerritUiServlet polygerritUI;
@@ -423,14 +386,12 @@
 
     @Inject
     PolyGerritFilter(
-        GerritOptions options,
         Paths paths,
         @Named(POLYGERRIT_INDEX_SERVLET) HttpServlet polyGerritIndex,
         PolyGerritUiServlet polygerritUI,
         @Nullable BowerComponentsDevServlet bowerComponentServlet,
         @Nullable FontsDevServlet fontServlet) {
       this.paths = paths;
-      this.options = options;
       this.polyGerritIndex = polyGerritIndex;
       this.polygerritUI = polygerritUI;
       this.bowerComponentServlet = bowerComponentServlet;
@@ -448,13 +409,6 @@
         throws IOException, ServletException {
       HttpServletRequest req = (HttpServletRequest) request;
       HttpServletResponse res = (HttpServletResponse) response;
-      if (handlePolyGerritParam(req, res)) {
-        return;
-      }
-      if (!isPolyGerritEnabled(req)) {
-        chain.doFilter(req, res);
-        return;
-      }
 
       GuiceFilterRequestWrapper reqWrapper = new GuiceFilterRequestWrapper(req);
       String path = pathInfo(req);
@@ -493,71 +447,6 @@
       return uri.startsWith(ctx) ? uri.substring(ctx.length()) : uri;
     }
 
-    private boolean handlePolyGerritParam(HttpServletRequest req, HttpServletResponse res)
-        throws IOException {
-      if (!options.enableGwtUi() || !"GET".equals(req.getMethod())) {
-        return false;
-      }
-      boolean redirect = false;
-      String param = req.getParameter("polygerrit");
-      if ("1".equals(param)) {
-        setPolyGerritCookie(req, res, UiType.POLYGERRIT);
-        redirect = true;
-      } else if ("0".equals(param)) {
-        setPolyGerritCookie(req, res, UiType.GWT);
-        redirect = true;
-      }
-      if (redirect) {
-        // Strip polygerrit param from URL. This actually strips all params,
-        // which is a similar behavior to the JS PolyGerrit redirector code.
-        // Stripping just one param is frustratingly difficult without the use
-        // of Apache httpclient, which is a dep we don't want here:
-        // https://gerrit-review.googlesource.com/#/c/57570/57/gerrit-httpd/BUCK@32
-        res.sendRedirect(req.getRequestURL().toString());
-      }
-      return redirect;
-    }
-
-    private boolean isPolyGerritEnabled(HttpServletRequest req) {
-      return !options.enableGwtUi() || isPolyGerritCookie(req);
-    }
-
-    private boolean isPolyGerritCookie(HttpServletRequest req) {
-      UiType type = UiType.POLYGERRIT;
-      Cookie[] all = req.getCookies();
-      if (all != null) {
-        for (Cookie c : all) {
-          if (GERRIT_UI_COOKIE.equals(c.getName())) {
-            UiType t = UiType.parse(c.getValue());
-            if (t != null) {
-              type = t;
-              break;
-            }
-          }
-        }
-      }
-      return type == UiType.POLYGERRIT;
-    }
-
-    private void setPolyGerritCookie(HttpServletRequest req, HttpServletResponse res, UiType pref) {
-      // Only actually set a cookie if GWT UI is enabled in addition to default PG UI;
-      // otherwise clear it.
-      Cookie cookie = new Cookie(GERRIT_UI_COOKIE, pref.name());
-      if (options.enableGwtUi()) {
-        cookie.setPath("/");
-        cookie.setSecure(isSecure(req));
-        cookie.setMaxAge(GERRIT_UI_COOKIE_MAX_AGE);
-      } else {
-        cookie.setValue("");
-        cookie.setMaxAge(0);
-      }
-      res.addCookie(cookie);
-    }
-
-    private static boolean isSecure(HttpServletRequest req) {
-      return req.isSecure() || "https".equals(req.getScheme());
-    }
-
     private static boolean isPolyGerritAsset(String path) {
       return matchPath(POLYGERRIT_ASSET_PATHS, path);
     }
diff --git a/java/com/google/gerrit/httpd/raw/ThemeFactory.java b/java/com/google/gerrit/httpd/raw/ThemeFactory.java
deleted file mode 100644
index 6a75e07..0000000
--- a/java/com/google/gerrit/httpd/raw/ThemeFactory.java
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (C) 2011 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.httpd.raw;
-
-import com.google.gerrit.common.data.HostPageData;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.inject.Inject;
-import org.eclipse.jgit.lib.Config;
-
-class ThemeFactory {
-  private final Config cfg;
-
-  @Inject
-  ThemeFactory(@GerritServerConfig Config cfg) {
-    this.cfg = cfg;
-  }
-
-  HostPageData.Theme getSignedOutTheme() {
-    return getTheme("signed-out");
-  }
-
-  HostPageData.Theme getSignedInTheme() {
-    return getTheme("signed-in");
-  }
-
-  private HostPageData.Theme getTheme(String name) {
-    HostPageData.Theme theme = new HostPageData.Theme();
-    theme.backgroundColor = color(name, "backgroundColor", "#FFFFFF");
-    theme.textColor = color(name, "textColor", "#353535");
-    theme.trimColor = color(name, "trimColor", "#EEEEEE");
-    theme.selectionColor = color(name, "selectionColor", "#D8EDF9");
-    theme.topMenuColor = color(name, "topMenuColor", "#FFFFFF");
-    theme.changeTableOutdatedColor = color(name, "changeTableOutdatedColor", "#F08080");
-    theme.tableOddRowColor = color(name, "tableOddRowColor", "transparent");
-    theme.tableEvenRowColor = color(name, "tableEvenRowColor", "transparent");
-    return theme;
-  }
-
-  private String color(String section, String name, String defaultValue) {
-    String v = cfg.getString("theme", section, name);
-    if (v == null || v.isEmpty()) {
-      v = cfg.getString("theme", null, name);
-      if (v == null || v.isEmpty()) {
-        v = defaultValue;
-      }
-    }
-    if (!v.startsWith("#") && v.matches("^[0-9a-fA-F]{2,6}$")) {
-      v = "#" + v;
-    }
-    return v;
-  }
-}
diff --git a/java/com/google/gerrit/httpd/raw/UserAgentRule.java b/java/com/google/gerrit/httpd/raw/UserAgentRule.java
deleted file mode 100644
index 4aac243..0000000
--- a/java/com/google/gerrit/httpd/raw/UserAgentRule.java
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.httpd.raw;
-
-import static java.util.regex.Pattern.compile;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.servlet.http.HttpServletRequest;
-
-/**
- * Selects the value for the {@code user.agent} property.
- *
- * <p>Examines the {@code User-Agent} HTTP request header, and tries to match it to known {@code
- * user.agent} values.
- *
- * <p>Ported from JavaScript in {@code com.google.gwt.user.UserAgent.gwt.xml}.
- */
-class UserAgentRule {
-  private static final Pattern msie = compile(".*msie ([0-11]+)\\.([0-11]+).*");
-  private static final Pattern gecko = compile(".*rv:([0-9]+)\\.([0-9]+).*");
-
-  String getName() {
-    return "user.agent";
-  }
-
-  String select(HttpServletRequest req) {
-    String ua = req.getHeader("User-Agent");
-    if (ua == null) {
-      return null;
-    }
-
-    ua = ua.toLowerCase();
-
-    if (ua.contains("opera")) {
-      return "opera";
-
-    } else if (ua.contains("webkit")) {
-      return "safari";
-
-    } else if (ua.contains("msie")) {
-      // GWT 2.0 uses document.documentMode here, which we can't do
-      // on the server side.
-
-      Matcher m = msie.matcher(ua);
-      if (m.matches() && m.groupCount() == 2) {
-        int v = makeVersion(m);
-        if (v >= 11000) {
-          return "ie11";
-        }
-        if (v >= 10000) {
-          return "ie10";
-        }
-        if (v >= 9000) {
-          return "ie9";
-        }
-        if (v >= 8000) {
-          return "ie8";
-        }
-      }
-      return null;
-
-    } else if (ua.contains("edge")) {
-      return "edge";
-    } else if (ua.contains("gecko")) {
-      Matcher m = gecko.matcher(ua);
-      if (m.matches() && m.groupCount() == 2) {
-        if (makeVersion(m) >= 1008) {
-          return "gecko1_8";
-        }
-      }
-      return "gecko";
-    }
-
-    return null;
-  }
-
-  private int makeVersion(Matcher result) {
-    return (Integer.parseInt(result.group(1)) * 1000) + Integer.parseInt(result.group(2));
-  }
-}
diff --git a/java/com/google/gerrit/httpd/raw/WarGwtUiServlet.java b/java/com/google/gerrit/httpd/raw/WarGwtUiServlet.java
deleted file mode 100644
index 5fe7054..0000000
--- a/java/com/google/gerrit/httpd/raw/WarGwtUiServlet.java
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.httpd.raw;
-
-import com.google.common.cache.Cache;
-import com.google.gerrit.server.util.time.TimeUtil;
-import java.nio.file.FileSystem;
-import java.nio.file.Path;
-import java.nio.file.attribute.FileTime;
-
-class WarGwtUiServlet extends ResourceServlet {
-  private static final long serialVersionUID = 1L;
-
-  private static final FileTime NOW = FileTime.fromMillis(TimeUtil.nowMs());
-
-  private final FileSystem warFs;
-
-  WarGwtUiServlet(Cache<Path, Resource> cache, FileSystem warFs) {
-    super(cache, false);
-    this.warFs = warFs;
-  }
-
-  @Override
-  protected Path getResourcePath(String pathInfo) {
-    return warFs.getPath("/gerrit_ui/" + pathInfo);
-  }
-
-  @Override
-  protected FileTime getLastModifiedTime(Path p) {
-    // Return initialization time of this class, since the GWT outputs from the
-    // build process all have mtimes of 1980/1/1.
-    return NOW;
-  }
-}
diff --git a/java/com/google/gerrit/httpd/restapi/RestApiServlet.java b/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
index 519a218..ec71d8f 100644
--- a/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
+++ b/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
@@ -97,6 +97,7 @@
 import com.google.gerrit.extensions.restapi.RestView;
 import com.google.gerrit.extensions.restapi.TopLevelResource;
 import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
+import com.google.gerrit.git.LockFailureException;
 import com.google.gerrit.httpd.WebSession;
 import com.google.gerrit.httpd.restapi.ParameterParser.QueryParams;
 import com.google.gerrit.server.AccessPath;
@@ -108,7 +109,6 @@
 import com.google.gerrit.server.audit.ExtendedHttpAuditEvent;
 import com.google.gerrit.server.cache.PerThreadCache;
 import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.git.LockFailureException;
 import com.google.gerrit.server.logging.RequestId;
 import com.google.gerrit.server.logging.TraceContext;
 import com.google.gerrit.server.permissions.GlobalPermission;
diff --git a/java/com/google/gerrit/httpd/rpc/AuditedHttpServletResponse.java b/java/com/google/gerrit/httpd/rpc/AuditedHttpServletResponse.java
deleted file mode 100644
index 31819e8..0000000
--- a/java/com/google/gerrit/httpd/rpc/AuditedHttpServletResponse.java
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.httpd.rpc;
-
-import java.io.IOException;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpServletResponseWrapper;
-
-class AuditedHttpServletResponse extends HttpServletResponseWrapper implements HttpServletResponse {
-  private int status;
-
-  AuditedHttpServletResponse(HttpServletResponse response) {
-    super(response);
-  }
-
-  @SuppressWarnings("all") // @Override for servlet API 3.0+ only.
-  public int getStatus() {
-    return status;
-  }
-
-  @Override
-  public void setStatus(int sc) {
-    super.setStatus(sc);
-    this.status = sc;
-  }
-
-  @Override
-  @Deprecated
-  public void setStatus(int sc, String sm) {
-    super.setStatus(sc, sm);
-    this.status = sc;
-  }
-
-  @Override
-  public void sendError(int sc) throws IOException {
-    super.sendError(sc);
-    this.status = sc;
-  }
-
-  @Override
-  public void sendError(int sc, String msg) throws IOException {
-    super.sendError(sc, msg);
-    this.status = sc;
-  }
-
-  @Override
-  public void sendRedirect(String location) throws IOException {
-    super.sendRedirect(location);
-    this.status = SC_MOVED_TEMPORARILY;
-  }
-}
diff --git a/java/com/google/gerrit/httpd/rpc/GerritJsonServlet.java b/java/com/google/gerrit/httpd/rpc/GerritJsonServlet.java
deleted file mode 100644
index 16e82e9..0000000
--- a/java/com/google/gerrit/httpd/rpc/GerritJsonServlet.java
+++ /dev/null
@@ -1,288 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.httpd.rpc;
-
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.MultimapBuilder;
-import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.common.audit.Audit;
-import com.google.gerrit.common.auth.SignInRequired;
-import com.google.gerrit.common.errors.NotSignedInException;
-import com.google.gerrit.extensions.registration.DynamicItem;
-import com.google.gerrit.httpd.WebSession;
-import com.google.gerrit.server.AccessPath;
-import com.google.gerrit.server.CurrentUser;
-import com.google.gerrit.server.audit.AuditService;
-import com.google.gerrit.server.audit.RpcAuditEvent;
-import com.google.gerrit.server.util.time.TimeUtil;
-import com.google.gson.GsonBuilder;
-import com.google.gwtjsonrpc.common.RemoteJsonService;
-import com.google.gwtjsonrpc.server.ActiveCall;
-import com.google.gwtjsonrpc.server.JsonServlet;
-import com.google.gwtjsonrpc.server.MethodHandle;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/** Base JSON servlet to ensure the current user is not forged. */
-@SuppressWarnings("serial")
-final class GerritJsonServlet extends JsonServlet<GerritJsonServlet.GerritCall> {
-  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
-  private static final ThreadLocal<GerritCall> currentCall = new ThreadLocal<>();
-  private static final ThreadLocal<MethodHandle> currentMethod = new ThreadLocal<>();
-  private final DynamicItem<WebSession> session;
-  private final RemoteJsonService service;
-  private final AuditService audit;
-
-  @Inject
-  GerritJsonServlet(final DynamicItem<WebSession> w, RemoteJsonService s, AuditService a) {
-    session = w;
-    service = s;
-    audit = a;
-  }
-
-  @Override
-  protected GerritCall createActiveCall(final HttpServletRequest req, HttpServletResponse rsp) {
-    final GerritCall call = new GerritCall(session.get(), req, new AuditedHttpServletResponse(rsp));
-    currentCall.set(call);
-    return call;
-  }
-
-  @Override
-  protected GsonBuilder createGsonBuilder() {
-    return gerritDefaultGsonBuilder();
-  }
-
-  private static GsonBuilder gerritDefaultGsonBuilder() {
-    final GsonBuilder g = defaultGsonBuilder();
-
-    g.registerTypeAdapter(
-        org.eclipse.jgit.diff.Edit.class, new org.eclipse.jgit.diff.EditDeserializer());
-
-    return g;
-  }
-
-  @Override
-  protected void preInvoke(GerritCall call) {
-    super.preInvoke(call);
-
-    if (call.isComplete()) {
-      return;
-    }
-
-    if (call.getMethod().getAnnotation(SignInRequired.class) != null) {
-      // If SignInRequired is set on this method we must have both a
-      // valid XSRF token *and* have the user signed in. Doing these
-      // checks also validates that they agree on the user identity.
-      //
-      if (!call.requireXsrfValid() || !session.get().isSignedIn()) {
-        call.onFailure(new NotSignedInException());
-      }
-    }
-  }
-
-  @Override
-  protected Object createServiceHandle() {
-    return service;
-  }
-
-  @Override
-  protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {
-    try {
-      super.service(req, resp);
-    } finally {
-      audit();
-      currentCall.set(null);
-    }
-  }
-
-  private void audit() {
-    try {
-      GerritCall call = currentCall.get();
-      MethodHandle method = call.getMethod();
-      if (method == null) {
-        return;
-      }
-      Audit note = method.getAnnotation(Audit.class);
-      if (note != null) {
-        String sid = call.getWebSession().getSessionId();
-        CurrentUser username = call.getWebSession().getUser();
-        ListMultimap<String, ?> args = extractParams(note, call);
-        String what = extractWhat(note, call);
-        Object result = call.getResult();
-
-        audit.dispatch(
-            new RpcAuditEvent(
-                sid,
-                username,
-                what,
-                call.getWhen(),
-                args,
-                call.getHttpServletRequest().getMethod(),
-                call.getHttpServletRequest().getMethod(),
-                ((AuditedHttpServletResponse) (call.getHttpServletResponse())).getStatus(),
-                result));
-      }
-    } catch (Throwable all) {
-      logger.atSevere().withCause(all).log("Unable to log the call");
-    }
-  }
-
-  private ListMultimap<String, ?> extractParams(Audit note, GerritCall call) {
-    ListMultimap<String, Object> args = MultimapBuilder.hashKeys().arrayListValues().build();
-
-    Object[] params = call.getParams();
-    for (int i = 0; i < params.length; i++) {
-      args.put("$" + i, params[i]);
-    }
-
-    for (int idx : note.obfuscate()) {
-      args.removeAll("$" + idx);
-      args.put("$" + idx, "*****");
-    }
-    return args;
-  }
-
-  private String extractWhat(Audit note, GerritCall call) {
-    Class<?> methodClass = call.getMethodClass();
-    String methodClassName = methodClass != null ? methodClass.getName() : "<UNKNOWN_CLASS>";
-    methodClassName = methodClassName.substring(methodClassName.lastIndexOf('.') + 1);
-    String what = note.action();
-    if (what.length() == 0) {
-      what = call.getMethod().getName();
-    }
-
-    return methodClassName + "." + what;
-  }
-
-  static class GerritCall extends ActiveCall {
-    private final WebSession session;
-    private final long when;
-    private static final Field resultField;
-    private static final Field methodField;
-
-    // Needed to allow access to non-public result field in GWT/JSON-RPC
-    static {
-      resultField = getPrivateField(ActiveCall.class, "result");
-      methodField = getPrivateField(MethodHandle.class, "method");
-    }
-
-    private static Field getPrivateField(Class<?> clazz, String fieldName) {
-      Field declaredField = null;
-      try {
-        declaredField = clazz.getDeclaredField(fieldName);
-        declaredField.setAccessible(true);
-      } catch (Exception e) {
-        logger.atSevere().log("Unable to expose RPS/JSON result field");
-      }
-      return declaredField;
-    }
-
-    // Surrogate of the missing getMethodClass() in GWT/JSON-RPC
-    public Class<?> getMethodClass() {
-      if (methodField == null) {
-        return null;
-      }
-
-      try {
-        Method method = (Method) methodField.get(this.getMethod());
-        return method.getDeclaringClass();
-      } catch (IllegalArgumentException e) {
-        logger.atSevere().log("Cannot access result field");
-      } catch (IllegalAccessException e) {
-        logger.atSevere().log("No permissions to access result field");
-      }
-
-      return null;
-    }
-
-    // Surrogate of the missing getResult() in GWT/JSON-RPC
-    public Object getResult() {
-      if (resultField == null) {
-        return null;
-      }
-
-      try {
-        return resultField.get(this);
-      } catch (IllegalArgumentException e) {
-        logger.atSevere().log("Cannot access result field");
-      } catch (IllegalAccessException e) {
-        logger.atSevere().log("No permissions to access result field");
-      }
-
-      return null;
-    }
-
-    GerritCall(WebSession session, HttpServletRequest i, HttpServletResponse o) {
-      super(i, o);
-      this.session = session;
-      this.when = TimeUtil.nowMs();
-    }
-
-    @Override
-    public MethodHandle getMethod() {
-      if (currentMethod.get() == null) {
-        return super.getMethod();
-      }
-      return currentMethod.get();
-    }
-
-    @Override
-    public void onFailure(Throwable error) {
-      if (error instanceof IllegalArgumentException || error instanceof IllegalStateException) {
-        super.onFailure(error);
-      } else if (error instanceof OrmException || error instanceof RuntimeException) {
-        onInternalFailure(error);
-      } else {
-        super.onFailure(error);
-      }
-    }
-
-    @Override
-    public boolean xsrfValidate() {
-      final String keyIn = getXsrfKeyIn();
-      if (keyIn == null || "".equals(keyIn)) {
-        // Anonymous requests don't need XSRF protection, they shouldn't
-        // be able to cause critical state changes.
-        //
-        return !session.isSignedIn();
-
-      } else if (session.isSignedIn() && session.isValidXGerritAuth(keyIn)) {
-        // The session must exist, and must be using this token.
-        //
-        session.getUser().setAccessPath(AccessPath.JSON_RPC);
-        return true;
-      }
-      return false;
-    }
-
-    public WebSession getWebSession() {
-      return session;
-    }
-
-    public long getWhen() {
-      return when;
-    }
-
-    public long getElapsed() {
-      return TimeUtil.nowMs() - when;
-    }
-  }
-}
diff --git a/java/com/google/gerrit/httpd/rpc/GerritJsonServletProvider.java b/java/com/google/gerrit/httpd/rpc/GerritJsonServletProvider.java
deleted file mode 100644
index b167167..0000000
--- a/java/com/google/gerrit/httpd/rpc/GerritJsonServletProvider.java
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.httpd.rpc;
-
-import com.google.gwtjsonrpc.common.RemoteJsonService;
-import com.google.inject.AbstractModule;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.Provider;
-
-/** Creates {@link GerritJsonServlet} with a {@link RemoteJsonService}. */
-class GerritJsonServletProvider implements Provider<GerritJsonServlet> {
-  @Inject private Injector injector;
-
-  private final Class<? extends RemoteJsonService> serviceClass;
-
-  @Inject
-  GerritJsonServletProvider(Class<? extends RemoteJsonService> c) {
-    serviceClass = c;
-  }
-
-  @Override
-  public GerritJsonServlet get() {
-    final RemoteJsonService srv = injector.getInstance(serviceClass);
-    return injector
-        .createChildInjector(
-            new AbstractModule() {
-              @Override
-              protected void configure() {
-                bind(RemoteJsonService.class).toInstance(srv);
-              }
-            })
-        .getInstance(GerritJsonServlet.class);
-  }
-}
diff --git a/java/com/google/gerrit/httpd/rpc/Handler.java b/java/com/google/gerrit/httpd/rpc/Handler.java
deleted file mode 100644
index ae20571..0000000
--- a/java/com/google/gerrit/httpd/rpc/Handler.java
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.httpd.rpc;
-
-import com.google.gerrit.common.errors.NoSuchEntityException;
-import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gerrit.server.project.NoSuchProjectException;
-import com.google.gerrit.server.project.NoSuchRefException;
-import com.google.gwtjsonrpc.common.AsyncCallback;
-import com.google.gwtjsonrpc.common.VoidResult;
-import com.google.gwtorm.server.OrmException;
-import java.util.concurrent.Callable;
-
-/**
- * Base class for RPC service implementations.
- *
- * <p>Typically an RPC service implementation will extend this class and use Guice injection to
- * manage its state. For example:
- *
- * <pre>
- *   class Foo extends Handler&lt;Result&gt; {
- *     interface Factory {
- *       Foo create(... args ...);
- *     }
- *     &#064;Inject
- *     Foo(state, @Assisted args) { ... }
- *     Result get() throws Exception { ... }
- *   }
- * </pre>
- *
- * @param <T> type of result for {@link AsyncCallback#onSuccess(Object)} if the operation completed
- *     successfully.
- */
-public abstract class Handler<T> implements Callable<T> {
-  public static <T> Handler<T> wrap(Callable<T> r) {
-    return new Handler<T>() {
-      @Override
-      public T call() throws Exception {
-        return r.call();
-      }
-    };
-  }
-
-  /**
-   * Run the operation and pass the result to the callback.
-   *
-   * @param callback callback to receive the result of {@link #call()}.
-   */
-  public final void to(AsyncCallback<T> callback) {
-    try {
-      final T r = call();
-      if (r != null) {
-        callback.onSuccess(r);
-      }
-    } catch (NoSuchProjectException | NoSuchChangeException | NoSuchRefException e) {
-      callback.onFailure(new NoSuchEntityException());
-
-    } catch (OrmException e) {
-      if (e.getCause() instanceof NoSuchEntityException) {
-        callback.onFailure(e.getCause());
-
-      } else {
-        callback.onFailure(e);
-      }
-    } catch (Exception e) {
-      callback.onFailure(e);
-    }
-  }
-
-  /**
-   * Compute the operation result.
-   *
-   * @return the result of the operation. Return {@link VoidResult#INSTANCE} if there is no
-   *     meaningful return value for the operation.
-   * @throws Exception the operation failed. The caller will log the exception and the stack trace,
-   *     if it is worth logging on the server side.
-   */
-  @Override
-  public abstract T call() throws Exception;
-}
diff --git a/java/com/google/gerrit/httpd/rpc/RpcServletModule.java b/java/com/google/gerrit/httpd/rpc/RpcServletModule.java
deleted file mode 100644
index b03609e..0000000
--- a/java/com/google/gerrit/httpd/rpc/RpcServletModule.java
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.httpd.rpc;
-
-import com.google.gwtjsonrpc.common.RemoteJsonService;
-import com.google.inject.Key;
-import com.google.inject.Scopes;
-import com.google.inject.internal.UniqueAnnotations;
-import com.google.inject.servlet.ServletModule;
-
-/** Binds {@link RemoteJsonService} implementations to a JSON servlet. */
-public abstract class RpcServletModule extends ServletModule {
-  public static final String PREFIX = "/gerrit_ui/rpc/";
-
-  private final String prefix;
-
-  protected RpcServletModule(String pathPrefix) {
-    prefix = pathPrefix;
-  }
-
-  protected void rpc(Class<? extends RemoteJsonService> clazz) {
-    String name = clazz.getSimpleName();
-    if (name.endsWith("Impl")) {
-      name = name.substring(0, name.length() - 4);
-    }
-    rpc(name, clazz);
-  }
-
-  protected void rpc(String name, Class<? extends RemoteJsonService> clazz) {
-    final Key<GerritJsonServlet> srv = Key.get(GerritJsonServlet.class, UniqueAnnotations.create());
-    final GerritJsonServletProvider provider = new GerritJsonServletProvider(clazz);
-    bind(clazz);
-    serve(prefix + name).with(srv);
-    bind(srv).toProvider(provider).in(Scopes.SINGLETON);
-  }
-}
diff --git a/java/com/google/gerrit/httpd/rpc/SystemInfoServiceImpl.java b/java/com/google/gerrit/httpd/rpc/SystemInfoServiceImpl.java
deleted file mode 100644
index 634e8d8..0000000
--- a/java/com/google/gerrit/httpd/rpc/SystemInfoServiceImpl.java
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.httpd.rpc;
-
-import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.common.data.SshHostKey;
-import com.google.gerrit.common.data.SystemInfoService;
-import com.google.gerrit.server.ssh.SshInfo;
-import com.google.gwtjsonrpc.common.AsyncCallback;
-import com.google.gwtjsonrpc.common.VoidResult;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.jcraft.jsch.HostKey;
-import com.jcraft.jsch.JSch;
-import java.util.ArrayList;
-import java.util.List;
-import javax.servlet.http.HttpServletRequest;
-
-class SystemInfoServiceImpl implements SystemInfoService {
-  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
-  private static final JSch JSCH = new JSch();
-
-  private final List<HostKey> hostKeys;
-  private final Provider<HttpServletRequest> httpRequest;
-
-  @Inject
-  SystemInfoServiceImpl(SshInfo daemon, Provider<HttpServletRequest> hsr) {
-    hostKeys = daemon.getHostKeys();
-    httpRequest = hsr;
-  }
-
-  @Override
-  public void daemonHostKeys(AsyncCallback<List<SshHostKey>> callback) {
-    final ArrayList<SshHostKey> r = new ArrayList<>(hostKeys.size());
-    for (HostKey hk : hostKeys) {
-      String host = hk.getHost();
-      if (host.startsWith("*:")) {
-        final String port = host.substring(2);
-        host = "[" + httpRequest.get().getServerName() + "]:" + port;
-      }
-      final String fp = hk.getFingerPrint(JSCH);
-      r.add(new SshHostKey(host, hk.getType() + " " + hk.getKey(), fp));
-    }
-    callback.onSuccess(r);
-  }
-
-  @Override
-  public void clientError(String message, AsyncCallback<VoidResult> callback) {
-    HttpServletRequest r = httpRequest.get();
-    String ua = r.getHeader("User-Agent");
-    message = message.replaceAll("\n", "\n  ");
-    logger.atSevere().log("Client UI JavaScript error: User-Agent=%s: %s", ua, message);
-    callback.onSuccess(VoidResult.INSTANCE);
-  }
-}
diff --git a/java/com/google/gerrit/httpd/rpc/UiRpcModule.java b/java/com/google/gerrit/httpd/rpc/UiRpcModule.java
deleted file mode 100644
index 9aab920..0000000
--- a/java/com/google/gerrit/httpd/rpc/UiRpcModule.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.httpd.rpc;
-
-import com.google.gerrit.httpd.rpc.project.ProjectModule;
-
-/** Registers servlets to answer RPCs from client UI. */
-public class UiRpcModule extends RpcServletModule {
-  public UiRpcModule() {
-    super(PREFIX);
-  }
-
-  @Override
-  protected void configureServlets() {
-    rpc(SystemInfoServiceImpl.class);
-
-    install(new ProjectModule());
-  }
-}
diff --git a/java/com/google/gerrit/httpd/rpc/project/ChangeProjectAccess.java b/java/com/google/gerrit/httpd/rpc/project/ChangeProjectAccess.java
deleted file mode 100644
index 24efb86..0000000
--- a/java/com/google/gerrit/httpd/rpc/project/ChangeProjectAccess.java
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.httpd.rpc.project;
-
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.common.data.AccessSection;
-import com.google.gerrit.common.data.ProjectAccess;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.server.CreateGroupPermissionSyncer;
-import com.google.gerrit.server.CurrentUser;
-import com.google.gerrit.server.account.GroupBackend;
-import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gerrit.server.permissions.PermissionBackend;
-import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gerrit.server.project.ContributorAgreementsChecker;
-import com.google.gerrit.server.project.NoSuchProjectException;
-import com.google.gerrit.server.project.ProjectCache;
-import com.google.gerrit.server.project.ProjectConfig;
-import com.google.gerrit.server.restapi.project.SetParent;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.google.inject.assistedinject.Assisted;
-import java.io.IOException;
-import java.util.List;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.revwalk.RevCommit;
-
-class ChangeProjectAccess extends ProjectAccessHandler<ProjectAccess> {
-  interface Factory {
-    ChangeProjectAccess create(
-        @Assisted("projectName") Project.NameKey projectName,
-        @Nullable @Assisted ObjectId base,
-        @Assisted List<AccessSection> sectionList,
-        @Nullable @Assisted("parentProjectName") Project.NameKey parentProjectName,
-        @Nullable @Assisted String message);
-  }
-
-  private final GitReferenceUpdated gitRefUpdated;
-  private final ProjectAccessFactory.Factory projectAccessFactory;
-  private final ProjectCache projectCache;
-  private final CreateGroupPermissionSyncer createGroupPermissionSyncer;
-
-  @Inject
-  ChangeProjectAccess(
-      ProjectAccessFactory.Factory projectAccessFactory,
-      ProjectCache projectCache,
-      GroupBackend groupBackend,
-      MetaDataUpdate.User metaDataUpdateFactory,
-      AllProjectsName allProjects,
-      Provider<SetParent> setParent,
-      GitReferenceUpdated gitRefUpdated,
-      ContributorAgreementsChecker contributorAgreements,
-      Provider<CurrentUser> user,
-      PermissionBackend permissionBackend,
-      CreateGroupPermissionSyncer createGroupPermissionSyncer,
-      @Assisted("projectName") Project.NameKey projectName,
-      @Nullable @Assisted ObjectId base,
-      @Assisted List<AccessSection> sectionList,
-      @Nullable @Assisted("parentProjectName") Project.NameKey parentProjectName,
-      @Nullable @Assisted String message) {
-    super(
-        groupBackend,
-        metaDataUpdateFactory,
-        allProjects,
-        setParent,
-        user.get(),
-        projectName,
-        base,
-        sectionList,
-        parentProjectName,
-        message,
-        contributorAgreements,
-        permissionBackend,
-        true);
-    this.projectAccessFactory = projectAccessFactory;
-    this.projectCache = projectCache;
-    this.gitRefUpdated = gitRefUpdated;
-    this.createGroupPermissionSyncer = createGroupPermissionSyncer;
-  }
-
-  @Override
-  protected ProjectAccess updateProjectConfig(
-      ProjectConfig config, MetaDataUpdate md, boolean parentProjectUpdate)
-      throws IOException, NoSuchProjectException, ConfigInvalidException,
-          PermissionBackendException, ResourceConflictException {
-    RevCommit commit = config.commit(md);
-
-    gitRefUpdated.fire(
-        config.getProject().getNameKey(),
-        RefNames.REFS_CONFIG,
-        base,
-        commit.getId(),
-        user.asIdentifiedUser().state());
-
-    projectCache.evict(config.getProject());
-    createGroupPermissionSyncer.syncIfNeeded();
-    return projectAccessFactory.create(projectName).call();
-  }
-}
diff --git a/java/com/google/gerrit/httpd/rpc/project/ProjectAccessFactory.java b/java/com/google/gerrit/httpd/rpc/project/ProjectAccessFactory.java
deleted file mode 100644
index 6193e45..0000000
--- a/java/com/google/gerrit/httpd/rpc/project/ProjectAccessFactory.java
+++ /dev/null
@@ -1,295 +0,0 @@
-// Copyright (C) 2011 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.httpd.rpc.project;
-
-import static com.google.gerrit.server.permissions.GlobalPermission.ADMINISTRATE_SERVER;
-import static com.google.gerrit.server.permissions.RefPermission.CREATE_CHANGE;
-import static com.google.gerrit.server.permissions.RefPermission.READ;
-import static com.google.gerrit.server.permissions.RefPermission.WRITE_CONFIG;
-
-import com.google.common.collect.Maps;
-import com.google.gerrit.common.data.AccessSection;
-import com.google.gerrit.common.data.GroupDescription;
-import com.google.gerrit.common.data.GroupInfo;
-import com.google.gerrit.common.data.Permission;
-import com.google.gerrit.common.data.PermissionRule;
-import com.google.gerrit.common.data.ProjectAccess;
-import com.google.gerrit.common.data.RefConfigSection;
-import com.google.gerrit.common.data.WebLinkInfoCommon;
-import com.google.gerrit.common.errors.NoSuchGroupException;
-import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
-import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.server.WebLinks;
-import com.google.gerrit.server.account.GroupBackend;
-import com.google.gerrit.server.account.GroupControl;
-import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gerrit.server.permissions.GlobalPermission;
-import com.google.gerrit.server.permissions.PermissionBackend;
-import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gerrit.server.permissions.ProjectPermission;
-import com.google.gerrit.server.permissions.RefPermission;
-import com.google.gerrit.server.project.NoSuchProjectException;
-import com.google.gerrit.server.project.ProjectCache;
-import com.google.gerrit.server.project.ProjectConfig;
-import com.google.gerrit.server.project.ProjectState;
-import com.google.inject.Inject;
-import com.google.inject.assistedinject.Assisted;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-
-class ProjectAccessFactory extends Handler<ProjectAccess> {
-  interface Factory {
-    ProjectAccessFactory create(@Assisted Project.NameKey name);
-  }
-
-  private final GroupBackend groupBackend;
-  private final ProjectCache projectCache;
-  private final PermissionBackend permissionBackend;
-  private final GroupControl.Factory groupControlFactory;
-  private final MetaDataUpdate.Server metaDataUpdateFactory;
-  private final AllProjectsName allProjectsName;
-
-  private final Project.NameKey projectName;
-  private WebLinks webLinks;
-
-  @Inject
-  ProjectAccessFactory(
-      GroupBackend groupBackend,
-      ProjectCache projectCache,
-      PermissionBackend permissionBackend,
-      GroupControl.Factory groupControlFactory,
-      MetaDataUpdate.Server metaDataUpdateFactory,
-      AllProjectsName allProjectsName,
-      WebLinks webLinks,
-      @Assisted final Project.NameKey name) {
-    this.groupBackend = groupBackend;
-    this.projectCache = projectCache;
-    this.permissionBackend = permissionBackend;
-    this.groupControlFactory = groupControlFactory;
-    this.metaDataUpdateFactory = metaDataUpdateFactory;
-    this.allProjectsName = allProjectsName;
-    this.webLinks = webLinks;
-
-    this.projectName = name;
-  }
-
-  @Override
-  public ProjectAccess call()
-      throws NoSuchProjectException, IOException, ConfigInvalidException,
-          PermissionBackendException, ResourceConflictException {
-    ProjectState projectState = checkProjectState();
-
-    // Load the current configuration from the repository, ensuring its the most
-    // recent version available. If it differs from what was in the project
-    // state, force a cache flush now.
-    //
-    ProjectConfig config;
-    try (MetaDataUpdate md = metaDataUpdateFactory.create(projectName)) {
-      config = ProjectConfig.read(md);
-      if (config.updateGroupNames(groupBackend)) {
-        md.setMessage("Update group names\n");
-        config.commit(md);
-        projectCache.evict(config.getProject());
-        projectState = checkProjectState();
-      } else if (config.getRevision() != null
-          && !config.getRevision().equals(projectState.getConfig().getRevision())) {
-        projectCache.evict(config.getProject());
-        projectState = checkProjectState();
-      }
-    }
-
-    // The following implementation must match the GetAccess REST API endpoint.
-
-    List<AccessSection> local = new ArrayList<>();
-    Set<String> ownerOf = new HashSet<>();
-    Map<AccountGroup.UUID, Boolean> visibleGroups = new HashMap<>();
-    PermissionBackend.ForProject perm = permissionBackend.currentUser().project(projectName);
-    boolean checkReadConfig = check(perm, RefNames.REFS_CONFIG, READ);
-    boolean canWriteProjectConfig = true;
-    try {
-      perm.check(ProjectPermission.WRITE_CONFIG);
-    } catch (AuthException e) {
-      canWriteProjectConfig = false;
-    }
-
-    for (AccessSection section : config.getAccessSections()) {
-      String name = section.getName();
-      if (AccessSection.GLOBAL_CAPABILITIES.equals(name)) {
-        if (canWriteProjectConfig) {
-          local.add(section);
-          ownerOf.add(name);
-
-        } else if (checkReadConfig) {
-          local.add(section);
-        }
-
-      } else if (RefConfigSection.isValid(name)) {
-        if (check(perm, name, WRITE_CONFIG)) {
-          local.add(section);
-          ownerOf.add(name);
-
-        } else if (checkReadConfig) {
-          local.add(section);
-
-        } else if (check(perm, name, READ)) {
-          // Filter the section to only add rules describing groups that
-          // are visible to the current-user. This includes any group the
-          // user is a member of, as well as groups they own or that
-          // are visible to all users.
-
-          AccessSection dst = null;
-          for (Permission srcPerm : section.getPermissions()) {
-            Permission dstPerm = null;
-
-            for (PermissionRule srcRule : srcPerm.getRules()) {
-              AccountGroup.UUID group = srcRule.getGroup().getUUID();
-              if (group == null) {
-                continue;
-              }
-
-              Boolean canSeeGroup = visibleGroups.get(group);
-              if (canSeeGroup == null) {
-                try {
-                  canSeeGroup = groupControlFactory.controlFor(group).isVisible();
-                } catch (NoSuchGroupException e) {
-                  canSeeGroup = Boolean.FALSE;
-                }
-                visibleGroups.put(group, canSeeGroup);
-              }
-
-              if (canSeeGroup) {
-                if (dstPerm == null) {
-                  if (dst == null) {
-                    dst = new AccessSection(name);
-                    local.add(dst);
-                  }
-                  dstPerm = dst.getPermission(srcPerm.getName(), true);
-                }
-                dstPerm.add(srcRule);
-              }
-            }
-          }
-        }
-      }
-    }
-
-    if (ownerOf.isEmpty() && isAdmin()) {
-      // Special case: If the section list is empty, this project has no current
-      // access control information. Fall back to site administrators.
-      ownerOf.add(AccessSection.ALL);
-    }
-
-    final ProjectAccess detail = new ProjectAccess();
-    detail.setProjectName(projectName);
-
-    if (config.getRevision() != null) {
-      detail.setRevision(config.getRevision().name());
-    }
-
-    detail.setInheritsFrom(config.getProject().getParent(allProjectsName));
-
-    if (projectName.equals(allProjectsName)
-        && permissionBackend.currentUser().testOrFalse(ADMINISTRATE_SERVER)) {
-      ownerOf.add(AccessSection.GLOBAL_CAPABILITIES);
-    }
-
-    detail.setLocal(local);
-    detail.setOwnerOf(ownerOf);
-    detail.setCanUpload(
-        canWriteProjectConfig
-            || (checkReadConfig
-                && perm.ref(RefNames.REFS_CONFIG).testOrFalse(CREATE_CHANGE)
-                && projectState.statePermitsWrite()));
-    detail.setConfigVisible(canWriteProjectConfig || checkReadConfig);
-    detail.setGroupInfo(buildGroupInfo(local));
-    detail.setLabelTypes(projectState.getLabelTypes());
-    detail.setFileHistoryLinks(getConfigFileLogLinks(projectName.get()));
-    return detail;
-  }
-
-  private List<WebLinkInfoCommon> getConfigFileLogLinks(String projectName) {
-    List<WebLinkInfoCommon> links =
-        webLinks.getFileHistoryLinks(
-            projectName, RefNames.REFS_CONFIG, ProjectConfig.PROJECT_CONFIG);
-    return links.isEmpty() ? null : links;
-  }
-
-  private Map<AccountGroup.UUID, GroupInfo> buildGroupInfo(List<AccessSection> local) {
-    Map<AccountGroup.UUID, GroupInfo> infos = new HashMap<>();
-    for (AccessSection section : local) {
-      for (Permission permission : section.getPermissions()) {
-        for (PermissionRule rule : permission.getRules()) {
-          if (rule.getGroup() != null) {
-            AccountGroup.UUID uuid = rule.getGroup().getUUID();
-            if (uuid != null && !infos.containsKey(uuid)) {
-              GroupDescription.Basic group = groupBackend.get(uuid);
-              infos.put(uuid, group != null ? new GroupInfo(group) : null);
-            }
-          }
-        }
-      }
-    }
-    return Maps.filterEntries(infos, in -> in.getValue() != null);
-  }
-
-  private ProjectState checkProjectState()
-      throws NoSuchProjectException, IOException, PermissionBackendException,
-          ResourceConflictException {
-    ProjectState state = projectCache.checkedGet(projectName);
-    // Hidden projects(permitsRead = false) should only be accessible by the project owners.
-    // READ_CONFIG is checked here because it's only allowed to project owners(ACCESS may also
-    // be allowed for other users). Allowing project owners to access here will help them to view
-    // and update the config of hidden projects easily.
-    ProjectPermission permissionToCheck =
-        state.statePermitsRead() ? ProjectPermission.ACCESS : ProjectPermission.READ_CONFIG;
-    try {
-      permissionBackend.currentUser().project(projectName).check(permissionToCheck);
-    } catch (AuthException e) {
-      throw new NoSuchProjectException(projectName);
-    }
-    state.checkStatePermitsRead();
-    return state;
-  }
-
-  private static boolean check(PermissionBackend.ForProject ctx, String ref, RefPermission perm)
-      throws PermissionBackendException {
-    try {
-      ctx.ref(ref).check(perm);
-      return true;
-    } catch (AuthException denied) {
-      return false;
-    }
-  }
-
-  private boolean isAdmin() throws PermissionBackendException {
-    try {
-      permissionBackend.currentUser().check(GlobalPermission.ADMINISTRATE_SERVER);
-      return true;
-    } catch (AuthException e) {
-      return false;
-    }
-  }
-}
diff --git a/java/com/google/gerrit/httpd/rpc/project/ProjectAccessHandler.java b/java/com/google/gerrit/httpd/rpc/project/ProjectAccessHandler.java
deleted file mode 100644
index 44c8966..0000000
--- a/java/com/google/gerrit/httpd/rpc/project/ProjectAccessHandler.java
+++ /dev/null
@@ -1,251 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.httpd.rpc.project;
-
-import static com.google.gerrit.common.ProjectAccessUtil.mergeSections;
-import static java.util.Objects.requireNonNull;
-
-import com.google.common.base.MoreObjects;
-import com.google.gerrit.common.data.AccessSection;
-import com.google.gerrit.common.data.GroupReference;
-import com.google.gerrit.common.data.Permission;
-import com.google.gerrit.common.data.PermissionRule;
-import com.google.gerrit.common.errors.InvalidNameException;
-import com.google.gerrit.common.errors.NoSuchGroupException;
-import com.google.gerrit.common.errors.UpdateParentFailedException;
-import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.extensions.restapi.BadRequestException;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
-import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
-import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.server.CurrentUser;
-import com.google.gerrit.server.account.GroupBackend;
-import com.google.gerrit.server.account.GroupBackends;
-import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gerrit.server.permissions.PermissionBackend;
-import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gerrit.server.permissions.ProjectPermission;
-import com.google.gerrit.server.permissions.RefPermission;
-import com.google.gerrit.server.project.ContributorAgreementsChecker;
-import com.google.gerrit.server.project.NoSuchProjectException;
-import com.google.gerrit.server.project.ProjectConfig;
-import com.google.gerrit.server.project.RefPattern;
-import com.google.gerrit.server.restapi.project.SetParent;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.errors.RepositoryNotFoundException;
-import org.eclipse.jgit.lib.ObjectId;
-
-public abstract class ProjectAccessHandler<T> extends Handler<T> {
-
-  protected final GroupBackend groupBackend;
-  protected final Project.NameKey projectName;
-  protected final ObjectId base;
-  protected final CurrentUser user;
-
-  private final MetaDataUpdate.User metaDataUpdateFactory;
-  private final AllProjectsName allProjects;
-  private final Provider<SetParent> setParent;
-  private final ContributorAgreementsChecker contributorAgreements;
-  private final PermissionBackend permissionBackend;
-  private final Project.NameKey parentProjectName;
-
-  protected String message;
-
-  private List<AccessSection> sectionList;
-  private boolean checkIfOwner;
-  private Boolean canWriteConfig;
-
-  protected ProjectAccessHandler(
-      GroupBackend groupBackend,
-      MetaDataUpdate.User metaDataUpdateFactory,
-      AllProjectsName allProjects,
-      Provider<SetParent> setParent,
-      CurrentUser user,
-      Project.NameKey projectName,
-      ObjectId base,
-      List<AccessSection> sectionList,
-      Project.NameKey parentProjectName,
-      String message,
-      ContributorAgreementsChecker contributorAgreements,
-      PermissionBackend permissionBackend,
-      boolean checkIfOwner) {
-    this.groupBackend = groupBackend;
-    this.metaDataUpdateFactory = metaDataUpdateFactory;
-    this.allProjects = allProjects;
-    this.setParent = setParent;
-    this.user = user;
-
-    this.projectName = projectName;
-    this.base = base;
-    this.sectionList = sectionList;
-    this.parentProjectName = parentProjectName;
-    this.message = message;
-    this.contributorAgreements = contributorAgreements;
-    this.permissionBackend = permissionBackend;
-    this.checkIfOwner = checkIfOwner;
-  }
-
-  @Override
-  public final T call()
-      throws NoSuchProjectException, IOException, ConfigInvalidException, InvalidNameException,
-          NoSuchGroupException, OrmException, UpdateParentFailedException, AuthException,
-          PermissionBackendException, ResourceConflictException {
-    contributorAgreements.check(projectName, user);
-
-    try (MetaDataUpdate md = metaDataUpdateFactory.create(projectName)) {
-      ProjectConfig config = ProjectConfig.read(md, base);
-      Set<String> toDelete = scanSectionNames(config);
-      PermissionBackend.ForProject forProject = permissionBackend.user(user).project(projectName);
-
-      for (AccessSection section : mergeSections(sectionList)) {
-        String name = section.getName();
-
-        if (AccessSection.GLOBAL_CAPABILITIES.equals(name)) {
-          if (checkIfOwner && !canWriteConfig()) {
-            continue;
-          }
-          replace(config, toDelete, section);
-
-        } else if (AccessSection.isValid(name)) {
-          if (checkIfOwner) {
-            try {
-              forProject.ref(name).check(RefPermission.WRITE_CONFIG);
-            } catch (AuthException e) {
-              continue;
-            }
-          }
-
-          RefPattern.validate(name);
-
-          replace(config, toDelete, section);
-        }
-      }
-
-      for (String name : toDelete) {
-        if (AccessSection.GLOBAL_CAPABILITIES.equals(name)) {
-          if (!checkIfOwner || canWriteConfig()) {
-            config.remove(config.getAccessSection(name));
-          }
-
-        } else if (!checkIfOwner) {
-          config.remove(config.getAccessSection(name));
-        } else {
-          try {
-            forProject.ref(name).check(RefPermission.WRITE_CONFIG);
-            config.remove(config.getAccessSection(name));
-          } catch (AuthException e) {
-            // Do nothing.
-          }
-        }
-      }
-
-      boolean parentProjectUpdate = false;
-      if (!config.getProject().getNameKey().equals(allProjects)
-          && !config.getProject().getParent(allProjects).equals(parentProjectName)) {
-        parentProjectUpdate = true;
-        try {
-          setParent
-              .get()
-              .validateParentUpdate(
-                  projectName,
-                  user.asIdentifiedUser(),
-                  MoreObjects.firstNonNull(parentProjectName, allProjects).get(),
-                  checkIfOwner);
-        } catch (AuthException e) {
-          throw new UpdateParentFailedException(
-              "You are not allowed to change the parent project since you are "
-                  + "not an administrator. You may save the modifications for review "
-                  + "so that an administrator can approve them.",
-              e);
-        } catch (ResourceConflictException | UnprocessableEntityException | BadRequestException e) {
-          throw new UpdateParentFailedException(e.getMessage(), e);
-        }
-        config.getProject().setParentName(parentProjectName);
-      }
-
-      if (message != null && !message.isEmpty()) {
-        if (!message.endsWith("\n")) {
-          message += "\n";
-        }
-        md.setMessage(message);
-      } else {
-        md.setMessage("Modify access rules\n");
-      }
-
-      return updateProjectConfig(config, md, parentProjectUpdate);
-    } catch (RepositoryNotFoundException notFound) {
-      throw new NoSuchProjectException(projectName);
-    }
-  }
-
-  protected abstract T updateProjectConfig(
-      ProjectConfig config, MetaDataUpdate md, boolean parentProjectUpdate)
-      throws IOException, NoSuchProjectException, ConfigInvalidException, OrmException,
-          AuthException, PermissionBackendException, ResourceConflictException;
-
-  private void replace(ProjectConfig config, Set<String> toDelete, AccessSection section)
-      throws NoSuchGroupException {
-    for (Permission permission : section.getPermissions()) {
-      for (PermissionRule rule : permission.getRules()) {
-        lookupGroup(rule);
-      }
-    }
-    config.replace(section);
-    toDelete.remove(section.getName());
-  }
-
-  private static Set<String> scanSectionNames(ProjectConfig config) {
-    Set<String> names = new HashSet<>();
-    for (AccessSection section : config.getAccessSections()) {
-      names.add(section.getName());
-    }
-    return names;
-  }
-
-  private void lookupGroup(PermissionRule rule) throws NoSuchGroupException {
-    GroupReference ref = rule.getGroup();
-    if (ref.getUUID() == null) {
-      final GroupReference group = GroupBackends.findBestSuggestion(groupBackend, ref.getName());
-      if (group == null) {
-        throw new NoSuchGroupException(ref.getName());
-      }
-      ref.setUUID(group.getUUID());
-    }
-  }
-
-  /** Provide a local cache for {@code ProjectPermission.WRITE_CONFIG} capability. */
-  private boolean canWriteConfig() throws PermissionBackendException {
-    requireNonNull(user);
-
-    if (canWriteConfig != null) {
-      return canWriteConfig;
-    }
-    try {
-      permissionBackend.user(user).project(projectName).check(ProjectPermission.WRITE_CONFIG);
-      canWriteConfig = true;
-    } catch (AuthException e) {
-      canWriteConfig = false;
-    }
-    return canWriteConfig;
-  }
-}
diff --git a/java/com/google/gerrit/httpd/rpc/project/ProjectAdminServiceImpl.java b/java/com/google/gerrit/httpd/rpc/project/ProjectAdminServiceImpl.java
deleted file mode 100644
index da471c3..0000000
--- a/java/com/google/gerrit/httpd/rpc/project/ProjectAdminServiceImpl.java
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.httpd.rpc.project;
-
-import com.google.gerrit.common.data.AccessSection;
-import com.google.gerrit.common.data.ProjectAccess;
-import com.google.gerrit.common.data.ProjectAdminService;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwtjsonrpc.common.AsyncCallback;
-import com.google.inject.Inject;
-import java.util.List;
-import org.eclipse.jgit.lib.ObjectId;
-
-class ProjectAdminServiceImpl implements ProjectAdminService {
-  private final ChangeProjectAccess.Factory changeProjectAccessFactory;
-  private final ReviewProjectAccess.Factory reviewProjectAccessFactory;
-  private final ProjectAccessFactory.Factory projectAccessFactory;
-
-  @Inject
-  ProjectAdminServiceImpl(
-      final ChangeProjectAccess.Factory changeProjectAccessFactory,
-      final ReviewProjectAccess.Factory reviewProjectAccessFactory,
-      final ProjectAccessFactory.Factory projectAccessFactory) {
-    this.changeProjectAccessFactory = changeProjectAccessFactory;
-    this.reviewProjectAccessFactory = reviewProjectAccessFactory;
-    this.projectAccessFactory = projectAccessFactory;
-  }
-
-  @Override
-  public void projectAccess(
-      final Project.NameKey projectName, AsyncCallback<ProjectAccess> callback) {
-    projectAccessFactory.create(projectName).to(callback);
-  }
-
-  private static ObjectId getBase(String baseRevision) {
-    if (baseRevision != null && !baseRevision.isEmpty()) {
-      return ObjectId.fromString(baseRevision);
-    }
-    return null;
-  }
-
-  @Override
-  public void changeProjectAccess(
-      Project.NameKey projectName,
-      String baseRevision,
-      String msg,
-      List<AccessSection> sections,
-      Project.NameKey parentProjectName,
-      AsyncCallback<ProjectAccess> cb) {
-    changeProjectAccessFactory
-        .create(projectName, getBase(baseRevision), sections, parentProjectName, msg)
-        .to(cb);
-  }
-
-  @Override
-  public void reviewProjectAccess(
-      Project.NameKey projectName,
-      String baseRevision,
-      String msg,
-      List<AccessSection> sections,
-      Project.NameKey parentProjectName,
-      AsyncCallback<Change.Id> cb) {
-    reviewProjectAccessFactory
-        .create(projectName, getBase(baseRevision), sections, parentProjectName, msg)
-        .to(cb);
-  }
-}
diff --git a/java/com/google/gerrit/httpd/rpc/project/ProjectModule.java b/java/com/google/gerrit/httpd/rpc/project/ProjectModule.java
deleted file mode 100644
index 3d7d80f..0000000
--- a/java/com/google/gerrit/httpd/rpc/project/ProjectModule.java
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.httpd.rpc.project;
-
-import com.google.gerrit.extensions.config.FactoryModule;
-import com.google.gerrit.httpd.rpc.RpcServletModule;
-import com.google.gerrit.httpd.rpc.UiRpcModule;
-
-public class ProjectModule extends RpcServletModule {
-  public ProjectModule() {
-    super(UiRpcModule.PREFIX);
-  }
-
-  @Override
-  protected void configureServlets() {
-    install(
-        new FactoryModule() {
-          @Override
-          protected void configure() {
-            factory(ChangeProjectAccess.Factory.class);
-            factory(ReviewProjectAccess.Factory.class);
-            factory(ProjectAccessFactory.Factory.class);
-          }
-        });
-    rpc(ProjectAdminServiceImpl.class);
-  }
-}
diff --git a/java/com/google/gerrit/httpd/rpc/project/ReviewProjectAccess.java b/java/com/google/gerrit/httpd/rpc/project/ReviewProjectAccess.java
deleted file mode 100644
index 6a43a1d..0000000
--- a/java/com/google/gerrit/httpd/rpc/project/ReviewProjectAccess.java
+++ /dev/null
@@ -1,245 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.httpd.rpc.project;
-
-import com.google.common.base.Throwables;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.common.data.AccessSection;
-import com.google.gerrit.common.data.GlobalCapability;
-import com.google.gerrit.common.data.PermissionRule;
-import com.google.gerrit.extensions.api.changes.AddReviewerInput;
-import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
-import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.CurrentUser;
-import com.google.gerrit.server.Sequences;
-import com.google.gerrit.server.account.GroupBackend;
-import com.google.gerrit.server.change.ChangeInserter;
-import com.google.gerrit.server.change.ChangeResource;
-import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gerrit.server.group.SystemGroupBackend;
-import com.google.gerrit.server.permissions.PermissionBackend;
-import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gerrit.server.permissions.ProjectPermission;
-import com.google.gerrit.server.permissions.RefPermission;
-import com.google.gerrit.server.project.ContributorAgreementsChecker;
-import com.google.gerrit.server.project.ProjectCache;
-import com.google.gerrit.server.project.ProjectConfig;
-import com.google.gerrit.server.restapi.change.ChangesCollection;
-import com.google.gerrit.server.restapi.change.PostReviewers;
-import com.google.gerrit.server.restapi.project.SetParent;
-import com.google.gerrit.server.update.BatchUpdate;
-import com.google.gerrit.server.update.UpdateException;
-import com.google.gerrit.server.util.time.TimeUtil;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.google.inject.assistedinject.Assisted;
-import java.io.IOException;
-import java.util.List;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.ObjectInserter;
-import org.eclipse.jgit.lib.ObjectReader;
-import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.revwalk.RevWalk;
-
-public class ReviewProjectAccess extends ProjectAccessHandler<Change.Id> {
-  interface Factory {
-    ReviewProjectAccess create(
-        @Assisted("projectName") Project.NameKey projectName,
-        @Nullable @Assisted ObjectId base,
-        @Assisted List<AccessSection> sectionList,
-        @Nullable @Assisted("parentProjectName") Project.NameKey parentProjectName,
-        @Nullable @Assisted String message);
-  }
-
-  private final ReviewDb db;
-  private final PermissionBackend permissionBackend;
-  private final Sequences seq;
-  private final Provider<PostReviewers> reviewersProvider;
-  private final ProjectCache projectCache;
-  private final ChangesCollection changes;
-  private final ChangeInserter.Factory changeInserterFactory;
-  private final BatchUpdate.Factory updateFactory;
-  private final boolean allowProjectOwnersToChangeParent;
-
-  @Inject
-  ReviewProjectAccess(
-      PermissionBackend permissionBackend,
-      GroupBackend groupBackend,
-      MetaDataUpdate.User metaDataUpdateFactory,
-      ReviewDb db,
-      Provider<PostReviewers> reviewersProvider,
-      ProjectCache projectCache,
-      AllProjectsName allProjects,
-      ChangesCollection changes,
-      ChangeInserter.Factory changeInserterFactory,
-      BatchUpdate.Factory updateFactory,
-      Provider<SetParent> setParent,
-      Sequences seq,
-      ContributorAgreementsChecker contributorAgreements,
-      Provider<CurrentUser> user,
-      @GerritServerConfig Config config,
-      @Assisted("projectName") Project.NameKey projectName,
-      @Nullable @Assisted ObjectId base,
-      @Assisted List<AccessSection> sectionList,
-      @Nullable @Assisted("parentProjectName") Project.NameKey parentProjectName,
-      @Nullable @Assisted String message) {
-    super(
-        groupBackend,
-        metaDataUpdateFactory,
-        allProjects,
-        setParent,
-        user.get(),
-        projectName,
-        base,
-        sectionList,
-        parentProjectName,
-        message,
-        contributorAgreements,
-        permissionBackend,
-        false);
-    this.db = db;
-    this.permissionBackend = permissionBackend;
-    this.seq = seq;
-    this.reviewersProvider = reviewersProvider;
-    this.projectCache = projectCache;
-    this.changes = changes;
-    this.changeInserterFactory = changeInserterFactory;
-    this.updateFactory = updateFactory;
-    this.allowProjectOwnersToChangeParent =
-        config.getBoolean("receive", "allowProjectOwnersToChangeParent", false);
-  }
-
-  // TODO(dborowitz): Hack MetaDataUpdate so it can be created within a BatchUpdate and we can avoid
-  // calling setUpdateRef(false).
-  @SuppressWarnings("deprecation")
-  @Override
-  protected Change.Id updateProjectConfig(
-      ProjectConfig config, MetaDataUpdate md, boolean parentProjectUpdate)
-      throws IOException, OrmException, AuthException, PermissionBackendException,
-          ConfigInvalidException, ResourceConflictException {
-    PermissionBackend.ForProject perm = permissionBackend.user(user).project(config.getName());
-    if (!check(perm, ProjectPermission.READ_CONFIG)) {
-      throw new AuthException(RefNames.REFS_CONFIG + " not visible");
-    }
-
-    if (!check(perm, ProjectPermission.WRITE_CONFIG)
-        && !check(perm.ref(RefNames.REFS_CONFIG), RefPermission.CREATE_CHANGE)) {
-      throw new AuthException("cannot create change for " + RefNames.REFS_CONFIG);
-    }
-
-    projectCache.checkedGet(config.getName()).checkStatePermitsWrite();
-
-    md.setInsertChangeId(true);
-    Change.Id changeId = new Change.Id(seq.nextChangeId());
-    RevCommit commit =
-        config.commitToNewRef(
-            md, new PatchSet.Id(changeId, Change.INITIAL_PATCH_SET_ID).toRefName());
-    if (commit.getId().equals(base)) {
-      return null;
-    }
-
-    try (ObjectInserter objInserter = md.getRepository().newObjectInserter();
-        ObjectReader objReader = objInserter.newReader();
-        RevWalk rw = new RevWalk(objReader);
-        BatchUpdate bu =
-            updateFactory.create(db, config.getProject().getNameKey(), user, TimeUtil.nowTs())) {
-      bu.setRepository(md.getRepository(), rw, objInserter);
-      bu.insertChange(
-          changeInserterFactory
-              .create(changeId, commit, RefNames.REFS_CONFIG)
-              .setValidate(false)
-              .setUpdateRef(false)); // Created by commitToNewRef.
-      bu.execute();
-    } catch (UpdateException | RestApiException e) {
-      throw new IOException(e);
-    }
-
-    ChangeResource rsrc;
-    try {
-      rsrc = changes.parse(changeId);
-    } catch (RestApiException e) {
-      throw new IOException(e);
-    }
-    addProjectOwnersAsReviewers(rsrc);
-    if (parentProjectUpdate && !allowProjectOwnersToChangeParent) {
-      addAdministratorsAsReviewers(rsrc);
-    }
-    return changeId;
-  }
-
-  private void addProjectOwnersAsReviewers(ChangeResource rsrc) {
-    final String projectOwners = groupBackend.get(SystemGroupBackend.PROJECT_OWNERS).getName();
-    try {
-      AddReviewerInput input = new AddReviewerInput();
-      input.reviewer = projectOwners;
-      reviewersProvider.get().apply(rsrc, input);
-    } catch (Exception e) {
-      // one of the owner groups is not visible to the user and this it why it
-      // can't be added as reviewer
-      Throwables.throwIfUnchecked(e);
-    }
-  }
-
-  private void addAdministratorsAsReviewers(ChangeResource rsrc) {
-    List<PermissionRule> adminRules =
-        projectCache
-            .getAllProjects()
-            .getConfig()
-            .getAccessSection(AccessSection.GLOBAL_CAPABILITIES)
-            .getPermission(GlobalCapability.ADMINISTRATE_SERVER)
-            .getRules();
-    for (PermissionRule r : adminRules) {
-      try {
-        AddReviewerInput input = new AddReviewerInput();
-        input.reviewer = r.getGroup().getUUID().get();
-        reviewersProvider.get().apply(rsrc, input);
-      } catch (Exception e) {
-        // ignore
-        Throwables.throwIfUnchecked(e);
-      }
-    }
-  }
-
-  private boolean check(PermissionBackend.ForRef perm, RefPermission p)
-      throws PermissionBackendException {
-    try {
-      perm.check(p);
-      return true;
-    } catch (AuthException denied) {
-      return false;
-    }
-  }
-
-  private boolean check(PermissionBackend.ForProject perm, ProjectPermission p)
-      throws PermissionBackendException {
-    try {
-      perm.check(p);
-      return true;
-    } catch (AuthException denied) {
-      return false;
-    }
-  }
-}
diff --git a/java/com/google/gerrit/launcher/BUILD b/java/com/google/gerrit/launcher/BUILD
index 18dcd52..918a83f 100644
--- a/java/com/google/gerrit/launcher/BUILD
+++ b/java/com/google/gerrit/launcher/BUILD
@@ -8,7 +8,7 @@
 )
 
 # The root of the workspace is non-hermetic, but we need it for
-# on-the-fly GWT recompiles and PolyGerrit updates.
+# on-the-flyPolyGerrit updates.
 genrule(
     name = "gen_root",
     outs = ["workspace-root.txt"],
diff --git a/java/com/google/gerrit/lucene/LuceneChangeIndex.java b/java/com/google/gerrit/lucene/LuceneChangeIndex.java
index 66db468..b208a31 100644
--- a/java/com/google/gerrit/lucene/LuceneChangeIndex.java
+++ b/java/com/google/gerrit/lucene/LuceneChangeIndex.java
@@ -76,6 +76,7 @@
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
+import java.util.function.Consumer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexableField;
@@ -129,6 +130,7 @@
       ChangeField.STORED_SUBMIT_RECORD_LENIENT.getName();
   private static final String SUBMIT_RECORD_STRICT_FIELD =
       ChangeField.STORED_SUBMIT_RECORD_STRICT.getName();
+  private static final String TOTAL_COMMENT_COUNT_FIELD = ChangeField.TOTAL_COMMENT_COUNT.getName();
   private static final String UNRESOLVED_COMMENT_COUNT_FIELD =
       ChangeField.UNRESOLVED_COMMENT_COUNT.getName();
 
@@ -504,6 +506,7 @@
     }
 
     decodeUnresolvedCommentCount(doc, cd);
+    decodeTotalCommentCount(doc, cd);
     return cd;
   }
 
@@ -633,9 +636,18 @@
 
   private void decodeUnresolvedCommentCount(
       ListMultimap<String, IndexableField> doc, ChangeData cd) {
-    IndexableField f = Iterables.getFirst(doc.get(UNRESOLVED_COMMENT_COUNT_FIELD), null);
+    decodeIntField(doc, UNRESOLVED_COMMENT_COUNT_FIELD, cd::setUnresolvedCommentCount);
+  }
+
+  private void decodeTotalCommentCount(ListMultimap<String, IndexableField> doc, ChangeData cd) {
+    decodeIntField(doc, TOTAL_COMMENT_COUNT_FIELD, cd::setTotalCommentCount);
+  }
+
+  private static void decodeIntField(
+      ListMultimap<String, IndexableField> doc, String fieldName, Consumer<Integer> consumer) {
+    IndexableField f = Iterables.getFirst(doc.get(fieldName), null);
     if (f != null && f.numericValue() != null) {
-      cd.setUnresolvedCommentCount(f.numericValue().intValue());
+      consumer.accept(f.numericValue().intValue());
     }
   }
 
diff --git a/java/com/google/gerrit/pgm/Daemon.java b/java/com/google/gerrit/pgm/Daemon.java
index a777a1c..9a24867 100644
--- a/java/com/google/gerrit/pgm/Daemon.java
+++ b/java/com/google/gerrit/pgm/Daemon.java
@@ -97,7 +97,7 @@
 import com.google.gerrit.server.schema.DataSourceProvider;
 import com.google.gerrit.server.schema.InMemoryAccountPatchReviewStore;
 import com.google.gerrit.server.schema.JdbcAccountPatchReviewStore;
-import com.google.gerrit.server.schema.SchemaVersionCheck;
+import com.google.gerrit.server.schema.ReviewDbSchemaVersionCheck;
 import com.google.gerrit.server.securestore.DefaultSecureStore;
 import com.google.gerrit.server.securestore.SecureStore;
 import com.google.gerrit.server.securestore.SecureStoreClassName;
@@ -290,7 +290,7 @@
         JythonShell shell = new JythonShell();
         shell.set("m", manager);
         shell.set("ds", dbInjector.getInstance(DataSourceProvider.class));
-        shell.set("schk", dbInjector.getInstance(SchemaVersionCheck.class));
+        shell.set("schk", dbInjector.getInstance(ReviewDbSchemaVersionCheck.class));
         shell.set("d", this);
         shell.run();
       } else {
@@ -397,7 +397,7 @@
 
   private Injector createSysInjector() {
     final List<Module> modules = new ArrayList<>();
-    modules.add(SchemaVersionCheck.module());
+    modules.add(ReviewDbSchemaVersionCheck.module());
     modules.add(new DropWizardMetricMaker.RestModule());
     modules.add(new LogFileCompressor.Module());
 
@@ -480,8 +480,7 @@
         new AbstractModule() {
           @Override
           protected void configure() {
-            bind(GerritOptions.class)
-                .toInstance(new GerritOptions(config, headless, slave, polyGerritDev));
+            bind(GerritOptions.class).toInstance(new GerritOptions(headless, slave, polyGerritDev));
             if (inMemoryTest) {
               bind(String.class)
                   .annotatedWith(SecureStoreClassName.class)
diff --git a/java/com/google/gerrit/pgm/LocalUsernamesToLowerCase.java b/java/com/google/gerrit/pgm/LocalUsernamesToLowerCase.java
index 5bfc00f..6ebd6a3 100644
--- a/java/com/google/gerrit/pgm/LocalUsernamesToLowerCase.java
+++ b/java/com/google/gerrit/pgm/LocalUsernamesToLowerCase.java
@@ -29,7 +29,7 @@
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.meta.MetaDataUpdate;
 import com.google.gerrit.server.index.account.AccountSchemaDefinitions;
-import com.google.gerrit.server.schema.SchemaVersionCheck;
+import com.google.gerrit.server.schema.ReviewDbSchemaVersionCheck;
 import com.google.gwtorm.server.OrmDuplicateKeyException;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
@@ -55,7 +55,7 @@
   @Override
   public int run() throws Exception {
     Injector dbInjector = createDbInjector(MULTI_USER);
-    manager.add(dbInjector, dbInjector.createChildInjector(SchemaVersionCheck.module()));
+    manager.add(dbInjector, dbInjector.createChildInjector(ReviewDbSchemaVersionCheck.module()));
     manager.start();
     dbInjector
         .createChildInjector(
diff --git a/java/com/google/gerrit/pgm/http/jetty/HttpLog.java b/java/com/google/gerrit/pgm/http/jetty/HttpLog.java
index b7ec2be..dab9d7e 100644
--- a/java/com/google/gerrit/pgm/http/jetty/HttpLog.java
+++ b/java/com/google/gerrit/pgm/http/jetty/HttpLog.java
@@ -45,6 +45,7 @@
   protected static final String P_PROTOCOL = "Version";
   protected static final String P_STATUS = "Status";
   protected static final String P_CONTENT_LENGTH = "Content-Length";
+  protected static final String P_LATENCY = "Latency";
   protected static final String P_REFERER = "Referer";
   protected static final String P_USER_AGENT = "User-Agent";
 
@@ -94,6 +95,7 @@
     set(event, P_PROTOCOL, req.getProtocol());
     set(event, P_STATUS, rsp.getStatus());
     set(event, P_CONTENT_LENGTH, rsp.getContentCount());
+    set(event, P_LATENCY, System.currentTimeMillis() - req.getTimeStamp());
     set(event, P_REFERER, req.getHeader("Referer"));
     set(event, P_USER_AGENT, req.getHeader("User-Agent"));
 
diff --git a/java/com/google/gerrit/pgm/http/jetty/HttpLogLayout.java b/java/com/google/gerrit/pgm/http/jetty/HttpLogLayout.java
index 2eea88d..bd7d998 100644
--- a/java/com/google/gerrit/pgm/http/jetty/HttpLogLayout.java
+++ b/java/com/google/gerrit/pgm/http/jetty/HttpLogLayout.java
@@ -67,6 +67,9 @@
     opt(buf, event, HttpLog.P_CONTENT_LENGTH);
 
     buf.append(' ');
+    opt(buf, event, HttpLog.P_LATENCY);
+
+    buf.append(' ');
     dq_opt(buf, event, HttpLog.P_REFERER);
 
     buf.append(' ');
diff --git a/java/com/google/gerrit/pgm/init/BaseInit.java b/java/com/google/gerrit/pgm/init/BaseInit.java
index deaf139..71957e1 100644
--- a/java/com/google/gerrit/pgm/init/BaseInit.java
+++ b/java/com/google/gerrit/pgm/init/BaseInit.java
@@ -43,7 +43,7 @@
 import com.google.gerrit.server.index.IndexModule;
 import com.google.gerrit.server.plugins.JarScanner;
 import com.google.gerrit.server.schema.ReviewDbFactory;
-import com.google.gerrit.server.schema.SchemaUpdater;
+import com.google.gerrit.server.schema.ReviewDbSchemaUpdater;
 import com.google.gerrit.server.schema.UpdateUI;
 import com.google.gerrit.server.securestore.SecureStore;
 import com.google.gerrit.server.securestore.SecureStoreClassName;
@@ -358,7 +358,7 @@
     public final ConsoleUI ui;
     public final SitePaths site;
     public final InitFlags flags;
-    final SchemaUpdater schemaUpdater;
+    final ReviewDbSchemaUpdater schemaUpdater;
     final SchemaFactory<ReviewDb> schema;
     final GitRepositoryManager repositoryManager;
 
@@ -367,7 +367,7 @@
         ConsoleUI ui,
         SitePaths site,
         InitFlags flags,
-        SchemaUpdater schemaUpdater,
+        ReviewDbSchemaUpdater schemaUpdater,
         @ReviewDbFactory SchemaFactory<ReviewDb> schema,
         GitRepositoryManager repositoryManager) {
       this.ui = ui;
diff --git a/java/com/google/gerrit/pgm/util/SiteProgram.java b/java/com/google/gerrit/pgm/util/SiteProgram.java
index 1338efb..65feeab 100644
--- a/java/com/google/gerrit/pgm/util/SiteProgram.java
+++ b/java/com/google/gerrit/pgm/util/SiteProgram.java
@@ -34,7 +34,7 @@
 import com.google.gerrit.server.schema.DataSourceProvider;
 import com.google.gerrit.server.schema.DataSourceType;
 import com.google.gerrit.server.schema.DatabaseModule;
-import com.google.gerrit.server.schema.SchemaModule;
+import com.google.gerrit.server.schema.ReviewDbSchemaModule;
 import com.google.gerrit.server.securestore.SecureStoreClassName;
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.AbstractModule;
@@ -188,7 +188,7 @@
           }
         });
     modules.add(new DatabaseModule());
-    modules.add(new SchemaModule());
+    modules.add(new ReviewDbSchemaModule());
     modules.add(cfgInjector.getInstance(GitRepositoryManagerModule.class));
     modules.add(new NotesMigration.Module());
 
diff --git a/java/com/google/gerrit/prettify/BUILD b/java/com/google/gerrit/prettify/BUILD
index 366a1a0..33e5425 100644
--- a/java/com/google/gerrit/prettify/BUILD
+++ b/java/com/google/gerrit/prettify/BUILD
@@ -1,22 +1,3 @@
-load("//tools/bzl:gwt.bzl", "gwt_module")
-
-gwt_module(
-    name = "client",
-    srcs = glob(["common/**/*.java"]),
-    exported_deps = [
-        "//java/com/google/gerrit/extensions:client",
-        "//java/com/google/gerrit/reviewdb:client",
-        "//java/com/google/gwtexpui/safehtml",
-        "//java/org/eclipse/jgit:Edit",
-        "//java/org/eclipse/jgit:client",
-        "//lib:gwtjsonrpc",
-        "//lib:gwtjsonrpc_src",
-    ],
-    gwt_xml = "PrettyFormatter.gwt.xml",
-    visibility = ["//visibility:public"],
-    deps = ["//lib/gwt:user-neverlink"],
-)
-
 java_library(
     name = "server",
     srcs = glob(["common/**/*.java"]),
diff --git a/java/com/google/gerrit/prettify/PrettyFormatter.gwt.xml b/java/com/google/gerrit/prettify/PrettyFormatter.gwt.xml
deleted file mode 100644
index 06035d27..0000000
--- a/java/com/google/gerrit/prettify/PrettyFormatter.gwt.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the 'License');
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an 'AS IS' BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<module>
-  <replace-with class='com.google.gerrit.prettify.client.PrivateScopeImplIE8'>
-    <when-type-is class='com.google.gerrit.prettify.client.PrivateScopeImpl'/>
-    <any>
-      <when-property-is name="user.agent" value="ie8" />
-    </any>
-  </replace-with>
-
-  <inherits name='com.google.gwt.resources.Resources'/>
-  <inherits name='com.google.gwtexpui.safehtml.SafeHtml'/>
-  <source path='common' />
-</module>
diff --git a/java/com/google/gerrit/reviewdb/BUILD b/java/com/google/gerrit/reviewdb/BUILD
index 40f39c0..a4c6601 100644
--- a/java/com/google/gerrit/reviewdb/BUILD
+++ b/java/com/google/gerrit/reviewdb/BUILD
@@ -2,19 +2,6 @@
     default_visibility = ["//visibility:public"],
 )
 
-load("//tools/bzl:gwt.bzl", "gwt_module")
-
-gwt_module(
-    name = "client",
-    srcs = glob(["client/**/*.java"]),
-    gwt_xml = "ReviewDB.gwt.xml",
-    deps = [
-        "//java/com/google/gerrit/extensions:client",
-        "//lib:gwtorm-client",
-        "//lib:gwtorm-client_src",
-    ],
-)
-
 java_library(
     name = "server",
     srcs = glob(["**/*.java"]),
diff --git a/java/com/google/gerrit/reviewdb/ReviewDB.gwt.xml b/java/com/google/gerrit/reviewdb/ReviewDB.gwt.xml
deleted file mode 100644
index 4402826..0000000
--- a/java/com/google/gerrit/reviewdb/ReviewDB.gwt.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<!--
- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<module>
-  <inherits name='com.google.gwtorm.GWTORM'/>
-</module>
diff --git a/java/com/google/gerrit/reviewdb/server/ReviewDb.java b/java/com/google/gerrit/reviewdb/server/ReviewDb.java
index f0661e9..8e4292c 100644
--- a/java/com/google/gerrit/reviewdb/server/ReviewDb.java
+++ b/java/com/google/gerrit/reviewdb/server/ReviewDb.java
@@ -33,7 +33,7 @@
  * </ul>
  */
 public interface ReviewDb extends Schema {
-  /* If you change anything, update SchemaVersion.C to use a new version. */
+  /* If you change anything, update ReviewDbSchemaVersion.C to use a new version. */
 
   @Relation(id = 1)
   SchemaVersionAccess schemaVersion();
diff --git a/java/com/google/gerrit/server/BUILD b/java/com/google/gerrit/server/BUILD
index 0d48bca..8401852 100644
--- a/java/com/google/gerrit/server/BUILD
+++ b/java/com/google/gerrit/server/BUILD
@@ -32,6 +32,7 @@
         "//java/com/google/gerrit/common:annotations",
         "//java/com/google/gerrit/common:server",
         "//java/com/google/gerrit/extensions:api",
+        "//java/com/google/gerrit/git",
         "//java/com/google/gerrit/index",
         "//java/com/google/gerrit/index:query_exception",
         "//java/com/google/gerrit/index/project",
diff --git a/java/com/google/gerrit/server/CreateGroupPermissionSyncer.java b/java/com/google/gerrit/server/CreateGroupPermissionSyncer.java
index ee0138c..94ce924 100644
--- a/java/com/google/gerrit/server/CreateGroupPermissionSyncer.java
+++ b/java/com/google/gerrit/server/CreateGroupPermissionSyncer.java
@@ -57,17 +57,20 @@
   private final AllUsersName allUsers;
   private final ProjectCache projectCache;
   private final Provider<MetaDataUpdate.Server> metaDataUpdateFactory;
+  private final ProjectConfig.Factory projectConfigFactory;
 
   @Inject
   CreateGroupPermissionSyncer(
       AllProjectsName allProjects,
       AllUsersName allUsers,
       ProjectCache projectCache,
-      Provider<MetaDataUpdate.Server> metaDataUpdateFactory) {
+      Provider<MetaDataUpdate.Server> metaDataUpdateFactory,
+      ProjectConfig.Factory projectConfigFactory) {
     this.allProjects = allProjects;
     this.allUsers = allUsers;
     this.projectCache = projectCache;
     this.metaDataUpdateFactory = metaDataUpdateFactory;
+    this.projectConfigFactory = projectConfigFactory;
   }
 
   /**
@@ -102,7 +105,7 @@
     }
 
     try (MetaDataUpdate md = metaDataUpdateFactory.get().create(allUsers)) {
-      ProjectConfig config = ProjectConfig.read(md);
+      ProjectConfig config = projectConfigFactory.read(md);
       AccessSection createGroupAccessSection =
           config.getAccessSection(RefNames.REFS_GROUPS + "*", true);
       if (createGroupsGlobal.isEmpty()) {
diff --git a/java/com/google/gerrit/server/account/AccountsUpdate.java b/java/com/google/gerrit/server/account/AccountsUpdate.java
index 1445dfd..ff1c50b 100644
--- a/java/com/google/gerrit/server/account/AccountsUpdate.java
+++ b/java/com/google/gerrit/server/account/AccountsUpdate.java
@@ -25,6 +25,8 @@
 import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.Runnables;
 import com.google.gerrit.common.Nullable;
+import com.google.gerrit.git.LockFailureException;
+import com.google.gerrit.git.RefUpdateUtil;
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.IdentifiedUser;
@@ -35,10 +37,8 @@
 import com.google.gerrit.server.config.AllUsersName;
 import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
 import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.LockFailureException;
 import com.google.gerrit.server.git.meta.MetaDataUpdate;
 import com.google.gerrit.server.index.change.ReindexAfterRefUpdate;
-import com.google.gerrit.server.update.RefUpdateUtil;
 import com.google.gerrit.server.update.RetryHelper;
 import com.google.gerrit.server.update.RetryHelper.Action;
 import com.google.gerrit.server.update.RetryHelper.ActionType;
diff --git a/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java b/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java
index 358a3a8..0f731ed 100644
--- a/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java
+++ b/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java
@@ -43,7 +43,6 @@
 import com.google.gerrit.extensions.common.ChangeMessageInfo;
 import com.google.gerrit.extensions.common.CommentInfo;
 import com.google.gerrit.extensions.common.CommitMessageInput;
-import com.google.gerrit.extensions.common.EditInfo;
 import com.google.gerrit.extensions.common.Input;
 import com.google.gerrit.extensions.common.MergePatchSetInput;
 import com.google.gerrit.extensions.common.PureRevertInfo;
@@ -256,16 +255,6 @@
   }
 
   @Override
-  public RevisionApi current() throws RestApiException {
-    return revision("current");
-  }
-
-  @Override
-  public RevisionApi revision(int id) throws RestApiException {
-    return revision(String.valueOf(id));
-  }
-
-  @Override
   public RevisionApi revision(String id) throws RestApiException {
     try {
       return revisionApi.create(revisions.parse(change, IdString.fromDecoded(id)));
@@ -284,11 +273,6 @@
   }
 
   @Override
-  public void abandon() throws RestApiException {
-    abandon(new AbandonInput());
-  }
-
-  @Override
   public void abandon(AbandonInput in) throws RestApiException {
     try {
       abandon.apply(change, in);
@@ -298,11 +282,6 @@
   }
 
   @Override
-  public void restore() throws RestApiException {
-    restore(new RestoreInput());
-  }
-
-  @Override
   public void restore(RestoreInput in) throws RestApiException {
     try {
       restore.apply(change, in);
@@ -312,13 +291,6 @@
   }
 
   @Override
-  public void move(String destination) throws RestApiException {
-    MoveInput in = new MoveInput();
-    in.destinationBranch = destination;
-    move(in);
-  }
-
-  @Override
   public void move(MoveInput in) throws RestApiException {
     try {
       move.apply(change, in);
@@ -360,11 +332,6 @@
   }
 
   @Override
-  public ChangeApi revert() throws RestApiException {
-    return revert(new RevertInput());
-  }
-
-  @Override
   public ChangeApi revert(RevertInput in) throws RestApiException {
     try {
       return changeApi.id(revert.apply(change, in)._number);
@@ -383,20 +350,6 @@
   }
 
   @Override
-  public List<ChangeInfo> submittedTogether() throws RestApiException {
-    SubmittedTogetherInfo info =
-        submittedTogether(
-            EnumSet.noneOf(ListChangesOption.class), EnumSet.noneOf(SubmittedTogetherOption.class));
-    return info.changes;
-  }
-
-  @Override
-  public SubmittedTogetherInfo submittedTogether(EnumSet<SubmittedTogetherOption> options)
-      throws RestApiException {
-    return submittedTogether(EnumSet.noneOf(ListChangesOption.class), options);
-  }
-
-  @Override
   public SubmittedTogetherInfo submittedTogether(
       EnumSet<ListChangesOption> listOptions, EnumSet<SubmittedTogetherOption> submitOptions)
       throws RestApiException {
@@ -411,17 +364,6 @@
     }
   }
 
-  @Deprecated
-  @Override
-  public void publish() throws RestApiException {
-    throw new UnsupportedOperationException("draft workflow is discontinued");
-  }
-
-  @Override
-  public void rebase() throws RestApiException {
-    rebase(new RebaseInput());
-  }
-
   @Override
   public void rebase(RebaseInput in) throws RestApiException {
     try {
@@ -466,13 +408,6 @@
   }
 
   @Override
-  public AddReviewerResult addReviewer(String reviewer) throws RestApiException {
-    AddReviewerInput in = new AddReviewerInput();
-    in.reviewer = reviewer;
-    return addReviewer(in);
-  }
-
-  @Override
   public AddReviewerResult addReviewer(AddReviewerInput in) throws RestApiException {
     try {
       return postReviewers.apply(change, in);
@@ -491,11 +426,6 @@
     };
   }
 
-  @Override
-  public SuggestedReviewersRequest suggestReviewers(String query) throws RestApiException {
-    return suggestReviewers().withQuery(query);
-  }
-
   private List<SuggestedReviewerInfo> suggestReviewers(SuggestedReviewersRequest r)
       throws RestApiException {
     try {
@@ -517,30 +447,11 @@
   }
 
   @Override
-  public ChangeInfo get() throws RestApiException {
-    return get(
-        EnumSet.complementOf(
-            EnumSet.of(ListChangesOption.CHECK, ListChangesOption.SKIP_MERGEABLE)));
-  }
-
-  @Override
-  public EditInfo getEdit() throws RestApiException {
-    return edit().get().orElse(null);
-  }
-
-  @Override
   public ChangeEditApi edit() throws RestApiException {
     return changeEditApi.create(change);
   }
 
   @Override
-  public void setMessage(String msg) throws RestApiException {
-    CommitMessageInput in = new CommitMessageInput();
-    in.message = msg;
-    setMessage(in);
-  }
-
-  @Override
   public void setMessage(CommitMessageInput in) throws RestApiException {
     try {
       putMessage.apply(change, in);
@@ -550,11 +461,6 @@
   }
 
   @Override
-  public ChangeInfo info() throws RestApiException {
-    return get(EnumSet.noneOf(ListChangesOption.class));
-  }
-
-  @Override
   public void setHashtags(HashtagsInput input) throws RestApiException {
     try {
       postHashtags.apply(change, input);
diff --git a/java/com/google/gerrit/server/api/changes/RevisionApiImpl.java b/java/com/google/gerrit/server/api/changes/RevisionApiImpl.java
index 33f211d..f8a2ecb 100644
--- a/java/com/google/gerrit/server/api/changes/RevisionApiImpl.java
+++ b/java/com/google/gerrit/server/api/changes/RevisionApiImpl.java
@@ -18,6 +18,7 @@
 import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
 
 import com.google.common.collect.ImmutableSet;
+import com.google.gerrit.common.Nullable;
 import com.google.gerrit.extensions.api.changes.ChangeApi;
 import com.google.gerrit.extensions.api.changes.Changes;
 import com.google.gerrit.extensions.api.changes.CherryPickInput;
@@ -26,6 +27,7 @@
 import com.google.gerrit.extensions.api.changes.DraftInput;
 import com.google.gerrit.extensions.api.changes.FileApi;
 import com.google.gerrit.extensions.api.changes.RebaseInput;
+import com.google.gerrit.extensions.api.changes.RelatedChangesInfo;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
 import com.google.gerrit.extensions.api.changes.ReviewResult;
 import com.google.gerrit.extensions.api.changes.RevisionApi;
@@ -64,6 +66,7 @@
 import com.google.gerrit.server.restapi.change.GetDescription;
 import com.google.gerrit.server.restapi.change.GetMergeList;
 import com.google.gerrit.server.restapi.change.GetPatch;
+import com.google.gerrit.server.restapi.change.GetRelated;
 import com.google.gerrit.server.restapi.change.GetRevisionActions;
 import com.google.gerrit.server.restapi.change.ListRevisionComments;
 import com.google.gerrit.server.restapi.change.ListRevisionDrafts;
@@ -129,6 +132,7 @@
   private final TestSubmitType.Get getSubmitType;
   private final Provider<TestSubmitRule> testSubmitRule;
   private final Provider<GetMergeList> getMergeList;
+  private final GetRelated getRelated;
   private final PutDescription putDescription;
   private final GetDescription getDescription;
 
@@ -169,6 +173,7 @@
       TestSubmitType.Get getSubmitType,
       Provider<TestSubmitRule> testSubmitRule,
       Provider<GetMergeList> getMergeList,
+      GetRelated getRelated,
       PutDescription putDescription,
       GetDescription getDescription,
       @Assisted RevisionResource r) {
@@ -207,6 +212,7 @@
     this.getSubmitType = getSubmitType;
     this.testSubmitRule = testSubmitRule;
     this.getMergeList = getMergeList;
+    this.getRelated = getRelated;
     this.putDescription = putDescription;
     this.getDescription = getDescription;
     this.revision = r;
@@ -222,12 +228,6 @@
   }
 
   @Override
-  public void submit() throws RestApiException {
-    SubmitInput in = new SubmitInput();
-    submit(in);
-  }
-
-  @Override
   public void submit(SubmitInput in) throws RestApiException {
     try {
       submit.apply(revision, in);
@@ -237,11 +237,6 @@
   }
 
   @Override
-  public BinaryResult submitPreview() throws RestApiException {
-    return submitPreview("zip");
-  }
-
-  @Override
   public BinaryResult submitPreview(String format) throws RestApiException {
     try {
       submitPreview.setFormat(format);
@@ -252,22 +247,6 @@
   }
 
   @Override
-  public void publish() throws RestApiException {
-    throw new UnsupportedOperationException("draft workflow is discontinued");
-  }
-
-  @Override
-  public void delete() throws RestApiException {
-    throw new UnsupportedOperationException("draft workflow is discontinued");
-  }
-
-  @Override
-  public ChangeApi rebase() throws RestApiException {
-    RebaseInput in = new RebaseInput();
-    return rebase(in);
-  }
-
-  @Override
   public ChangeApi rebase(RebaseInput in) throws RestApiException {
     try {
       return changes.id(rebase.apply(revision, in)._number);
@@ -361,17 +340,7 @@
 
   @SuppressWarnings("unchecked")
   @Override
-  public Map<String, FileInfo> files() throws RestApiException {
-    try {
-      return (Map<String, FileInfo>) listFiles.apply(revision).value();
-    } catch (Exception e) {
-      throw asRestApiException("Cannot retrieve files", e);
-    }
-  }
-
-  @SuppressWarnings("unchecked")
-  @Override
-  public Map<String, FileInfo> files(String base) throws RestApiException {
+  public Map<String, FileInfo> files(@Nullable String base) throws RestApiException {
     try {
       return (Map<String, FileInfo>) listFiles.setBase(base).apply(revision).value();
     } catch (Exception e) {
@@ -590,6 +559,15 @@
   }
 
   @Override
+  public RelatedChangesInfo related() throws RestApiException {
+    try {
+      return getRelated.apply(revision);
+    } catch (Exception e) {
+      throw asRestApiException("Cannot get related changes", e);
+    }
+  }
+
+  @Override
   public void description(String description) throws RestApiException {
     DescriptionInput in = new DescriptionInput();
     in.description = description;
diff --git a/java/com/google/gerrit/server/change/ChangeJson.java b/java/com/google/gerrit/server/change/ChangeJson.java
index c64cd12..b7049a7 100644
--- a/java/com/google/gerrit/server/change/ChangeJson.java
+++ b/java/com/google/gerrit/server/change/ChangeJson.java
@@ -535,6 +535,7 @@
     out.created = in.getCreatedOn();
     out.updated = in.getLastUpdatedOn();
     out._number = in.getId().get();
+    out.totalCommentCount = cd.totalCommentCount();
     out.unresolvedCommentCount = cd.unresolvedCommentCount();
 
     if (user.isIdentifiedUser()) {
diff --git a/java/com/google/gerrit/server/change/RebaseChangeOp.java b/java/com/google/gerrit/server/change/RebaseChangeOp.java
index 1f216f0..dac8fec 100644
--- a/java/com/google/gerrit/server/change/RebaseChangeOp.java
+++ b/java/com/google/gerrit/server/change/RebaseChangeOp.java
@@ -20,12 +20,14 @@
 import com.google.gerrit.extensions.restapi.MergeConflictException;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.RestApiException;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gerrit.reviewdb.client.RevId;
 import com.google.gerrit.server.ChangeUtil;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.change.RebaseUtil.Base;
+import com.google.gerrit.server.git.GroupCollector;
 import com.google.gerrit.server.git.MergeUtil;
 import com.google.gerrit.server.notedb.ChangeNotes;
 import com.google.gerrit.server.permissions.PermissionBackendException;
@@ -199,8 +201,14 @@
               + " was rebased");
     }
 
-    if (base != null) {
-      patchSetInserter.setGroups(base.patchSet().getGroups());
+    if (base != null && base.notes().getChange().getStatus() != Change.Status.MERGED) {
+      if (base.notes().getChange().getStatus() != Change.Status.MERGED) {
+        // Add to end of relation chain for open base change.
+        patchSetInserter.setGroups(base.patchSet().getGroups());
+      } else {
+        // If the base is merged, start a new relation chain.
+        patchSetInserter.setGroups(GroupCollector.getDefaultGroups(rebasedCommit));
+      }
     }
     patchSetInserter.updateRepo(ctx);
   }
diff --git a/java/com/google/gerrit/server/config/GerritOptions.java b/java/com/google/gerrit/server/config/GerritOptions.java
index 0192ddd..17b65c9 100644
--- a/java/com/google/gerrit/server/config/GerritOptions.java
+++ b/java/com/google/gerrit/server/config/GerritOptions.java
@@ -14,29 +14,21 @@
 
 package com.google.gerrit.server.config;
 
-import org.eclipse.jgit.lib.Config;
-
 public class GerritOptions {
   private final boolean headless;
   private final boolean slave;
-  private final boolean enableGwtUi;
   private final boolean forcePolyGerritDev;
 
-  public GerritOptions(Config cfg, boolean headless, boolean slave, boolean forcePolyGerritDev) {
-    this.slave = slave;
-    this.enableGwtUi = cfg.getBoolean("gerrit", null, "enableGwtUi", true);
-    this.forcePolyGerritDev = forcePolyGerritDev;
+  public GerritOptions(boolean headless, boolean slave, boolean forcePolyGerritDev) {
     this.headless = headless;
+    this.slave = slave;
+    this.forcePolyGerritDev = forcePolyGerritDev;
   }
 
   public boolean headless() {
     return headless;
   }
 
-  public boolean enableGwtUi() {
-    return !headless && enableGwtUi;
-  }
-
   public boolean enableMasterFeatures() {
     return !slave;
   }
diff --git a/java/com/google/gerrit/server/config/ProjectConfigEntry.java b/java/com/google/gerrit/server/config/ProjectConfigEntry.java
index 5515f0e..92ae10a 100644
--- a/java/com/google/gerrit/server/config/ProjectConfigEntry.java
+++ b/java/com/google/gerrit/server/config/ProjectConfigEntry.java
@@ -302,12 +302,16 @@
 
     private final GitRepositoryManager repoManager;
     private final DynamicMap<ProjectConfigEntry> pluginConfigEntries;
+    private final ProjectConfig.Factory projectConfigFactory;
 
     @Inject
     UpdateChecker(
-        GitRepositoryManager repoManager, DynamicMap<ProjectConfigEntry> pluginConfigEntries) {
+        GitRepositoryManager repoManager,
+        DynamicMap<ProjectConfigEntry> pluginConfigEntries,
+        ProjectConfig.Factory projectConfigFactory) {
       this.repoManager = repoManager;
       this.pluginConfigEntries = pluginConfigEntries;
+      this.projectConfigFactory = projectConfigFactory;
     }
 
     @Override
@@ -361,7 +365,7 @@
         return null;
       }
       try (Repository repo = repoManager.openRepository(p)) {
-        ProjectConfig pc = new ProjectConfig(p);
+        ProjectConfig pc = projectConfigFactory.create(p);
         pc.load(repo, id);
         return pc;
       }
diff --git a/java/com/google/gerrit/server/git/BanCommit.java b/java/com/google/gerrit/server/git/BanCommit.java
index 4991715..3cb771e 100644
--- a/java/com/google/gerrit/server/git/BanCommit.java
+++ b/java/com/google/gerrit/server/git/BanCommit.java
@@ -18,6 +18,7 @@
 import static java.nio.charset.StandardCharsets.UTF_8;
 
 import com.google.gerrit.extensions.restapi.AuthException;
+import com.google.gerrit.git.LockFailureException;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.reviewdb.client.RefNames;
 import com.google.gerrit.server.CurrentUser;
diff --git a/java/com/google/gerrit/server/git/DefaultAdvertiseRefsHook.java b/java/com/google/gerrit/server/git/DefaultAdvertiseRefsHook.java
index ef5e65b..be8fcdb 100644
--- a/java/com/google/gerrit/server/git/DefaultAdvertiseRefsHook.java
+++ b/java/com/google/gerrit/server/git/DefaultAdvertiseRefsHook.java
@@ -14,8 +14,11 @@
 
 package com.google.gerrit.server.git;
 
+import com.google.common.collect.ImmutableMap;
 import com.google.gerrit.server.permissions.PermissionBackend;
 import com.google.gerrit.server.permissions.PermissionBackendException;
+import java.io.IOException;
+import java.util.List;
 import java.util.Map;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
@@ -28,7 +31,6 @@
  * implements {@link org.eclipse.jgit.transport.AdvertiseRefsHook}.
  */
 public class DefaultAdvertiseRefsHook extends AbstractAdvertiseRefsHook {
-
   private final PermissionBackend.ForProject perm;
   private final PermissionBackend.RefFilterOptions opts;
 
@@ -42,9 +44,24 @@
   protected Map<String, Ref> getAdvertisedRefs(Repository repo, RevWalk revWalk)
       throws ServiceMayNotContinueException {
     try {
-      return perm.filter(repo.getAllRefs(), repo, opts);
-    } catch (PermissionBackendException e) {
-      throw new ServiceMayNotContinueException(e);
+      Map<String, Ref> refs;
+      List<String> prefixes = opts.prefixes();
+      if (prefixes.isEmpty() || prefixes.get(0).isEmpty()) {
+        refs = repo.getAllRefs();
+      } else {
+        ImmutableMap.Builder<String, Ref> b = new ImmutableMap.Builder<>();
+        for (String prefix : prefixes) {
+          for (Ref ref : repo.getRefDatabase().getRefsByPrefix(prefix)) {
+            b.put(ref.getName(), ref);
+          }
+        }
+        refs = b.build();
+      }
+      return perm.filter(refs, repo, opts);
+    } catch (IOException | PermissionBackendException e) {
+      ServiceMayNotContinueException ex = new ServiceMayNotContinueException();
+      ex.initCause(e);
+      throw ex;
     }
   }
 }
diff --git a/java/com/google/gerrit/server/git/LockFailureException.java b/java/com/google/gerrit/server/git/LockFailureException.java
deleted file mode 100644
index 02a30e0..0000000
--- a/java/com/google/gerrit/server/git/LockFailureException.java
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.git;
-
-import static com.google.common.collect.ImmutableList.toImmutableList;
-
-import com.google.common.collect.ImmutableList;
-import java.io.IOException;
-import org.eclipse.jgit.lib.BatchRefUpdate;
-import org.eclipse.jgit.lib.RefUpdate;
-import org.eclipse.jgit.transport.ReceiveCommand;
-
-/** Thrown when updating a ref in Git fails with LOCK_FAILURE. */
-public class LockFailureException extends IOException {
-  private static final long serialVersionUID = 1L;
-
-  private final ImmutableList<String> refs;
-
-  public LockFailureException(String message, RefUpdate refUpdate) {
-    super(message);
-    refs = ImmutableList.of(refUpdate.getName());
-  }
-
-  public LockFailureException(String message, BatchRefUpdate batchRefUpdate) {
-    super(message);
-    refs =
-        batchRefUpdate
-            .getCommands()
-            .stream()
-            .filter(c -> c.getResult() == ReceiveCommand.Result.LOCK_FAILURE)
-            .map(ReceiveCommand::getRefName)
-            .collect(toImmutableList());
-  }
-
-  /** Subset of ref names that caused the lock failure. */
-  public ImmutableList<String> getFailedRefs() {
-    return refs;
-  }
-}
diff --git a/java/com/google/gerrit/server/git/MultiBaseLocalDiskRepositoryManager.java b/java/com/google/gerrit/server/git/MultiBaseLocalDiskRepositoryManager.java
index 6fafe4e..01e85cf 100644
--- a/java/com/google/gerrit/server/git/MultiBaseLocalDiskRepositoryManager.java
+++ b/java/com/google/gerrit/server/git/MultiBaseLocalDiskRepositoryManager.java
@@ -17,7 +17,7 @@
 import static com.google.common.base.Preconditions.checkState;
 
 import com.google.gerrit.lifecycle.LifecycleModule;
-import com.google.gerrit.reviewdb.client.Project.NameKey;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.RepositoryConfig;
 import com.google.gerrit.server.config.SitePaths;
@@ -54,7 +54,7 @@
   }
 
   @Override
-  public Path getBasePath(NameKey name) {
+  public Path getBasePath(Project.NameKey name) {
     Path alternateBasePath = config.getBasePath(name);
     return alternateBasePath != null ? alternateBasePath : super.getBasePath(name);
   }
diff --git a/java/com/google/gerrit/server/git/NotesBranchUtil.java b/java/com/google/gerrit/server/git/NotesBranchUtil.java
index 24b3727..1636b85 100644
--- a/java/com/google/gerrit/server/git/NotesBranchUtil.java
+++ b/java/com/google/gerrit/server/git/NotesBranchUtil.java
@@ -16,10 +16,11 @@
 
 import static com.google.common.base.MoreObjects.firstNonNull;
 
+import com.google.gerrit.git.LockFailureException;
+import com.google.gerrit.git.RefUpdateUtil;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.update.RefUpdateUtil;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 import java.io.IOException;
diff --git a/java/com/google/gerrit/server/git/meta/VersionedMetaData.java b/java/com/google/gerrit/server/git/meta/VersionedMetaData.java
index 8b14177..196267e 100644
--- a/java/com/google/gerrit/server/git/meta/VersionedMetaData.java
+++ b/java/com/google/gerrit/server/git/meta/VersionedMetaData.java
@@ -19,8 +19,8 @@
 import com.google.common.base.MoreObjects;
 import com.google.common.flogger.FluentLogger;
 import com.google.gerrit.common.Nullable;
+import com.google.gerrit.git.LockFailureException;
 import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.server.git.LockFailureException;
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.StringReader;
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
index 6267590..c747533 100644
--- a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
+++ b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
@@ -321,6 +321,7 @@
   private final SetHashtagsOp.Factory hashtagsFactory;
   private final SubmoduleOp.Factory subOpFactory;
   private final TagCache tagCache;
+  private final ProjectConfig.Factory projectConfigFactory;
 
   // Assisted injected fields.
   private final AllRefsWatcher allRefsWatcher;
@@ -365,6 +366,7 @@
       AccountResolver accountResolver,
       AllProjectsName allProjectsName,
       BatchUpdate.Factory batchUpdateFactory,
+      ProjectConfig.Factory projectConfigFactory,
       @GerritServerConfig Config cfg,
       ChangeEditUtil editUtil,
       ChangeIndexer indexer,
@@ -437,6 +439,7 @@
     this.seq = seq;
     this.subOpFactory = subOpFactory;
     this.tagCache = tagCache;
+    this.projectConfigFactory = projectConfigFactory;
 
     // Assisted injected fields.
     this.allRefsWatcher = allRefsWatcher;
@@ -1055,7 +1058,7 @@
       case UPDATE:
       case UPDATE_NONFASTFORWARD:
         try {
-          ProjectConfig cfg = new ProjectConfig(project.getNameKey());
+          ProjectConfig cfg = projectConfigFactory.create(project.getNameKey());
           cfg.load(project.getNameKey(), receivePack.getRevWalk(), cmd.getNewId());
           if (!cfg.getValidationErrors().isEmpty()) {
             addError("Invalid project configuration:");
diff --git a/java/com/google/gerrit/server/git/validators/CommitValidators.java b/java/com/google/gerrit/server/git/validators/CommitValidators.java
index 9f75c07..e3dfa75 100644
--- a/java/com/google/gerrit/server/git/validators/CommitValidators.java
+++ b/java/com/google/gerrit/server/git/validators/CommitValidators.java
@@ -98,6 +98,7 @@
     private final AccountValidator accountValidator;
     private final String installCommitMsgHookCommand;
     private final ProjectCache projectCache;
+    private final ProjectConfig.Factory projectConfigFactory;
 
     @Inject
     Factory(
@@ -110,7 +111,8 @@
         AllProjectsName allProjects,
         ExternalIdsConsistencyChecker externalIdsConsistencyChecker,
         AccountValidator accountValidator,
-        ProjectCache projectCache) {
+        ProjectCache projectCache,
+        ProjectConfig.Factory projectConfigFactory) {
       this.gerritIdent = gerritIdent;
       this.urlFormatter = urlFormatter;
       this.pluginValidators = pluginValidators;
@@ -122,6 +124,7 @@
       this.installCommitMsgHookCommand =
           cfg != null ? cfg.getString("gerrit", null, "installCommitMsgHookCommand") : null;
       this.projectCache = projectCache;
+      this.projectConfigFactory = projectConfigFactory;
     }
 
     public CommitValidators forReceiveCommits(
@@ -145,7 +148,7 @@
               new SignedOffByValidator(user, perm, projectState),
               new ChangeIdValidator(
                   projectState, user, urlFormatter, installCommitMsgHookCommand, sshInfo, change),
-              new ConfigValidator(branch, user, rw, allUsers, allProjects),
+              new ConfigValidator(projectConfigFactory, branch, user, rw, allUsers, allProjects),
               new BannedCommitsValidator(rejectCommits),
               new PluginCommitValidationListener(pluginValidators),
               new ExternalIdUpdateListener(allUsers, externalIdsConsistencyChecker),
@@ -172,7 +175,7 @@
               new SignedOffByValidator(user, perm, projectCache.checkedGet(branch.getParentKey())),
               new ChangeIdValidator(
                   projectState, user, urlFormatter, installCommitMsgHookCommand, sshInfo, change),
-              new ConfigValidator(branch, user, rw, allUsers, allProjects),
+              new ConfigValidator(projectConfigFactory, branch, user, rw, allUsers, allProjects),
               new PluginCommitValidationListener(pluginValidators),
               new ExternalIdUpdateListener(allUsers, externalIdsConsistencyChecker),
               new AccountCommitValidator(repoManager, allUsers, accountValidator),
@@ -331,7 +334,8 @@
             .append(getCommitMessageHookInstallationHint())
             .append("\n")
             .append("and then amend the commit:\n")
-            .append("  git commit --amend\n");
+            .append("  git commit --amend\n")
+            .append("Finally, push your changes again\n");
       }
       return new CommitValidationMessage(sb.toString(), Type.ERROR);
     }
@@ -378,6 +382,7 @@
 
   /** If this is the special project configuration branch, validate the config. */
   public static class ConfigValidator implements CommitValidationListener {
+    private final ProjectConfig.Factory projectConfigFactory;
     private final Branch.NameKey branch;
     private final IdentifiedUser user;
     private final RevWalk rw;
@@ -385,11 +390,13 @@
     private final AllProjectsName allProjects;
 
     public ConfigValidator(
+        ProjectConfig.Factory projectConfigFactory,
         Branch.NameKey branch,
         IdentifiedUser user,
         RevWalk rw,
         AllUsersName allUsers,
         AllProjectsName allProjects) {
+      this.projectConfigFactory = projectConfigFactory;
       this.branch = branch;
       this.user = user;
       this.rw = rw;
@@ -404,7 +411,7 @@
         List<CommitValidationMessage> messages = new ArrayList<>();
 
         try {
-          ProjectConfig cfg = new ProjectConfig(receiveEvent.project.getNameKey());
+          ProjectConfig cfg = projectConfigFactory.create(receiveEvent.project.getNameKey());
           cfg.load(rw, receiveEvent.command.getNewId());
           if (!cfg.getValidationErrors().isEmpty()) {
             addError("Invalid project configuration:", messages);
diff --git a/java/com/google/gerrit/server/git/validators/MergeValidators.java b/java/com/google/gerrit/server/git/validators/MergeValidators.java
index 0422c51..56a641f 100644
--- a/java/com/google/gerrit/server/git/validators/MergeValidators.java
+++ b/java/com/google/gerrit/server/git/validators/MergeValidators.java
@@ -127,6 +127,7 @@
     private final ProjectCache projectCache;
     private final PermissionBackend permissionBackend;
     private final DynamicMap<ProjectConfigEntry> pluginConfigEntries;
+    private final ProjectConfig.Factory projectConfigFactory;
     private final boolean allowProjectOwnersToChangeParent;
 
     public interface Factory {
@@ -140,12 +141,14 @@
         ProjectCache projectCache,
         PermissionBackend permissionBackend,
         DynamicMap<ProjectConfigEntry> pluginConfigEntries,
+        ProjectConfig.Factory projectConfigFactory,
         @GerritServerConfig Config config) {
       this.allProjectsName = allProjectsName;
       this.allUsersName = allUsersName;
       this.projectCache = projectCache;
       this.permissionBackend = permissionBackend;
       this.pluginConfigEntries = pluginConfigEntries;
+      this.projectConfigFactory = projectConfigFactory;
       this.allowProjectOwnersToChangeParent =
           config.getBoolean("receive", "allowProjectOwnersToChangeParent", false);
     }
@@ -162,7 +165,7 @@
       if (RefNames.REFS_CONFIG.equals(destBranch.get())) {
         final Project.NameKey newParent;
         try {
-          ProjectConfig cfg = new ProjectConfig(destProject.getNameKey());
+          ProjectConfig cfg = projectConfigFactory.create(destProject.getNameKey());
           cfg.load(destProject.getNameKey(), repo, commit);
           newParent = cfg.getProject().getParent(allProjectsName);
           final Project.NameKey oldParent = destProject.getProject().getParent(allProjectsName);
diff --git a/java/com/google/gerrit/server/group/db/GroupsUpdate.java b/java/com/google/gerrit/server/group/db/GroupsUpdate.java
index 6477f31..ecb9b2d 100644
--- a/java/com/google/gerrit/server/group/db/GroupsUpdate.java
+++ b/java/com/google/gerrit/server/group/db/GroupsUpdate.java
@@ -21,6 +21,8 @@
 import com.google.common.collect.Sets;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.common.errors.NoSuchGroupException;
+import com.google.gerrit.git.LockFailureException;
+import com.google.gerrit.git.RefUpdateUtil;
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.reviewdb.client.Project;
@@ -34,12 +36,10 @@
 import com.google.gerrit.server.config.GerritServerId;
 import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
 import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.LockFailureException;
 import com.google.gerrit.server.git.meta.MetaDataUpdate;
 import com.google.gerrit.server.group.GroupAuditService;
 import com.google.gerrit.server.group.InternalGroup;
 import com.google.gerrit.server.index.group.GroupIndexer;
-import com.google.gerrit.server.update.RefUpdateUtil;
 import com.google.gerrit.server.update.RetryHelper;
 import com.google.gerrit.server.util.time.TimeUtil;
 import com.google.gwtorm.server.OrmDuplicateKeyException;
diff --git a/java/com/google/gerrit/server/group/db/RenameGroupOp.java b/java/com/google/gerrit/server/group/db/RenameGroupOp.java
index eada57d..e002192 100644
--- a/java/com/google/gerrit/server/group/db/RenameGroupOp.java
+++ b/java/com/google/gerrit/server/group/db/RenameGroupOp.java
@@ -49,6 +49,7 @@
 
   private final ProjectCache projectCache;
   private final MetaDataUpdate.Server metaDataUpdateFactory;
+  private final ProjectConfig.Factory projectConfigFactory;
 
   private final PersonIdent author;
   private final AccountGroup.UUID uuid;
@@ -63,6 +64,7 @@
       WorkQueue workQueue,
       ProjectCache projectCache,
       MetaDataUpdate.Server metaDataUpdateFactory,
+      ProjectConfig.Factory projectConfigFactory,
       @Assisted("author") PersonIdent author,
       @Assisted AccountGroup.UUID uuid,
       @Assisted("oldName") String oldName,
@@ -70,6 +72,7 @@
     super(workQueue);
     this.projectCache = projectCache;
     this.metaDataUpdateFactory = metaDataUpdateFactory;
+    this.projectConfigFactory = projectConfigFactory;
 
     this.author = author;
     this.uuid = uuid;
@@ -109,7 +112,7 @@
   private void rename(MetaDataUpdate md) throws IOException, ConfigInvalidException {
     boolean success = false;
     for (int attempts = 0; !success && attempts < MAX_TRIES; attempts++) {
-      ProjectConfig config = ProjectConfig.read(md);
+      ProjectConfig config = projectConfigFactory.read(md);
 
       // The group isn't referenced, or its name has been fixed already.
       //
diff --git a/java/com/google/gerrit/server/index/change/ChangeField.java b/java/com/google/gerrit/server/index/change/ChangeField.java
index 5d12e79..b79a1c2 100644
--- a/java/com/google/gerrit/server/index/change/ChangeField.java
+++ b/java/com/google/gerrit/server/index/change/ChangeField.java
@@ -508,11 +508,15 @@
                           cd.messages().stream().map(ChangeMessage::getMessage))
                       .collect(toSet()));
 
-  /** Number of unresolved comments of the change. */
+  /** Number of unresolved comment threads of the change, including robot comments. */
   public static final FieldDef<ChangeData, Integer> UNRESOLVED_COMMENT_COUNT =
       intRange(ChangeQueryBuilder.FIELD_UNRESOLVED_COMMENT_COUNT)
           .build(ChangeData::unresolvedCommentCount);
 
+  /** Total number of published inline comments of the change, including robot comments. */
+  public static final FieldDef<ChangeData, Integer> TOTAL_COMMENT_COUNT =
+      intRange("total_comments").build(ChangeData::totalCommentCount);
+
   /** Whether the change is mergeable. */
   public static final FieldDef<ChangeData, String> MERGEABLE =
       exact(ChangeQueryBuilder.FIELD_MERGEABLE)
diff --git a/java/com/google/gerrit/server/index/change/ChangeSchemaDefinitions.java b/java/com/google/gerrit/server/index/change/ChangeSchemaDefinitions.java
index 2000cd1..9016fd1 100644
--- a/java/com/google/gerrit/server/index/change/ChangeSchemaDefinitions.java
+++ b/java/com/google/gerrit/server/index/change/ChangeSchemaDefinitions.java
@@ -99,7 +99,9 @@
   @Deprecated static final Schema<ChangeData> V49 = schema(V48);
 
   // Bump Lucene version requires reindexing
-  static final Schema<ChangeData> V50 = schema(V49);
+  @Deprecated static final Schema<ChangeData> V50 = schema(V49);
+
+  static final Schema<ChangeData> V51 = schema(V50, ChangeField.TOTAL_COMMENT_COUNT);
 
   public static final String NAME = "changes";
   public static final ChangeSchemaDefinitions INSTANCE = new ChangeSchemaDefinitions();
diff --git a/java/com/google/gerrit/server/ioutil/BUILD b/java/com/google/gerrit/server/ioutil/BUILD
index 15e67af..ea91929 100644
--- a/java/com/google/gerrit/server/ioutil/BUILD
+++ b/java/com/google/gerrit/server/ioutil/BUILD
@@ -3,7 +3,7 @@
     srcs = glob(["**/*.java"]),
     visibility = ["//visibility:public"],
     deps = [
-        "//java/com/google/gerrit/reviewdb:client",
+        "//java/com/google/gerrit/reviewdb:server",
         "//lib:automaton",
         "//lib:guava",
         "//lib/jgit/org.eclipse.jgit.archive:jgit-archive",
diff --git a/java/com/google/gerrit/server/notedb/CommentJsonMigrator.java b/java/com/google/gerrit/server/notedb/CommentJsonMigrator.java
index b250a34..e122754 100644
--- a/java/com/google/gerrit/server/notedb/CommentJsonMigrator.java
+++ b/java/com/google/gerrit/server/notedb/CommentJsonMigrator.java
@@ -20,6 +20,7 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.git.RefUpdateUtil;
 import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.reviewdb.client.PatchLineComment.Status;
 import com.google.gerrit.reviewdb.client.Project;
@@ -27,7 +28,6 @@
 import com.google.gerrit.reviewdb.client.RevId;
 import com.google.gerrit.server.config.AllUsersName;
 import com.google.gerrit.server.config.GerritServerIdProvider;
-import com.google.gerrit.server.update.RefUpdateUtil;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import java.io.IOException;
diff --git a/java/com/google/gerrit/server/notedb/IntBlob.java b/java/com/google/gerrit/server/notedb/IntBlob.java
new file mode 100644
index 0000000..9bac2a4
--- /dev/null
+++ b/java/com/google/gerrit/server/notedb/IntBlob.java
@@ -0,0 +1,126 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.notedb;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.base.CharMatcher;
+import com.google.common.primitives.Ints;
+import com.google.gerrit.common.Nullable;
+import com.google.gerrit.git.RefUpdateUtil;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
+import com.google.gwtorm.server.OrmException;
+import java.io.IOException;
+import java.util.Optional;
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectInserter;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.lib.ObjectReader;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevWalk;
+
+@AutoValue
+public abstract class IntBlob {
+  public static Optional<IntBlob> parse(Repository repo, String refName)
+      throws IOException, OrmException {
+    try (ObjectReader or = repo.newObjectReader()) {
+      return parse(repo, refName, or);
+    }
+  }
+
+  public static Optional<IntBlob> parse(Repository repo, String refName, RevWalk rw)
+      throws IOException, OrmException {
+    return parse(repo, refName, rw.getObjectReader());
+  }
+
+  private static Optional<IntBlob> parse(Repository repo, String refName, ObjectReader or)
+      throws IOException, OrmException {
+    Ref ref = repo.exactRef(refName);
+    if (ref == null) {
+      return Optional.empty();
+    }
+    ObjectId id = ref.getObjectId();
+    ObjectLoader ol = or.open(id, OBJ_BLOB);
+    if (ol.getType() != OBJ_BLOB) {
+      // In theory this should be thrown by open but not all implementations may do it properly
+      // (certainly InMemoryRepository doesn't).
+      throw new IncorrectObjectTypeException(id, OBJ_BLOB);
+    }
+    String str = CharMatcher.whitespace().trimFrom(new String(ol.getCachedBytes(), UTF_8));
+    Integer value = Ints.tryParse(str);
+    if (value == null) {
+      throw new OrmException("invalid value in " + refName + " blob at " + id.name());
+    }
+    return Optional.of(IntBlob.create(id, value));
+  }
+
+  public static RefUpdate tryStore(
+      Repository repo,
+      RevWalk rw,
+      Project.NameKey projectName,
+      String refName,
+      @Nullable ObjectId oldId,
+      int val,
+      GitReferenceUpdated gitRefUpdated)
+      throws IOException {
+    ObjectId newId;
+    try (ObjectInserter ins = repo.newObjectInserter()) {
+      newId = ins.insert(OBJ_BLOB, Integer.toString(val).getBytes(UTF_8));
+      ins.flush();
+    }
+    RefUpdate ru = repo.updateRef(refName);
+    if (oldId != null) {
+      ru.setExpectedOldObjectId(oldId);
+    }
+    ru.disableRefLog();
+    ru.setNewObjectId(newId);
+    ru.setForceUpdate(true); // Required for non-commitish updates.
+    RefUpdate.Result result = ru.update(rw);
+    if (refUpdated(result)) {
+      gitRefUpdated.fire(projectName, ru, null);
+    }
+    return ru;
+  }
+
+  public static void store(
+      Repository repo,
+      RevWalk rw,
+      Project.NameKey projectName,
+      String refName,
+      @Nullable ObjectId oldId,
+      int val,
+      GitReferenceUpdated gitRefUpdated)
+      throws IOException {
+    RefUpdateUtil.checkResult(tryStore(repo, rw, projectName, refName, oldId, val, gitRefUpdated));
+  }
+
+  private static boolean refUpdated(RefUpdate.Result result) {
+    return result == RefUpdate.Result.NEW || result == RefUpdate.Result.FORCED;
+  }
+
+  private static IntBlob create(ObjectId id, int value) {
+    return new AutoValue_IntBlob(id, value);
+  }
+
+  public abstract ObjectId id();
+
+  public abstract int value();
+}
diff --git a/java/com/google/gerrit/server/notedb/NoteDbUpdateManager.java b/java/com/google/gerrit/server/notedb/NoteDbUpdateManager.java
index 12448fb..046757d 100644
--- a/java/com/google/gerrit/server/notedb/NoteDbUpdateManager.java
+++ b/java/com/google/gerrit/server/notedb/NoteDbUpdateManager.java
@@ -30,6 +30,7 @@
 import com.google.common.collect.Table;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.extensions.restapi.RestModifyView;
+import com.google.gerrit.git.RefUpdateUtil;
 import com.google.gerrit.metrics.Timer1;
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.Change;
@@ -42,7 +43,6 @@
 import com.google.gerrit.server.git.InsertedObject;
 import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
 import com.google.gerrit.server.update.ChainedReceiveCommands;
-import com.google.gerrit.server.update.RefUpdateUtil;
 import com.google.gerrit.server.update.RetryingRestModifyView;
 import com.google.gwtorm.server.OrmConcurrencyException;
 import com.google.gwtorm.server.OrmException;
diff --git a/java/com/google/gerrit/server/notedb/RepoSequence.java b/java/com/google/gerrit/server/notedb/RepoSequence.java
index 4c497ac..56264e9 100644
--- a/java/com/google/gerrit/server/notedb/RepoSequence.java
+++ b/java/com/google/gerrit/server/notedb/RepoSequence.java
@@ -27,13 +27,10 @@
 import com.github.rholder.retry.StopStrategies;
 import com.github.rholder.retry.WaitStrategies;
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.CharMatcher;
-import com.google.common.base.Predicates;
 import com.google.common.base.Throwables;
 import com.google.common.collect.ImmutableList;
-import com.google.common.primitives.Ints;
 import com.google.common.util.concurrent.Runnables;
-import com.google.gerrit.common.Nullable;
+import com.google.gerrit.git.RefUpdateUtil;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.reviewdb.client.RefNames;
 import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
@@ -42,18 +39,15 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
-import org.eclipse.jgit.errors.IncorrectObjectTypeException;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectInserter;
-import org.eclipse.jgit.lib.ObjectLoader;
-import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.RefUpdate;
-import org.eclipse.jgit.lib.RefUpdate.Result;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.transport.ReceiveCommand;
@@ -75,9 +69,9 @@
   }
 
   @VisibleForTesting
-  static RetryerBuilder<RefUpdate.Result> retryerBuilder() {
-    return RetryerBuilder.<RefUpdate.Result>newBuilder()
-        .retryIfResult(Predicates.equalTo(RefUpdate.Result.LOCK_FAILURE))
+  static RetryerBuilder<RefUpdate> retryerBuilder() {
+    return RetryerBuilder.<RefUpdate>newBuilder()
+        .retryIfResult(ru -> ru != null && RefUpdate.Result.LOCK_FAILURE.equals(ru.getResult()))
         .withWaitStrategy(
             WaitStrategies.join(
                 WaitStrategies.exponentialWait(5, TimeUnit.SECONDS),
@@ -85,7 +79,7 @@
         .withStopStrategy(StopStrategies.stopAfterDelay(30, TimeUnit.SECONDS));
   }
 
-  private static final Retryer<RefUpdate.Result> RETRYER = retryerBuilder().build();
+  private static final Retryer<RefUpdate> RETRYER = retryerBuilder().build();
 
   private final GitRepositoryManager repoManager;
   private final GitReferenceUpdated gitRefUpdated;
@@ -95,7 +89,7 @@
   private final int floor;
   private final int batchSize;
   private final Runnable afterReadRef;
-  private final Retryer<RefUpdate.Result> retryer;
+  private final Retryer<RefUpdate> retryer;
 
   // Protects all non-final fields.
   private final Lock counterLock;
@@ -153,7 +147,7 @@
       Seed seed,
       int batchSize,
       Runnable afterReadRef,
-      Retryer<RefUpdate.Result> retryer) {
+      Retryer<RefUpdate> retryer) {
     this(repoManager, gitRefUpdated, projectName, name, seed, batchSize, afterReadRef, retryer, 0);
   }
 
@@ -165,7 +159,7 @@
       Seed seed,
       int batchSize,
       Runnable afterReadRef,
-      Retryer<RefUpdate.Result> retryer,
+      Retryer<RefUpdate> retryer,
       int floor) {
     this.repoManager = requireNonNull(repoManager, "repoManager");
     this.gitRefUpdated = requireNonNull(gitRefUpdated, "gitRefUpdated");
@@ -234,7 +228,7 @@
     try {
       try (Repository repo = repoManager.openRepository(projectName);
           RevWalk rw = new RevWalk(repo)) {
-        checkResult(store(repo, rw, null, val));
+        IntBlob.store(repo, rw, projectName, refName, null, val, gitRefUpdated);
         counter = limit;
       } catch (IOException e) {
         throw new OrmException(e);
@@ -250,7 +244,11 @@
       try (Repository repo = repoManager.openRepository(projectName);
           RevWalk rw = new RevWalk(repo)) {
         TryIncreaseTo attempt = new TryIncreaseTo(repo, rw, val);
-        checkResult(retryer.call(attempt));
+        RefUpdate ru = retryer.call(attempt);
+        // Null update is a sentinel meaning nothing to do.
+        if (ru != null) {
+          RefUpdateUtil.checkResult(ru);
+        }
         counter = limit;
       } catch (ExecutionException | RetryException e) {
         if (e.getCause() != null) {
@@ -269,7 +267,7 @@
     try (Repository repo = repoManager.openRepository(projectName);
         RevWalk rw = new RevWalk(repo)) {
       TryAcquire attempt = new TryAcquire(repo, rw, count);
-      checkResult(retryer.call(attempt));
+      RefUpdateUtil.checkResult(retryer.call(attempt));
       counter = attempt.next;
       limit = counter + count;
       acquireCount++;
@@ -283,17 +281,7 @@
     }
   }
 
-  private void checkResult(RefUpdate.Result result) throws OrmException {
-    if (!refUpdated(result) && result != Result.NO_CHANGE) {
-      throw new OrmException("failed to update " + refName + ": " + result);
-    }
-  }
-
-  private boolean refUpdated(RefUpdate.Result result) {
-    return result == RefUpdate.Result.NEW || result == RefUpdate.Result.FORCED;
-  }
-
-  private class TryAcquire implements Callable<RefUpdate.Result> {
+  private class TryAcquire implements Callable<RefUpdate> {
     private final Repository repo;
     private final RevWalk rw;
     private final int count;
@@ -307,23 +295,23 @@
     }
 
     @Override
-    public RefUpdate.Result call() throws Exception {
-      Ref ref = repo.exactRef(refName);
+    public RefUpdate call() throws Exception {
+      Optional<IntBlob> blob = IntBlob.parse(repo, refName, rw);
       afterReadRef.run();
       ObjectId oldId;
-      if (ref == null) {
+      if (!blob.isPresent()) {
         oldId = ObjectId.zeroId();
         next = seed.get();
       } else {
-        oldId = ref.getObjectId();
-        next = parse(rw, oldId);
+        oldId = blob.get().id();
+        next = blob.get().value();
       }
       next = Math.max(floor, next);
-      return store(repo, rw, oldId, next + count);
+      return IntBlob.tryStore(repo, rw, projectName, refName, oldId, next + count, gitRefUpdated);
     }
   }
 
-  private class TryIncreaseTo implements Callable<RefUpdate.Result> {
+  private class TryIncreaseTo implements Callable<RefUpdate> {
     private final Repository repo;
     private final RevWalk rw;
     private final int value;
@@ -335,60 +323,26 @@
     }
 
     @Override
-    public RefUpdate.Result call() throws Exception {
-      Ref ref = repo.exactRef(refName);
+    public RefUpdate call() throws Exception {
+      Optional<IntBlob> blob = IntBlob.parse(repo, refName, rw);
       afterReadRef.run();
       ObjectId oldId;
-      if (ref == null) {
+      if (!blob.isPresent()) {
         oldId = ObjectId.zeroId();
       } else {
-        oldId = ref.getObjectId();
-        int next = parse(rw, oldId);
+        oldId = blob.get().id();
+        int next = blob.get().value();
         if (next >= value) {
-          // a concurrent write updated the ref already to this or a higher value
-          return RefUpdate.Result.NO_CHANGE;
+          // A concurrent write updated the ref already to this or a higher value; return null as a
+          // sentinel meaning nothing to do. Returning RefUpdate doesn't give us the flexibility to
+          // return any other kind of sentinel, since it's a fairly thick object.
+          return null;
         }
       }
-      return store(repo, rw, oldId, value);
+      return IntBlob.tryStore(repo, rw, projectName, refName, oldId, value, gitRefUpdated);
     }
   }
 
-  private int parse(RevWalk rw, ObjectId id) throws IOException, OrmException {
-    ObjectLoader ol = rw.getObjectReader().open(id, OBJ_BLOB);
-    if (ol.getType() != OBJ_BLOB) {
-      // In theory this should be thrown by open but not all implementations
-      // may do it properly (certainly InMemoryRepository doesn't).
-      throw new IncorrectObjectTypeException(id, OBJ_BLOB);
-    }
-    String str = CharMatcher.whitespace().trimFrom(new String(ol.getCachedBytes(), UTF_8));
-    Integer val = Ints.tryParse(str);
-    if (val == null) {
-      throw new OrmException("invalid value in " + refName + " blob at " + id.name());
-    }
-    return val;
-  }
-
-  private RefUpdate.Result store(Repository repo, RevWalk rw, @Nullable ObjectId oldId, int val)
-      throws IOException {
-    ObjectId newId;
-    try (ObjectInserter ins = repo.newObjectInserter()) {
-      newId = ins.insert(OBJ_BLOB, Integer.toString(val).getBytes(UTF_8));
-      ins.flush();
-    }
-    RefUpdate ru = repo.updateRef(refName);
-    if (oldId != null) {
-      ru.setExpectedOldObjectId(oldId);
-    }
-    ru.disableRefLog();
-    ru.setNewObjectId(newId);
-    ru.setForceUpdate(true); // Required for non-commitish updates.
-    RefUpdate.Result result = ru.update(rw);
-    if (refUpdated(result)) {
-      gitRefUpdated.fire(projectName, ru, null);
-    }
-    return result;
-  }
-
   public static ReceiveCommand storeNew(ObjectInserter ins, String name, int val)
       throws IOException {
     ObjectId newId = ins.insert(OBJ_BLOB, Integer.toString(val).getBytes(UTF_8));
diff --git a/java/com/google/gerrit/server/notedb/rebuild/NoteDbMigrator.java b/java/com/google/gerrit/server/notedb/rebuild/NoteDbMigrator.java
index 225926d..01ac3e2 100644
--- a/java/com/google/gerrit/server/notedb/rebuild/NoteDbMigrator.java
+++ b/java/com/google/gerrit/server/notedb/rebuild/NoteDbMigrator.java
@@ -46,6 +46,8 @@
 import com.google.gerrit.common.FormatUtil;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.extensions.registration.DynamicSet;
+import com.google.gerrit.git.LockFailureException;
+import com.google.gerrit.git.RefUpdateUtil;
 import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.reviewdb.server.ReviewDb;
@@ -59,7 +61,6 @@
 import com.google.gerrit.server.config.SitePaths;
 import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
 import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.LockFailureException;
 import com.google.gerrit.server.git.WorkQueue;
 import com.google.gerrit.server.notedb.ChangeBundleReader;
 import com.google.gerrit.server.notedb.ChangeNotes;
@@ -73,7 +74,6 @@
 import com.google.gerrit.server.notedb.rebuild.ChangeRebuilder.NoPatchSetsException;
 import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.update.ChainedReceiveCommands;
-import com.google.gerrit.server.update.RefUpdateUtil;
 import com.google.gerrit.server.util.ManualRequestContext;
 import com.google.gerrit.server.util.ThreadLocalRequestContext;
 import com.google.gwtorm.server.OrmException;
diff --git a/java/com/google/gerrit/server/permissions/PermissionBackend.java b/java/com/google/gerrit/server/permissions/PermissionBackend.java
index db3c961..bea760c 100644
--- a/java/com/google/gerrit/server/permissions/PermissionBackend.java
+++ b/java/com/google/gerrit/server/permissions/PermissionBackend.java
@@ -18,6 +18,7 @@
 import static java.util.stream.Collectors.toSet;
 
 import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Sets;
 import com.google.common.flogger.FluentLogger;
 import com.google.gerrit.common.data.LabelType;
@@ -40,6 +41,7 @@
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
@@ -367,12 +369,19 @@
     /** Separately add reachable tags. */
     public abstract boolean filterTagsSeparately();
 
+    /**
+     * Select only refs with names matching prefixes per {@link
+     * org.eclipse.jgit.lib.RefDatabase#getRefsByPrefix}.
+     */
+    public abstract ImmutableList<String> prefixes();
+
     public abstract Builder toBuilder();
 
     public static Builder builder() {
       return new AutoValue_PermissionBackend_RefFilterOptions.Builder()
           .setFilterMeta(false)
-          .setFilterTagsSeparately(false);
+          .setFilterTagsSeparately(false)
+          .setPrefixes(Collections.singletonList(""));
     }
 
     @AutoValue.Builder
@@ -381,6 +390,8 @@
 
       public abstract Builder setFilterTagsSeparately(boolean val);
 
+      public abstract Builder setPrefixes(List<String> prefixes);
+
       public abstract RefFilterOptions build();
     }
 
diff --git a/java/com/google/gerrit/server/plugincontext/PluginSetEntryContext.java b/java/com/google/gerrit/server/plugincontext/PluginSetEntryContext.java
index afffbef..2268c07 100644
--- a/java/com/google/gerrit/server/plugincontext/PluginSetEntryContext.java
+++ b/java/com/google/gerrit/server/plugincontext/PluginSetEntryContext.java
@@ -103,8 +103,9 @@
    *
    * <p>Should only be used in exceptional cases to get direct access to the extension
    * implementation. If possible the extension should be invoked through {@link
-   * #run(ExtensionImplConsumer)}, {@link #run(ExtensionImplConsumer, Class)}, {@link
-   * #call(ExtensionImplFunction)} and {@link #call(CheckedExtensionImplFunction, Class)}.
+   * #run(PluginContext.ExtensionImplConsumer)}, {@link #run(PluginContext.ExtensionImplConsumer,
+   * java.lang.Class)}, {@link #call(PluginContext.ExtensionImplFunction)} and {@link
+   * #call(PluginContext.CheckedExtensionImplFunction, java.lang.Class)}.
    *
    * @return the implementation of this extension
    */
diff --git a/java/com/google/gerrit/server/plugins/JarScanner.java b/java/com/google/gerrit/server/plugins/JarScanner.java
index 1a9b859..486e264 100644
--- a/java/com/google/gerrit/server/plugins/JarScanner.java
+++ b/java/com/google/gerrit/server/plugins/JarScanner.java
@@ -195,7 +195,7 @@
     Collection<String> exports;
 
     private ClassData(Collection<String> exports) {
-      super(Opcodes.ASM6);
+      super(Opcodes.ASM7);
       this.exports = exports;
     }
 
@@ -263,7 +263,7 @@
 
   private abstract static class AbstractAnnotationVisitor extends AnnotationVisitor {
     AbstractAnnotationVisitor() {
-      super(Opcodes.ASM6);
+      super(Opcodes.ASM7);
     }
 
     @Override
diff --git a/java/com/google/gerrit/server/project/ContributorAgreementsChecker.java b/java/com/google/gerrit/server/project/ContributorAgreementsChecker.java
index fc342db..8912e31 100644
--- a/java/com/google/gerrit/server/project/ContributorAgreementsChecker.java
+++ b/java/com/google/gerrit/server/project/ContributorAgreementsChecker.java
@@ -14,6 +14,9 @@
 
 package com.google.gerrit.server.project;
 
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
 import com.google.gerrit.common.data.ContributorAgreement;
 import com.google.gerrit.common.data.PermissionRule;
 import com.google.gerrit.common.data.PermissionRule.Action;
@@ -34,6 +37,8 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
 
 @Singleton
 public class ContributorAgreementsChecker {
@@ -93,6 +98,20 @@
       List<AccountGroup.UUID> groupIds;
       groupIds = okGroupIds;
 
+      // matchProjects defaults to match all projects when missing.
+      List<String> matchProjectsRegexes = ca.getMatchProjectsRegexes();
+      if (!matchProjectsRegexes.isEmpty()
+          && !projectMatchesAnyPattern(project.get(), matchProjectsRegexes)) {
+        // Doesn't match, isn't checked.
+        continue;
+      }
+      // excludeProjects defaults to exclude no projects when missing.
+      List<String> excludeProjectsRegexes = ca.getExcludeProjectsRegexes();
+      if (!excludeProjectsRegexes.isEmpty()
+          && projectMatchesAnyPattern(project.get(), excludeProjectsRegexes)) {
+        // Matches, isn't checked.
+        continue;
+      }
       for (PermissionRule rule : ca.getAccepted()) {
         if ((rule.getAction() == Action.ALLOW)
             && (rule.getGroup() != null)
@@ -102,7 +121,7 @@
       }
     }
 
-    if (!iUser.getEffectiveGroups().containsAnyOf(okGroupIds)) {
+    if (!okGroupIds.isEmpty() && !iUser.getEffectiveGroups().containsAnyOf(okGroupIds)) {
       final StringBuilder msg = new StringBuilder();
       msg.append("No Contributor Agreement on file for user ")
           .append(iUser.getNameEmail())
@@ -114,4 +133,23 @@
       throw new AuthException(msg.toString());
     }
   }
+
+  private boolean projectMatchesAnyPattern(String projectName, List<String> regexes) {
+    requireNonNull(regexes);
+    checkArgument(!regexes.isEmpty());
+    for (String patternString : regexes) {
+      Pattern pattern;
+      try {
+        pattern = Pattern.compile(patternString);
+      } catch (PatternSyntaxException e) {
+        // Should never happen: Regular expressions validated when reading project.config.
+        throw new IllegalStateException(
+            "Invalid matchProjects or excludeProjects clause in project.config", e);
+      }
+      if (pattern.matcher(projectName).find()) {
+        return true;
+      }
+    }
+    return false;
+  }
 }
diff --git a/java/com/google/gerrit/server/project/CreateProjectArgs.java b/java/com/google/gerrit/server/project/CreateProjectArgs.java
index a68bd84..df31c19 100644
--- a/java/com/google/gerrit/server/project/CreateProjectArgs.java
+++ b/java/com/google/gerrit/server/project/CreateProjectArgs.java
@@ -49,6 +49,7 @@
     enableSignedPush = InheritableBoolean.INHERIT;
     requireSignedPush = InheritableBoolean.INHERIT;
     submitType = SubmitType.MERGE_IF_NECESSARY;
+    rejectEmptyCommit = InheritableBoolean.INHERIT;
   }
 
   public Project.NameKey getProject() {
diff --git a/java/com/google/gerrit/server/project/ProjectCacheImpl.java b/java/com/google/gerrit/server/project/ProjectCacheImpl.java
index aa455e6..ddeeb8a 100644
--- a/java/com/google/gerrit/server/project/ProjectCacheImpl.java
+++ b/java/com/google/gerrit/server/project/ProjectCacheImpl.java
@@ -25,6 +25,10 @@
 import com.google.common.flogger.FluentLogger;
 import com.google.gerrit.index.project.ProjectIndexer;
 import com.google.gerrit.lifecycle.LifecycleModule;
+import com.google.gerrit.metrics.Description;
+import com.google.gerrit.metrics.Description.Units;
+import com.google.gerrit.metrics.MetricMaker;
+import com.google.gerrit.metrics.Timer0;
 import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.cache.CacheModule;
@@ -89,6 +93,7 @@
   private final Lock listLock;
   private final ProjectCacheClock clock;
   private final Provider<ProjectIndexer> indexer;
+  private final Timer0 guessRelevantGroupsLatency;
 
   @Inject
   ProjectCacheImpl(
@@ -97,7 +102,8 @@
       @Named(CACHE_NAME) LoadingCache<String, ProjectState> byName,
       @Named(CACHE_LIST) LoadingCache<ListKey, ImmutableSortedSet<Project.NameKey>> list,
       ProjectCacheClock clock,
-      Provider<ProjectIndexer> indexer) {
+      Provider<ProjectIndexer> indexer,
+      MetricMaker metricMaker) {
     this.allProjectsName = allProjectsName;
     this.allUsersName = allUsersName;
     this.byName = byName;
@@ -105,6 +111,13 @@
     this.listLock = new ReentrantLock(true /* fair */);
     this.clock = clock;
     this.indexer = indexer;
+
+    this.guessRelevantGroupsLatency =
+        metricMaker.newTimer(
+            "group/guess_relevant_groups_latency",
+            new Description("Latency for guessing relevant groups")
+                .setCumulative()
+                .setUnit(Units.NANOSECONDS));
   }
 
   @Override
@@ -234,15 +247,17 @@
 
   @Override
   public Set<AccountGroup.UUID> guessRelevantGroupUUIDs() {
-    return all()
-        .stream()
-        .map(n -> byName.getIfPresent(n.get()))
-        .filter(Objects::nonNull)
-        .flatMap(p -> p.getConfig().getAllGroupUUIDs().stream())
-        // getAllGroupUUIDs shouldn't really return null UUIDs, but harden
-        // against them just in case there is a bug or corner case.
-        .filter(id -> id != null && id.get() != null)
-        .collect(toSet());
+    try (Timer0.Context ignored = guessRelevantGroupsLatency.start()) {
+      return all()
+          .stream()
+          .map(n -> byName.getIfPresent(n.get()))
+          .filter(Objects::nonNull)
+          .flatMap(p -> p.getConfig().getAllGroupUUIDs().stream())
+          // getAllGroupUUIDs shouldn't really return null UUIDs, but harden
+          // against them just in case there is a bug or corner case.
+          .filter(id -> id != null && id.get() != null)
+          .collect(toSet());
+    }
   }
 
   @Override
@@ -262,12 +277,18 @@
     private final ProjectState.Factory projectStateFactory;
     private final GitRepositoryManager mgr;
     private final ProjectCacheClock clock;
+    private final ProjectConfig.Factory projectConfigFactory;
 
     @Inject
-    Loader(ProjectState.Factory psf, GitRepositoryManager g, ProjectCacheClock clock) {
+    Loader(
+        ProjectState.Factory psf,
+        GitRepositoryManager g,
+        ProjectCacheClock clock,
+        ProjectConfig.Factory projectConfigFactory) {
       projectStateFactory = psf;
       mgr = g;
       this.clock = clock;
+      this.projectConfigFactory = projectConfigFactory;
     }
 
     @Override
@@ -276,7 +297,7 @@
         long now = clock.read();
         Project.NameKey key = new Project.NameKey(projectName);
         try (Repository git = mgr.openRepository(key)) {
-          ProjectConfig cfg = new ProjectConfig(key);
+          ProjectConfig cfg = projectConfigFactory.create(key);
           cfg.load(key, git);
 
           ProjectState state = projectStateFactory.create(cfg);
diff --git a/java/com/google/gerrit/server/project/ProjectConfig.java b/java/com/google/gerrit/server/project/ProjectConfig.java
index bccc415..74c0f3b 100644
--- a/java/com/google/gerrit/server/project/ProjectConfig.java
+++ b/java/com/google/gerrit/server/project/ProjectConfig.java
@@ -59,6 +59,7 @@
 import com.google.gerrit.server.git.ValidationError;
 import com.google.gerrit.server.git.meta.MetaDataUpdate;
 import com.google.gerrit.server.git.meta.VersionedMetaData;
+import com.google.inject.Singleton;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -127,6 +128,8 @@
   private static final String KEY_ACCEPTED = "accepted";
   private static final String KEY_AUTO_VERIFY = "autoVerify";
   private static final String KEY_AGREEMENT_URL = "agreementUrl";
+  private static final String KEY_MATCH_PROJECTS = "matchProjects";
+  private static final String KEY_EXCLUDE_PROJECTS = "excludeProjects";
 
   private static final String NOTIFY = "notify";
   private static final String KEY_EMAIL = "email";
@@ -165,6 +168,29 @@
 
   private static final Pattern EXCLUSIVE_PERMISSIONS_SPLIT_PATTERN = Pattern.compile("[, \t]{1,}");
 
+  // Don't use an assisted factory, since instances created by an assisted factory retain references
+  // to their enclosing injector. Instances of ProjectConfig are cached for a long time in the
+  // ProjectCache, so this would retain lots more memory.
+  @Singleton
+  public static class Factory {
+    public ProjectConfig create(Project.NameKey projectName) {
+      return new ProjectConfig(projectName);
+    }
+
+    public ProjectConfig read(MetaDataUpdate update) throws IOException, ConfigInvalidException {
+      ProjectConfig r = create(update.getProjectName());
+      r.load(update);
+      return r;
+    }
+
+    public ProjectConfig read(MetaDataUpdate update, ObjectId id)
+        throws IOException, ConfigInvalidException {
+      ProjectConfig r = create(update.getProjectName());
+      r.load(update, id);
+      return r;
+    }
+  }
+
   private Project project;
   private AccountsSection accountsSection;
   private GroupList groupList;
@@ -186,20 +212,6 @@
   private Map<String, List<String>> extensionPanelSections;
   private Map<String, GroupReference> groupsByName;
 
-  public static ProjectConfig read(MetaDataUpdate update)
-      throws IOException, ConfigInvalidException {
-    ProjectConfig r = new ProjectConfig(update.getProjectName());
-    r.load(update);
-    return r;
-  }
-
-  public static ProjectConfig read(MetaDataUpdate update, ObjectId id)
-      throws IOException, ConfigInvalidException {
-    ProjectConfig r = new ProjectConfig(update.getProjectName());
-    r.load(update, id);
-    return r;
-  }
-
   public static CommentLinkInfoImpl buildCommentLink(Config cfg, String name, boolean allowRaw)
       throws IllegalArgumentException {
     String match = cfg.getString(COMMENTLINK, name, KEY_MATCH);
@@ -241,7 +253,7 @@
     commentLinkSections.add(commentLink);
   }
 
-  public ProjectConfig(Project.NameKey projectName) {
+  private ProjectConfig(Project.NameKey projectName) {
     this.projectName = projectName;
   }
 
@@ -593,6 +605,9 @@
       ca.setAgreementUrl(rc.getString(CONTRIBUTOR_AGREEMENT, name, KEY_AGREEMENT_URL));
       ca.setAccepted(
           loadPermissionRules(rc, CONTRIBUTOR_AGREEMENT, name, KEY_ACCEPTED, groupsByName, false));
+      ca.setExcludeProjectsRegexes(
+          loadPatterns(rc, CONTRIBUTOR_AGREEMENT, name, KEY_EXCLUDE_PROJECTS));
+      ca.setMatchProjectsRegexes(loadPatterns(rc, CONTRIBUTOR_AGREEMENT, name, KEY_MATCH_PROJECTS));
 
       List<PermissionRule> rules =
           loadPermissionRules(
@@ -753,6 +768,22 @@
     }
   }
 
+  private ImmutableList<String> loadPatterns(
+      Config rc, String section, String subsection, String varName) {
+    ImmutableList.Builder<String> patterns = ImmutableList.builder();
+    for (String patternString : rc.getStringList(section, subsection, varName)) {
+      try {
+        // While one could just use getStringList directly, compiling first will cause the server
+        // to fail fast if any of the patterns are invalid.
+        patterns.add(Pattern.compile(patternString).pattern());
+      } catch (PatternSyntaxException e) {
+        error(new ValidationError(PROJECT_CONFIG, "Invalid regular expression: " + e.getMessage()));
+        continue;
+      }
+    }
+    return patterns.build();
+  }
+
   private ImmutableList<PermissionRule> loadPermissionRules(
       Config rc,
       String section,
@@ -1163,6 +1194,16 @@
           ca.getName(),
           KEY_ACCEPTED,
           ruleToStringList(ca.getAccepted(), keepGroups));
+      rc.setStringList(
+          CONTRIBUTOR_AGREEMENT,
+          ca.getName(),
+          KEY_EXCLUDE_PROJECTS,
+          patternToStringList(ca.getExcludeProjectsRegexes()));
+      rc.setStringList(
+          CONTRIBUTOR_AGREEMENT,
+          ca.getName(),
+          KEY_MATCH_PROJECTS,
+          patternToStringList(ca.getMatchProjectsRegexes()));
     }
   }
 
@@ -1206,6 +1247,10 @@
     }
   }
 
+  private List<String> patternToStringList(List<String> list) {
+    return list;
+  }
+
   private List<String> ruleToStringList(
       List<PermissionRule> list, Set<AccountGroup.UUID> keepGroups) {
     List<String> rules = new ArrayList<>();
diff --git a/java/com/google/gerrit/server/project/SectionMatcher.java b/java/com/google/gerrit/server/project/SectionMatcher.java
index 11b1f37..3095f2f 100644
--- a/java/com/google/gerrit/server/project/SectionMatcher.java
+++ b/java/com/google/gerrit/server/project/SectionMatcher.java
@@ -16,7 +16,6 @@
 
 import com.google.gerrit.common.data.AccessSection;
 import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.client.Project.NameKey;
 import com.google.gerrit.server.CurrentUser;
 
 /**
@@ -57,7 +56,7 @@
     return matcher;
   }
 
-  public NameKey getProject() {
+  public Project.NameKey getProject() {
     return project;
   }
 }
diff --git a/java/com/google/gerrit/server/query/change/ChangeData.java b/java/com/google/gerrit/server/query/change/ChangeData.java
index 83d68db..0f5d938 100644
--- a/java/com/google/gerrit/server/query/change/ChangeData.java
+++ b/java/com/google/gerrit/server/query/change/ChangeData.java
@@ -30,6 +30,7 @@
 import com.google.common.collect.ListMultimap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import com.google.common.primitives.Ints;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.common.data.LabelTypes;
 import com.google.gerrit.common.data.SubmitRecord;
@@ -391,6 +392,7 @@
   private PersonIdent committer;
   private int parentCount;
   private Integer unresolvedCommentCount;
+  private Integer totalCommentCount;
   private LabelTypes labelTypes;
 
   private ImmutableList<byte[]> refStates;
@@ -925,6 +927,23 @@
     this.unresolvedCommentCount = count;
   }
 
+  public Integer totalCommentCount() throws OrmException {
+    if (totalCommentCount == null) {
+      if (!lazyLoad) {
+        return null;
+      }
+
+      // Fail on overflow.
+      totalCommentCount =
+          Ints.checkedCast((long) publishedComments().size() + robotComments().size());
+    }
+    return totalCommentCount;
+  }
+
+  public void setTotalCommentCount(Integer count) {
+    this.totalCommentCount = count;
+  }
+
   public List<ChangeMessage> messages() throws OrmException {
     if (messages == null) {
       if (!lazyLoad) {
diff --git a/java/com/google/gerrit/server/query/change/ChangeIsVisibleToPredicate.java b/java/com/google/gerrit/server/query/change/ChangeIsVisibleToPredicate.java
index f81ea15..d682b93 100644
--- a/java/com/google/gerrit/server/query/change/ChangeIsVisibleToPredicate.java
+++ b/java/com/google/gerrit/server/query/change/ChangeIsVisibleToPredicate.java
@@ -29,6 +29,7 @@
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.project.ProjectState;
 import com.google.gwtorm.server.OrmException;
+import com.google.inject.Inject;
 import com.google.inject.Provider;
 import java.io.IOException;
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
@@ -43,6 +44,7 @@
   protected final ProjectCache projectCache;
   private final Provider<AnonymousUser> anonymousUserProvider;
 
+  @Inject
   public ChangeIsVisibleToPredicate(
       Provider<ReviewDb> db,
       ChangeNotes.Factory notesFactory,
diff --git a/java/com/google/gerrit/server/restapi/change/ChangesCollection.java b/java/com/google/gerrit/server/restapi/change/ChangesCollection.java
index 561c27c..30d93be 100644
--- a/java/com/google/gerrit/server/restapi/change/ChangesCollection.java
+++ b/java/com/google/gerrit/server/restapi/change/ChangesCollection.java
@@ -17,6 +17,7 @@
 import com.google.gerrit.extensions.registration.DynamicMap;
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.IdString;
+import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.extensions.restapi.RestCollection;
@@ -101,7 +102,8 @@
   }
 
   public ChangeResource parse(Change.Id id)
-      throws RestApiException, OrmException, PermissionBackendException, IOException {
+      throws ResourceConflictException, ResourceNotFoundException, OrmException,
+          PermissionBackendException, IOException {
     List<ChangeNotes> notes = changeFinder.find(id);
     if (notes.isEmpty()) {
       throw new ResourceNotFoundException(toIdString(id));
@@ -139,7 +141,7 @@
   }
 
   private void checkProjectStatePermitsRead(Project.NameKey project)
-      throws IOException, RestApiException {
+      throws IOException, ResourceNotFoundException, ResourceConflictException {
     ProjectState projectState = projectCache.checkedGet(project);
     if (projectState == null) {
       throw new ResourceNotFoundException("project not found: " + project.get());
diff --git a/java/com/google/gerrit/server/restapi/change/Files.java b/java/com/google/gerrit/server/restapi/change/Files.java
index 1bb6bf2..b374fdc 100644
--- a/java/com/google/gerrit/server/restapi/change/Files.java
+++ b/java/com/google/gerrit/server/restapi/change/Files.java
@@ -18,6 +18,7 @@
 import com.google.common.flogger.FluentLogger;
 import com.google.common.hash.Hasher;
 import com.google.common.hash.Hashing;
+import com.google.gerrit.common.Nullable;
 import com.google.gerrit.extensions.common.FileInfo;
 import com.google.gerrit.extensions.registration.DynamicMap;
 import com.google.gerrit.extensions.restapi.AuthException;
@@ -332,7 +333,7 @@
       return this;
     }
 
-    public ListFiles setBase(String base) {
+    public ListFiles setBase(@Nullable String base) {
       this.base = base;
       return this;
     }
diff --git a/java/com/google/gerrit/server/restapi/change/GetRelated.java b/java/com/google/gerrit/server/restapi/change/GetRelated.java
index 3313136..30fbf39 100644
--- a/java/com/google/gerrit/server/restapi/change/GetRelated.java
+++ b/java/com/google/gerrit/server/restapi/change/GetRelated.java
@@ -17,9 +17,10 @@
 import static java.util.stream.Collectors.toSet;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.MoreObjects;
 import com.google.common.collect.Lists;
 import com.google.gerrit.common.Nullable;
+import com.google.gerrit.extensions.api.changes.RelatedChangeAndCommitInfo;
+import com.google.gerrit.extensions.api.changes.RelatedChangesInfo;
 import com.google.gerrit.extensions.common.CommitInfo;
 import com.google.gerrit.extensions.restapi.RestReadView;
 import com.google.gerrit.index.IndexConfig;
@@ -70,15 +71,15 @@
   }
 
   @Override
-  public RelatedInfo apply(RevisionResource rsrc)
+  public RelatedChangesInfo apply(RevisionResource rsrc)
       throws RepositoryNotFoundException, IOException, OrmException, NoSuchProjectException,
           PermissionBackendException {
-    RelatedInfo relatedInfo = new RelatedInfo();
-    relatedInfo.changes = getRelated(rsrc);
-    return relatedInfo;
+    RelatedChangesInfo relatedChangesInfo = new RelatedChangesInfo();
+    relatedChangesInfo.changes = getRelated(rsrc);
+    return relatedChangesInfo;
   }
 
-  private List<ChangeAndCommit> getRelated(RevisionResource rsrc)
+  private List<RelatedChangeAndCommitInfo> getRelated(RevisionResource rsrc)
       throws OrmException, IOException, PermissionBackendException {
     Set<String> groups = getAllGroups(rsrc.getNotes(), db.get(), psUtil);
     if (groups.isEmpty()) {
@@ -94,7 +95,7 @@
     if (cds.size() == 1 && cds.get(0).getId().equals(rsrc.getChange().getId())) {
       return Collections.emptyList();
     }
-    List<ChangeAndCommit> result = new ArrayList<>(cds.size());
+    List<RelatedChangeAndCommitInfo> result = new ArrayList<>(cds.size());
 
     boolean isEdit = rsrc.getEdit().isPresent();
     PatchSet basePs = isEdit ? rsrc.getEdit().get().getBasePatchSet() : rsrc.getPatchSet();
@@ -111,11 +112,11 @@
       } else {
         commit = d.commit();
       }
-      result.add(new ChangeAndCommit(rsrc.getProject(), d.data().change(), ps, commit));
+      result.add(newChangeAndCommit(rsrc.getProject(), d.data().change(), ps, commit));
     }
 
     if (result.size() == 1) {
-      ChangeAndCommit r = result.get(0);
+      RelatedChangeAndCommitInfo r = result.get(0);
       if (r.commit != null && r.commit.commit.equals(rsrc.getPatchSet().getRevision().get())) {
         return Collections.emptyList();
       }
@@ -143,69 +144,30 @@
     }
   }
 
-  public static class RelatedInfo {
-    public List<ChangeAndCommit> changes;
-  }
+  static RelatedChangeAndCommitInfo newChangeAndCommit(
+      Project.NameKey project, @Nullable Change change, @Nullable PatchSet ps, RevCommit c) {
+    RelatedChangeAndCommitInfo info = new RelatedChangeAndCommitInfo();
+    info.project = project.get();
 
-  public static class ChangeAndCommit {
-    public String project;
-    public String changeId;
-    public CommitInfo commit;
-    public Integer _changeNumber;
-    public Integer _revisionNumber;
-    public Integer _currentRevisionNumber;
-    public String status;
-
-    public ChangeAndCommit() {}
-
-    ChangeAndCommit(
-        Project.NameKey project, @Nullable Change change, @Nullable PatchSet ps, RevCommit c) {
-      this.project = project.get();
-
-      if (change != null) {
-        changeId = change.getKey().get();
-        _changeNumber = change.getChangeId();
-        _revisionNumber = ps != null ? ps.getPatchSetId() : null;
-        PatchSet.Id curr = change.currentPatchSetId();
-        _currentRevisionNumber = curr != null ? curr.get() : null;
-        status = change.getStatus().asChangeStatus().toString();
-      }
-
-      commit = new CommitInfo();
-      commit.commit = c.name();
-      commit.parents = Lists.newArrayListWithCapacity(c.getParentCount());
-      for (int i = 0; i < c.getParentCount(); i++) {
-        CommitInfo p = new CommitInfo();
-        p.commit = c.getParent(i).name();
-        commit.parents.add(p);
-      }
-      commit.author = CommonConverters.toGitPerson(c.getAuthorIdent());
-      commit.subject = c.getShortMessage();
+    if (change != null) {
+      info.changeId = change.getKey().get();
+      info._changeNumber = change.getChangeId();
+      info._revisionNumber = ps != null ? ps.getPatchSetId() : null;
+      PatchSet.Id curr = change.currentPatchSetId();
+      info._currentRevisionNumber = curr != null ? curr.get() : null;
+      info.status = change.getStatus().asChangeStatus().toString();
     }
 
-    @Override
-    public String toString() {
-      return MoreObjects.toStringHelper(this)
-          .add("project", project)
-          .add("changeId", changeId)
-          .add("commit", toString(commit))
-          .add("_changeNumber", _changeNumber)
-          .add("_revisionNumber", _revisionNumber)
-          .add("_currentRevisionNumber", _currentRevisionNumber)
-          .add("status", status)
-          .toString();
+    info.commit = new CommitInfo();
+    info.commit.commit = c.name();
+    info.commit.parents = Lists.newArrayListWithCapacity(c.getParentCount());
+    for (int i = 0; i < c.getParentCount(); i++) {
+      CommitInfo p = new CommitInfo();
+      p.commit = c.getParent(i).name();
+      info.commit.parents.add(p);
     }
-
-    private static String toString(CommitInfo commit) {
-      return MoreObjects.toStringHelper(commit)
-          .add("commit", commit.commit)
-          .add("parent", commit.parents)
-          .add("author", commit.author)
-          .add("committer", commit.committer)
-          .add("subject", commit.subject)
-          .add("message", commit.message)
-          .add("webLinks", commit.webLinks)
-          .toString();
-    }
+    info.commit.author = CommonConverters.toGitPerson(c.getAuthorIdent());
+    info.commit.subject = c.getShortMessage();
+    return info;
   }
 }
diff --git a/java/com/google/gerrit/server/restapi/change/Move.java b/java/com/google/gerrit/server/restapi/change/Move.java
index 013d3e9..df1d9b9 100644
--- a/java/com/google/gerrit/server/restapi/change/Move.java
+++ b/java/com/google/gerrit/server/restapi/change/Move.java
@@ -27,6 +27,7 @@
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.BadRequestException;
+import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.extensions.webui.UiAction;
@@ -47,6 +48,7 @@
 import com.google.gerrit.server.PatchSetUtil;
 import com.google.gerrit.server.change.ChangeJson;
 import com.google.gerrit.server.change.ChangeResource;
+import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.notedb.ChangeUpdate;
 import com.google.gerrit.server.permissions.PermissionBackend;
@@ -68,6 +70,7 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.revwalk.RevCommit;
@@ -87,6 +90,7 @@
   private final PatchSetUtil psUtil;
   private final ApprovalsUtil approvalsUtil;
   private final ProjectCache projectCache;
+  private final boolean moveEnabled;
 
   @Inject
   Move(
@@ -99,7 +103,8 @@
       RetryHelper retryHelper,
       PatchSetUtil psUtil,
       ApprovalsUtil approvalsUtil,
-      ProjectCache projectCache) {
+      ProjectCache projectCache,
+      @GerritServerConfig Config gerritConfig) {
     super(retryHelper);
     this.permissionBackend = permissionBackend;
     this.dbProvider = dbProvider;
@@ -110,6 +115,7 @@
     this.psUtil = psUtil;
     this.approvalsUtil = approvalsUtil;
     this.projectCache = projectCache;
+    this.moveEnabled = gerritConfig.getBoolean("change", null, "move", true);
   }
 
   @Override
@@ -117,6 +123,12 @@
       BatchUpdate.Factory updateFactory, ChangeResource rsrc, MoveInput input)
       throws RestApiException, OrmException, UpdateException, PermissionBackendException,
           IOException {
+    if (!moveEnabled) {
+      // This will be removed with the above config once we reach consensus for the move change
+      // behavior. See: https://bugs.chromium.org/p/gerrit/issues/detail?id=9877
+      throw new MethodNotAllowedException("move changes endpoint is disabled");
+    }
+
     Change change = rsrc.getChange();
     Project.NameKey project = rsrc.getProject();
     IdentifiedUser caller = rsrc.getUser().asIdentifiedUser();
diff --git a/java/com/google/gerrit/server/restapi/change/Rebase.java b/java/com/google/gerrit/server/restapi/change/Rebase.java
index 2e2f565..eed0896 100644
--- a/java/com/google/gerrit/server/restapi/change/Rebase.java
+++ b/java/com/google/gerrit/server/restapi/change/Rebase.java
@@ -161,7 +161,8 @@
 
     Base base = rebaseUtil.parseBase(rsrc, str);
     if (base == null) {
-      throw new ResourceConflictException("base revision is missing: " + str);
+      throw new ResourceConflictException(
+          "base revision is missing from the destination branch: " + str);
     }
     PatchSet.Id baseId = base.patchSet().getId();
     if (change.getId().equals(baseId.getParentKey())) {
diff --git a/java/com/google/gerrit/server/restapi/config/GetServerInfo.java b/java/com/google/gerrit/server/restapi/config/GetServerInfo.java
index 6f44a1c..963a1b4 100644
--- a/java/com/google/gerrit/server/restapi/config/GetServerInfo.java
+++ b/java/com/google/gerrit/server/restapi/config/GetServerInfo.java
@@ -49,7 +49,6 @@
 import com.google.gerrit.server.config.AuthConfig;
 import com.google.gerrit.server.config.ConfigResource;
 import com.google.gerrit.server.config.ConfigUtil;
-import com.google.gerrit.server.config.GerritOptions;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.SitePaths;
 import com.google.gerrit.server.documentation.QueryDocumentationExecutor;
@@ -97,7 +96,6 @@
   private final NotesMigration migration;
   private final ProjectCache projectCache;
   private final AgreementJson agreementJson;
-  private final GerritOptions gerritOptions;
   private final ChangeIndexCollection indexes;
   private final SitePaths sitePaths;
 
@@ -121,7 +119,6 @@
       NotesMigration migration,
       ProjectCache projectCache,
       AgreementJson agreementJson,
-      GerritOptions gerritOptions,
       ChangeIndexCollection indexes,
       SitePaths sitePaths) {
     this.config = config;
@@ -142,7 +139,6 @@
     this.migration = migration;
     this.projectCache = projectCache;
     this.agreementJson = agreementJson;
-    this.gerritOptions = gerritOptions;
     this.indexes = indexes;
     this.sitePaths = sitePaths;
   }
@@ -309,10 +305,6 @@
     info.editGpgKeys =
         toBoolean(enableSignedPush && config.getBoolean("gerrit", null, "editGpgKeys", true));
     info.webUis = EnumSet.noneOf(UiType.class);
-    info.webUis.add(UiType.POLYGERRIT);
-    if (gerritOptions.enableGwtUi()) {
-      info.webUis.add(UiType.GWT);
-    }
     return info;
   }
 
diff --git a/java/com/google/gerrit/server/restapi/project/CreateAccessChange.java b/java/com/google/gerrit/server/restapi/project/CreateAccessChange.java
index feb37c0..f679610 100644
--- a/java/com/google/gerrit/server/restapi/project/CreateAccessChange.java
+++ b/java/com/google/gerrit/server/restapi/project/CreateAccessChange.java
@@ -68,6 +68,7 @@
   private final SetAccessUtil setAccess;
   private final ChangeJson.Factory jsonFactory;
   private final ProjectCache projectCache;
+  private final ProjectConfig.Factory projectConfigFactory;
 
   @Inject
   CreateAccessChange(
@@ -79,7 +80,8 @@
       Provider<ReviewDb> db,
       SetAccessUtil accessUtil,
       ChangeJson.Factory jsonFactory,
-      ProjectCache projectCache) {
+      ProjectCache projectCache,
+      ProjectConfig.Factory projectConfigFactory) {
     this.permissionBackend = permissionBackend;
     this.seq = seq;
     this.changeInserterFactory = changeInserterFactory;
@@ -89,6 +91,7 @@
     this.setAccess = accessUtil;
     this.jsonFactory = jsonFactory;
     this.projectCache = projectCache;
+    this.projectConfigFactory = projectConfigFactory;
   }
 
   @Override
@@ -117,7 +120,7 @@
         input.parent == null ? null : new Project.NameKey(input.parent);
 
     try (MetaDataUpdate md = metaDataUpdateUser.create(rsrc.getNameKey())) {
-      ProjectConfig config = ProjectConfig.read(md);
+      ProjectConfig config = projectConfigFactory.read(md);
       ObjectId oldCommit = config.getRevision();
       String oldCommitSha1 = oldCommit == null ? null : oldCommit.getName();
 
diff --git a/java/com/google/gerrit/server/restapi/project/CreateProject.java b/java/com/google/gerrit/server/restapi/project/CreateProject.java
index 5620370..60a24d8 100644
--- a/java/com/google/gerrit/server/restapi/project/CreateProject.java
+++ b/java/com/google/gerrit/server/restapi/project/CreateProject.java
@@ -109,12 +109,13 @@
   private final MetaDataUpdate.User metaDataUpdateFactory;
   private final GitReferenceUpdated referenceUpdated;
   private final RepositoryConfig repositoryCfg;
-  private final PersonIdent serverIdent;
+  private final Provider<PersonIdent> serverIdent;
   private final Provider<IdentifiedUser> identifiedUser;
   private final Provider<PutConfig> putConfig;
   private final AllProjectsName allProjects;
   private final AllUsersName allUsers;
   private final PluginItemContext<ProjectNameLockManager> lockManager;
+  private final ProjectConfig.Factory projectConfigFactory;
 
   @Inject
   CreateProject(
@@ -130,12 +131,13 @@
       MetaDataUpdate.User metaDataUpdateFactory,
       GitReferenceUpdated referenceUpdated,
       RepositoryConfig repositoryCfg,
-      @GerritPersonIdent PersonIdent serverIdent,
+      @GerritPersonIdent Provider<PersonIdent> serverIdent,
       Provider<IdentifiedUser> identifiedUser,
       Provider<PutConfig> putConfig,
       AllProjectsName allProjects,
       AllUsersName allUsers,
-      PluginItemContext<ProjectNameLockManager> lockManager) {
+      PluginItemContext<ProjectNameLockManager> lockManager,
+      ProjectConfig.Factory projectConfigFactory) {
     this.projectsCollection = projectsCollection;
     this.groupResolver = groupResolver;
     this.projectCreationValidationListeners = projectCreationValidationListeners;
@@ -154,6 +156,7 @@
     this.allProjects = allProjects;
     this.allUsers = allUsers;
     this.lockManager = lockManager;
+    this.projectConfigFactory = projectConfigFactory;
   }
 
   @Override
@@ -286,7 +289,7 @@
   private void createProjectConfig(CreateProjectArgs args)
       throws IOException, ConfigInvalidException {
     try (MetaDataUpdate md = metaDataUpdateFactory.create(args.getProject())) {
-      ProjectConfig config = ProjectConfig.read(md);
+      ProjectConfig config = projectConfigFactory.read(md);
 
       Project newProject = config.getProject();
       newProject.setDescription(args.projectDescription);
@@ -354,7 +357,7 @@
       CommitBuilder cb = new CommitBuilder();
       cb.setTreeId(oi.insert(Constants.OBJ_TREE, new byte[] {}));
       cb.setAuthor(metaDataUpdateFactory.getUserPersonIdent());
-      cb.setCommitter(serverIdent);
+      cb.setCommitter(serverIdent.get());
       cb.setMessage("Initial empty repository\n");
 
       ObjectId id = oi.insert(cb);
diff --git a/java/com/google/gerrit/server/restapi/project/GetAccess.java b/java/com/google/gerrit/server/restapi/project/GetAccess.java
index a6b9404..8875d40 100644
--- a/java/com/google/gerrit/server/restapi/project/GetAccess.java
+++ b/java/com/google/gerrit/server/restapi/project/GetAccess.java
@@ -95,6 +95,7 @@
   private final MetaDataUpdate.Server metaDataUpdateFactory;
   private final GroupBackend groupBackend;
   private final WebLinks webLinks;
+  private final ProjectConfig.Factory projectConfigFactory;
 
   @Inject
   public GetAccess(
@@ -105,7 +106,8 @@
       MetaDataUpdate.Server metaDataUpdateFactory,
       ProjectJson projectJson,
       GroupBackend groupBackend,
-      WebLinks webLinks) {
+      WebLinks webLinks,
+      ProjectConfig.Factory projectConfigFactory) {
     this.user = self;
     this.permissionBackend = permissionBackend;
     this.allProjectsName = allProjectsName;
@@ -114,6 +116,7 @@
     this.metaDataUpdateFactory = metaDataUpdateFactory;
     this.groupBackend = groupBackend;
     this.webLinks = webLinks;
+    this.projectConfigFactory = projectConfigFactory;
   }
 
   public ProjectAccessInfo apply(Project.NameKey nameKey)
@@ -141,7 +144,7 @@
 
     ProjectConfig config;
     try (MetaDataUpdate md = metaDataUpdateFactory.create(projectName)) {
-      config = ProjectConfig.read(md);
+      config = projectConfigFactory.read(md);
       info.configWebLinks = new ArrayList<>();
 
       // config may have a null revision if the repo doesn't have its own refs/meta/config.
diff --git a/java/com/google/gerrit/server/restapi/project/Module.java b/java/com/google/gerrit/server/restapi/project/Module.java
index 8c8ab49..de5661d 100644
--- a/java/com/google/gerrit/server/restapi/project/Module.java
+++ b/java/com/google/gerrit/server/restapi/project/Module.java
@@ -55,7 +55,6 @@
     get(PROJECT_KIND, "access").to(GetAccess.class);
     post(PROJECT_KIND, "access").to(SetAccess.class);
     put(PROJECT_KIND, "access:review").to(CreateAccessChange.class);
-    post(PROJECT_KIND, "check.access").to(CheckAccess.class);
     get(PROJECT_KIND, "check.access").to(CheckAccessReadView.class);
 
     post(PROJECT_KIND, "check").to(Check.class);
diff --git a/java/com/google/gerrit/server/restapi/project/PutConfig.java b/java/com/google/gerrit/server/restapi/project/PutConfig.java
index 76ea0c9..921a591 100644
--- a/java/com/google/gerrit/server/restapi/project/PutConfig.java
+++ b/java/com/google/gerrit/server/restapi/project/PutConfig.java
@@ -47,6 +47,7 @@
 import com.google.gerrit.server.project.ProjectConfig;
 import com.google.gerrit.server.project.ProjectResource;
 import com.google.gerrit.server.project.ProjectState;
+import com.google.gerrit.server.project.ProjectState.Factory;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
@@ -77,20 +78,22 @@
   private final DynamicMap<RestView<ProjectResource>> views;
   private final Provider<CurrentUser> user;
   private final PermissionBackend permissionBackend;
+  private final ProjectConfig.Factory projectConfigFactory;
 
   @Inject
   PutConfig(
       @EnableSignedPush boolean serverEnableSignedPush,
       Provider<MetaDataUpdate.User> metaDataUpdateFactory,
       ProjectCache projectCache,
-      ProjectState.Factory projectStateFactory,
+      Factory projectStateFactory,
       DynamicMap<ProjectConfigEntry> pluginConfigEntries,
       PluginConfigFactory cfgFactory,
       AllProjectsName allProjects,
       UiActions uiActions,
       DynamicMap<RestView<ProjectResource>> views,
       Provider<CurrentUser> user,
-      PermissionBackend permissionBackend) {
+      PermissionBackend permissionBackend,
+      ProjectConfig.Factory projectConfigFactory) {
     this.serverEnableSignedPush = serverEnableSignedPush;
     this.metaDataUpdateFactory = metaDataUpdateFactory;
     this.projectCache = projectCache;
@@ -102,6 +105,7 @@
     this.views = views;
     this.user = user;
     this.permissionBackend = permissionBackend;
+    this.projectConfigFactory = projectConfigFactory;
   }
 
   @Override
@@ -122,7 +126,7 @@
     }
 
     try (MetaDataUpdate md = metaDataUpdateFactory.get().create(projectName)) {
-      ProjectConfig projectConfig = ProjectConfig.read(md);
+      ProjectConfig projectConfig = projectConfigFactory.read(md);
       Project p = projectConfig.getProject();
 
       p.setDescription(Strings.emptyToNull(input.description));
@@ -164,7 +168,7 @@
         throw new ResourceConflictException("Cannot update " + projectName);
       }
 
-      ProjectState state = projectStateFactory.create(ProjectConfig.read(md));
+      ProjectState state = projectStateFactory.create(projectConfigFactory.read(md));
       return new ConfigInfoImpl(
           serverEnableSignedPush,
           state,
diff --git a/java/com/google/gerrit/server/restapi/project/PutDescription.java b/java/com/google/gerrit/server/restapi/project/PutDescription.java
index 1c74021..081669a 100644
--- a/java/com/google/gerrit/server/restapi/project/PutDescription.java
+++ b/java/com/google/gerrit/server/restapi/project/PutDescription.java
@@ -42,15 +42,18 @@
   private final ProjectCache cache;
   private final MetaDataUpdate.Server updateFactory;
   private final PermissionBackend permissionBackend;
+  private final ProjectConfig.Factory projectConfigFactory;
 
   @Inject
   PutDescription(
       ProjectCache cache,
       MetaDataUpdate.Server updateFactory,
-      PermissionBackend permissionBackend) {
+      PermissionBackend permissionBackend,
+      ProjectConfig.Factory projectConfigFactory) {
     this.cache = cache;
     this.updateFactory = updateFactory;
     this.permissionBackend = permissionBackend;
+    this.projectConfigFactory = projectConfigFactory;
   }
 
   @Override
@@ -68,7 +71,7 @@
         .check(ProjectPermission.WRITE_CONFIG);
 
     try (MetaDataUpdate md = updateFactory.create(resource.getNameKey())) {
-      ProjectConfig config = ProjectConfig.read(md);
+      ProjectConfig config = projectConfigFactory.read(md);
       Project project = config.getProject();
       project.setDescription(Strings.emptyToNull(input.description));
 
diff --git a/java/com/google/gerrit/server/restapi/project/SetAccess.java b/java/com/google/gerrit/server/restapi/project/SetAccess.java
index c9d69a5..19e89a9 100644
--- a/java/com/google/gerrit/server/restapi/project/SetAccess.java
+++ b/java/com/google/gerrit/server/restapi/project/SetAccess.java
@@ -56,6 +56,7 @@
   private final Provider<IdentifiedUser> identifiedUser;
   private final SetAccessUtil accessUtil;
   private final CreateGroupPermissionSyncer createGroupPermissionSyncer;
+  private final ProjectConfig.Factory projectConfigFactory;
 
   @Inject
   private SetAccess(
@@ -66,7 +67,8 @@
       GetAccess getAccess,
       Provider<IdentifiedUser> identifiedUser,
       SetAccessUtil accessUtil,
-      CreateGroupPermissionSyncer createGroupPermissionSyncer) {
+      CreateGroupPermissionSyncer createGroupPermissionSyncer,
+      ProjectConfig.Factory projectConfigFactory) {
     this.groupBackend = groupBackend;
     this.permissionBackend = permissionBackend;
     this.metaDataUpdateFactory = metaDataUpdateFactory;
@@ -75,6 +77,7 @@
     this.identifiedUser = identifiedUser;
     this.accessUtil = accessUtil;
     this.createGroupPermissionSyncer = createGroupPermissionSyncer;
+    this.projectConfigFactory = projectConfigFactory;
   }
 
   @Override
@@ -89,7 +92,7 @@
     List<AccessSection> removals = accessUtil.getAccessSections(input.remove);
     List<AccessSection> additions = accessUtil.getAccessSections(input.add);
     try (MetaDataUpdate md = metaDataUpdateUser.create(rsrc.getNameKey())) {
-      config = ProjectConfig.read(md);
+      config = projectConfigFactory.read(md);
 
       // Check that the user has the right permissions.
       boolean checkedAdmin = false;
diff --git a/java/com/google/gerrit/server/restapi/project/SetDefaultDashboard.java b/java/com/google/gerrit/server/restapi/project/SetDefaultDashboard.java
index ef292e5..0f346df 100644
--- a/java/com/google/gerrit/server/restapi/project/SetDefaultDashboard.java
+++ b/java/com/google/gerrit/server/restapi/project/SetDefaultDashboard.java
@@ -47,6 +47,7 @@
   private final DashboardsCollection dashboards;
   private final Provider<GetDashboard> get;
   private final PermissionBackend permissionBackend;
+  private final ProjectConfig.Factory projectConfigFactory;
 
   @Option(name = "--inherited", usage = "set dashboard inherited by children")
   boolean inherited;
@@ -57,12 +58,14 @@
       MetaDataUpdate.Server updateFactory,
       DashboardsCollection dashboards,
       Provider<GetDashboard> get,
-      PermissionBackend permissionBackend) {
+      PermissionBackend permissionBackend,
+      ProjectConfig.Factory projectConfigFactory) {
     this.cache = cache;
     this.updateFactory = updateFactory;
     this.dashboards = dashboards;
     this.get = get;
     this.permissionBackend = permissionBackend;
+    this.projectConfigFactory = projectConfigFactory;
   }
 
   @Override
@@ -93,7 +96,7 @@
     }
 
     try (MetaDataUpdate md = updateFactory.create(rsrc.getProjectState().getNameKey())) {
-      ProjectConfig config = ProjectConfig.read(md);
+      ProjectConfig config = projectConfigFactory.read(md);
       Project project = config.getProject();
       if (inherited) {
         project.setDefaultDashboard(input.id);
diff --git a/java/com/google/gerrit/server/restapi/project/SetParent.java b/java/com/google/gerrit/server/restapi/project/SetParent.java
index d02d04a..12aaf76 100644
--- a/java/com/google/gerrit/server/restapi/project/SetParent.java
+++ b/java/com/google/gerrit/server/restapi/project/SetParent.java
@@ -61,6 +61,7 @@
   private final MetaDataUpdate.Server updateFactory;
   private final AllProjectsName allProjects;
   private final AllUsersName allUsers;
+  private final ProjectConfig.Factory projectConfigFactory;
   private volatile boolean allowProjectOwnersToChangeParent;
 
   @Inject
@@ -70,12 +71,14 @@
       MetaDataUpdate.Server updateFactory,
       AllProjectsName allProjects,
       AllUsersName allUsers,
+      ProjectConfig.Factory projectConfigFactory,
       @GerritServerConfig Config config) {
     this.cache = cache;
     this.permissionBackend = permissionBackend;
     this.updateFactory = updateFactory;
     this.allProjects = allProjects;
     this.allUsers = allUsers;
+    this.projectConfigFactory = projectConfigFactory;
     this.allowProjectOwnersToChangeParent =
         config.getBoolean("receive", "allowProjectOwnersToChangeParent", false);
   }
@@ -97,7 +100,7 @@
         MoreObjects.firstNonNull(Strings.emptyToNull(input.parent), allProjects.get());
     validateParentUpdate(rsrc.getProjectState().getNameKey(), user, parentName, checkIfAdmin);
     try (MetaDataUpdate md = updateFactory.create(rsrc.getNameKey())) {
-      ProjectConfig config = ProjectConfig.read(md);
+      ProjectConfig config = projectConfigFactory.read(md);
       Project project = config.getProject();
       project.setParentName(parentName);
 
diff --git a/java/com/google/gerrit/server/rules/StoredValues.java b/java/com/google/gerrit/server/rules/StoredValues.java
index 8b9cfe3..a712635 100644
--- a/java/com/google/gerrit/server/rules/StoredValues.java
+++ b/java/com/google/gerrit/server/rules/StoredValues.java
@@ -110,6 +110,18 @@
         }
       };
 
+  // Accessing GitRepositoryManager could be slow.
+  // It should be minimized or cached to reduce pause time
+  // when evaluating Prolog submit rules.
+  public static final StoredValue<GitRepositoryManager> REPO_MANAGER =
+      new StoredValue<GitRepositoryManager>() {
+        @Override
+        public GitRepositoryManager createValue(Prolog engine) {
+          PrologEnvironment env = (PrologEnvironment) engine.control;
+          return env.getArgs().getGitRepositoryManager();
+        }
+      };
+
   public static final StoredValue<Repository> REPOSITORY =
       new StoredValue<Repository>() {
         @Override
diff --git a/java/com/google/gerrit/server/schema/AllProjectsCreator.java b/java/com/google/gerrit/server/schema/AllProjectsCreator.java
index 348f88c..85965ef 100644
--- a/java/com/google/gerrit/server/schema/AllProjectsCreator.java
+++ b/java/com/google/gerrit/server/schema/AllProjectsCreator.java
@@ -73,6 +73,7 @@
   private final AllProjectsName allProjectsName;
   private final PersonIdent serverUser;
   private final NotesMigration notesMigration;
+  private final ProjectConfig.Factory projectConfigFactory;
   private final GroupReference anonymous;
   private final GroupReference registered;
   private final GroupReference owners;
@@ -90,11 +91,13 @@
       AllProjectsName allProjectsName,
       @GerritPersonIdent PersonIdent serverUser,
       NotesMigration notesMigration,
-      SystemGroupBackend systemGroupBackend) {
+      SystemGroupBackend systemGroupBackend,
+      ProjectConfig.Factory projectConfigFactory) {
     this.repositoryManager = repositoryManager;
     this.allProjectsName = allProjectsName;
     this.serverUser = serverUser;
     this.notesMigration = notesMigration;
+    this.projectConfigFactory = projectConfigFactory;
 
     this.anonymous = systemGroupBackend.getGroup(ANONYMOUS_USERS);
     this.registered = systemGroupBackend.getGroup(REGISTERED_USERS);
@@ -170,7 +173,7 @@
               Strings.emptyToNull(message),
               "Initialized Gerrit Code Review " + Version.getVersion()));
 
-      ProjectConfig config = ProjectConfig.read(md);
+      ProjectConfig config = projectConfigFactory.read(md);
       Project p = config.getProject();
       p.setDescription("Access inherited by all other projects.");
       p.setBooleanConfig(BooleanProjectConfig.REQUIRE_CHANGE_ID, InheritableBoolean.TRUE);
diff --git a/java/com/google/gerrit/server/schema/AllUsersCreator.java b/java/com/google/gerrit/server/schema/AllUsersCreator.java
index 3779d0d..3b1124d 100644
--- a/java/com/google/gerrit/server/schema/AllUsersCreator.java
+++ b/java/com/google/gerrit/server/schema/AllUsersCreator.java
@@ -35,6 +35,7 @@
 import com.google.gerrit.server.git.meta.MetaDataUpdate;
 import com.google.gerrit.server.group.SystemGroupBackend;
 import com.google.gerrit.server.project.ProjectConfig;
+import com.google.gerrit.server.project.ProjectConfig.Factory;
 import com.google.gerrit.server.project.RefPattern;
 import com.google.inject.Inject;
 import java.io.IOException;
@@ -50,6 +51,7 @@
   private final GitRepositoryManager mgr;
   private final AllUsersName allUsersName;
   private final PersonIdent serverUser;
+  private final ProjectConfig.Factory projectConfigFactory;
   private final GroupReference registered;
 
   @Nullable private GroupReference admin;
@@ -60,11 +62,13 @@
       GitRepositoryManager mgr,
       AllUsersName allUsersName,
       SystemGroupBackend systemGroupBackend,
-      @GerritPersonIdent PersonIdent serverUser) {
+      @GerritPersonIdent PersonIdent serverUser,
+      Factory projectConfigFactory) {
     this.mgr = mgr;
     this.allUsersName = allUsersName;
     this.serverUser = serverUser;
     this.registered = systemGroupBackend.getGroup(REGISTERED_USERS);
+    this.projectConfigFactory = projectConfigFactory;
     this.codeReviewLabel = getDefaultCodeReviewLabel();
   }
 
@@ -107,7 +111,7 @@
       md.getCommitBuilder().setCommitter(serverUser);
       md.setMessage("Initialized Gerrit Code Review " + Version.getVersion());
 
-      ProjectConfig config = ProjectConfig.read(md);
+      ProjectConfig config = projectConfigFactory.read(md);
       Project project = config.getProject();
       project.setDescription("Individual user settings and preferences.");
 
diff --git a/java/com/google/gerrit/server/schema/BUILD b/java/com/google/gerrit/server/schema/BUILD
index a04def6..93cad19 100644
--- a/java/com/google/gerrit/server/schema/BUILD
+++ b/java/com/google/gerrit/server/schema/BUILD
@@ -8,6 +8,7 @@
         "//java/com/google/gerrit/common:annotations",
         "//java/com/google/gerrit/common:server",
         "//java/com/google/gerrit/extensions:api",
+        "//java/com/google/gerrit/git",
         "//java/com/google/gerrit/lifecycle",
         "//java/com/google/gerrit/metrics",
         "//java/com/google/gerrit/reviewdb:server",
diff --git a/java/com/google/gerrit/server/schema/ReviewDbSchemaCreator.java b/java/com/google/gerrit/server/schema/ReviewDbSchemaCreator.java
new file mode 100644
index 0000000..3a42f07
--- /dev/null
+++ b/java/com/google/gerrit/server/schema/ReviewDbSchemaCreator.java
@@ -0,0 +1,275 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.schema;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.gerrit.common.Nullable;
+import com.google.gerrit.common.data.GroupReference;
+import com.google.gerrit.git.RefUpdateUtil;
+import com.google.gerrit.metrics.MetricMaker;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.GerritPersonIdent;
+import com.google.gerrit.server.Sequences;
+import com.google.gerrit.server.account.GroupUUID;
+import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.config.AllUsersName;
+import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gerrit.server.config.GerritServerId;
+import com.google.gerrit.server.config.SitePath;
+import com.google.gerrit.server.config.SitePaths;
+import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.git.meta.MetaDataUpdate;
+import com.google.gerrit.server.group.InternalGroup;
+import com.google.gerrit.server.group.db.AuditLogFormatter;
+import com.google.gerrit.server.group.db.GroupConfig;
+import com.google.gerrit.server.group.db.GroupNameNotes;
+import com.google.gerrit.server.group.db.InternalGroupCreation;
+import com.google.gerrit.server.group.db.InternalGroupUpdate;
+import com.google.gerrit.server.index.group.GroupIndex;
+import com.google.gerrit.server.index.group.GroupIndexCollection;
+import com.google.gerrit.server.notedb.NotesMigration;
+import com.google.gwtorm.jdbc.JdbcExecutor;
+import com.google.gwtorm.jdbc.JdbcSchema;
+import com.google.gwtorm.server.OrmDuplicateKeyException;
+import com.google.gwtorm.server.OrmException;
+import com.google.inject.Inject;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Collections;
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.lib.BatchRefUpdate;
+import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.Repository;
+
+/** Creates the current database schema and populates initial code rows. */
+public class ReviewDbSchemaCreator {
+  @SitePath private final Path site_path;
+
+  private final GitRepositoryManager repoManager;
+  private final AllProjectsCreator allProjectsCreator;
+  private final AllUsersCreator allUsersCreator;
+  private final AllUsersName allUsersName;
+  private final PersonIdent serverUser;
+  private final DataSourceType dataSourceType;
+  private final GroupIndexCollection indexCollection;
+  private final String serverId;
+
+  private final Config config;
+  private final MetricMaker metricMaker;
+  private final NotesMigration migration;
+  private final AllProjectsName allProjectsName;
+
+  @Inject
+  public ReviewDbSchemaCreator(
+      SitePaths site,
+      GitRepositoryManager repoManager,
+      AllProjectsCreator ap,
+      AllUsersCreator auc,
+      AllUsersName allUsersName,
+      @GerritPersonIdent PersonIdent au,
+      DataSourceType dst,
+      GroupIndexCollection ic,
+      @GerritServerId String serverId,
+      @GerritServerConfig Config config,
+      MetricMaker metricMaker,
+      NotesMigration migration,
+      AllProjectsName apName) {
+    this(
+        site.site_path,
+        repoManager,
+        ap,
+        auc,
+        allUsersName,
+        au,
+        dst,
+        ic,
+        serverId,
+        config,
+        metricMaker,
+        migration,
+        apName);
+  }
+
+  public ReviewDbSchemaCreator(
+      @SitePath Path site,
+      GitRepositoryManager repoManager,
+      AllProjectsCreator ap,
+      AllUsersCreator auc,
+      AllUsersName allUsersName,
+      @GerritPersonIdent PersonIdent au,
+      DataSourceType dst,
+      GroupIndexCollection ic,
+      String serverId,
+      Config config,
+      MetricMaker metricMaker,
+      NotesMigration migration,
+      AllProjectsName apName) {
+    site_path = site;
+    this.repoManager = repoManager;
+    allProjectsCreator = ap;
+    allUsersCreator = auc;
+    this.allUsersName = allUsersName;
+    serverUser = au;
+    dataSourceType = dst;
+    indexCollection = ic;
+    this.serverId = serverId;
+
+    this.config = config;
+    this.allProjectsName = apName;
+    this.migration = migration;
+    this.metricMaker = metricMaker;
+  }
+
+  public void create(ReviewDb db) throws OrmException, IOException, ConfigInvalidException {
+    final JdbcSchema jdbc = (JdbcSchema) db;
+    try (JdbcExecutor e = new JdbcExecutor(jdbc)) {
+      jdbc.updateSchema(e);
+    }
+
+    final CurrentSchemaVersion sVer = CurrentSchemaVersion.create();
+    sVer.versionNbr = ReviewDbSchemaVersion.getBinaryVersion();
+    db.schemaVersion().insert(Collections.singleton(sVer));
+
+    GroupReference admins = createGroupReference("Administrators");
+    GroupReference batchUsers = createGroupReference("Non-Interactive Users");
+
+    allProjectsCreator.setAdministrators(admins).setBatchUsers(batchUsers).create();
+    // We have to create the All-Users repository before we can use it to store the groups in it.
+    allUsersCreator.setAdministrators(admins).create();
+
+    // Don't rely on injection to construct Sequences, as it requires ReviewDb.
+    Sequences seqs =
+        new Sequences(
+            config,
+            () -> db,
+            migration,
+            repoManager,
+            GitReferenceUpdated.DISABLED,
+            allProjectsName,
+            allUsersName,
+            metricMaker);
+    try (Repository allUsersRepo = repoManager.openRepository(allUsersName)) {
+      createAdminsGroup(seqs, allUsersRepo, admins);
+      createBatchUsersGroup(seqs, allUsersRepo, batchUsers, admins.getUUID());
+    }
+
+    dataSourceType.getIndexScript().run(db);
+  }
+
+  private void createAdminsGroup(
+      Sequences seqs, Repository allUsersRepo, GroupReference groupReference)
+      throws OrmException, IOException, ConfigInvalidException {
+    InternalGroupCreation groupCreation = getGroupCreation(seqs, groupReference);
+    InternalGroupUpdate groupUpdate =
+        InternalGroupUpdate.builder().setDescription("Gerrit Site Administrators").build();
+
+    createGroup(allUsersRepo, groupCreation, groupUpdate);
+  }
+
+  private void createBatchUsersGroup(
+      Sequences seqs,
+      Repository allUsersRepo,
+      GroupReference groupReference,
+      AccountGroup.UUID adminsGroupUuid)
+      throws OrmException, IOException, ConfigInvalidException {
+    InternalGroupCreation groupCreation = getGroupCreation(seqs, groupReference);
+    InternalGroupUpdate groupUpdate =
+        InternalGroupUpdate.builder()
+            .setDescription("Users who perform batch actions on Gerrit")
+            .setOwnerGroupUUID(adminsGroupUuid)
+            .build();
+
+    createGroup(allUsersRepo, groupCreation, groupUpdate);
+  }
+
+  private void createGroup(
+      Repository allUsersRepo, InternalGroupCreation groupCreation, InternalGroupUpdate groupUpdate)
+      throws OrmException, ConfigInvalidException, IOException {
+    InternalGroup createdGroup = createGroupInNoteDb(allUsersRepo, groupCreation, groupUpdate);
+    index(createdGroup);
+  }
+
+  private InternalGroup createGroupInNoteDb(
+      Repository allUsersRepo, InternalGroupCreation groupCreation, InternalGroupUpdate groupUpdate)
+      throws ConfigInvalidException, IOException, OrmDuplicateKeyException {
+    // This method is only executed on a new server which doesn't have any accounts or groups.
+    AuditLogFormatter auditLogFormatter =
+        AuditLogFormatter.createBackedBy(ImmutableSet.of(), ImmutableSet.of(), serverId);
+
+    GroupConfig groupConfig =
+        GroupConfig.createForNewGroup(allUsersName, allUsersRepo, groupCreation);
+    groupConfig.setGroupUpdate(groupUpdate, auditLogFormatter);
+
+    AccountGroup.NameKey groupName = groupUpdate.getName().orElseGet(groupCreation::getNameKey);
+    GroupNameNotes groupNameNotes =
+        GroupNameNotes.forNewGroup(
+            allUsersName, allUsersRepo, groupCreation.getGroupUUID(), groupName);
+
+    commit(allUsersRepo, groupConfig, groupNameNotes);
+
+    return groupConfig
+        .getLoadedGroup()
+        .orElseThrow(() -> new IllegalStateException("Created group wasn't automatically loaded"));
+  }
+
+  private void commit(
+      Repository allUsersRepo, GroupConfig groupConfig, GroupNameNotes groupNameNotes)
+      throws IOException {
+    BatchRefUpdate batchRefUpdate = allUsersRepo.getRefDatabase().newBatchUpdate();
+    try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate(allUsersRepo, batchRefUpdate)) {
+      groupConfig.commit(metaDataUpdate);
+    }
+    // MetaDataUpdates unfortunately can't be reused. -> Create a new one.
+    try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate(allUsersRepo, batchRefUpdate)) {
+      groupNameNotes.commit(metaDataUpdate);
+    }
+    RefUpdateUtil.executeChecked(batchRefUpdate, allUsersRepo);
+  }
+
+  private MetaDataUpdate createMetaDataUpdate(
+      Repository allUsersRepo, @Nullable BatchRefUpdate batchRefUpdate) {
+    MetaDataUpdate metaDataUpdate =
+        new MetaDataUpdate(
+            GitReferenceUpdated.DISABLED, allUsersName, allUsersRepo, batchRefUpdate);
+    metaDataUpdate.getCommitBuilder().setAuthor(serverUser);
+    metaDataUpdate.getCommitBuilder().setCommitter(serverUser);
+    return metaDataUpdate;
+  }
+
+  private void index(InternalGroup group) throws IOException {
+    for (GroupIndex groupIndex : indexCollection.getWriteIndexes()) {
+      groupIndex.replace(group);
+    }
+  }
+
+  private GroupReference createGroupReference(String name) {
+    AccountGroup.UUID groupUuid = GroupUUID.make(name, serverUser);
+    return new GroupReference(groupUuid, name);
+  }
+
+  private InternalGroupCreation getGroupCreation(Sequences seqs, GroupReference groupReference)
+      throws OrmException {
+    int next = seqs.nextGroupId();
+    return InternalGroupCreation.builder()
+        .setNameKey(new AccountGroup.NameKey(groupReference.getName()))
+        .setId(new AccountGroup.Id(next))
+        .setGroupUUID(groupReference.getUUID())
+        .build();
+  }
+}
diff --git a/java/com/google/gerrit/server/schema/ReviewDbSchemaModule.java b/java/com/google/gerrit/server/schema/ReviewDbSchemaModule.java
new file mode 100644
index 0000000..da8898a4
--- /dev/null
+++ b/java/com/google/gerrit/server/schema/ReviewDbSchemaModule.java
@@ -0,0 +1,53 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.schema;
+
+import static com.google.inject.Scopes.SINGLETON;
+
+import com.google.gerrit.extensions.config.FactoryModule;
+import com.google.gerrit.server.GerritPersonIdent;
+import com.google.gerrit.server.GerritPersonIdentProvider;
+import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.config.AllProjectsNameProvider;
+import com.google.gerrit.server.config.AllUsersName;
+import com.google.gerrit.server.config.AllUsersNameProvider;
+import com.google.gerrit.server.config.AnonymousCowardName;
+import com.google.gerrit.server.config.AnonymousCowardNameProvider;
+import com.google.gerrit.server.config.GerritServerId;
+import com.google.gerrit.server.config.GerritServerIdProvider;
+import org.eclipse.jgit.lib.PersonIdent;
+
+/** Validate the schema and connect to Git. */
+public class ReviewDbSchemaModule extends FactoryModule {
+  @Override
+  protected void configure() {
+    bind(PersonIdent.class)
+        .annotatedWith(GerritPersonIdent.class)
+        .toProvider(GerritPersonIdentProvider.class);
+
+    bind(AllProjectsName.class).toProvider(AllProjectsNameProvider.class).in(SINGLETON);
+
+    bind(AllUsersName.class).toProvider(AllUsersNameProvider.class).in(SINGLETON);
+
+    bind(String.class)
+        .annotatedWith(AnonymousCowardName.class)
+        .toProvider(AnonymousCowardNameProvider.class);
+
+    bind(String.class)
+        .annotatedWith(GerritServerId.class)
+        .toProvider(GerritServerIdProvider.class)
+        .in(SINGLETON);
+  }
+}
diff --git a/java/com/google/gerrit/server/schema/ReviewDbSchemaUpdater.java b/java/com/google/gerrit/server/schema/ReviewDbSchemaUpdater.java
new file mode 100644
index 0000000..86f4560
--- /dev/null
+++ b/java/com/google/gerrit/server/schema/ReviewDbSchemaUpdater.java
@@ -0,0 +1,133 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.schema;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.reviewdb.server.ReviewDbUtil;
+import com.google.gerrit.server.GerritPersonIdent;
+import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.config.AllUsersName;
+import com.google.gerrit.server.config.AnonymousCowardName;
+import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gerrit.server.config.SitePaths;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.group.SystemGroupBackend;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.Stage;
+import java.io.IOException;
+import java.sql.SQLException;
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.PersonIdent;
+
+/** Creates or updates the current database schema. */
+public class ReviewDbSchemaUpdater {
+  private final SchemaFactory<ReviewDb> schema;
+  private final ReviewDbSchemaCreator creator;
+  private final Provider<ReviewDbSchemaVersion> updater;
+
+  @Inject
+  ReviewDbSchemaUpdater(
+      @ReviewDbFactory SchemaFactory<ReviewDb> schema,
+      ReviewDbSchemaCreator creator,
+      Injector parent) {
+    this.schema = schema;
+    this.creator = creator;
+    this.updater = buildInjector(parent).getProvider(ReviewDbSchemaVersion.class);
+  }
+
+  private static Injector buildInjector(Injector parent) {
+    // Use DEVELOPMENT mode to allow lazy initialization of the
+    // graph. This avoids touching ancient schema versions that
+    // are behind this installation's current version.
+    return Guice.createInjector(
+        Stage.DEVELOPMENT,
+        new AbstractModule() {
+          @Override
+          protected void configure() {
+            bind(ReviewDbSchemaVersion.class).to(ReviewDbSchemaVersion.C);
+
+            for (Key<?> k :
+                new Key<?>[] {
+                  Key.get(PersonIdent.class, GerritPersonIdent.class),
+                  Key.get(String.class, AnonymousCowardName.class),
+                  Key.get(Config.class, GerritServerConfig.class),
+                }) {
+              rebind(parent, k);
+            }
+
+            for (Class<?> c :
+                new Class<?>[] {
+                  AllProjectsName.class,
+                  AllUsersCreator.class,
+                  AllUsersName.class,
+                  GitRepositoryManager.class,
+                  SitePaths.class,
+                  SystemGroupBackend.class,
+                }) {
+              rebind(parent, Key.get(c));
+            }
+          }
+
+          private <T> void rebind(Injector parent, Key<T> c) {
+            bind(c).toProvider(parent.getProvider(c));
+          }
+        });
+  }
+
+  public void update(UpdateUI ui) throws OrmException {
+    try (ReviewDb db = ReviewDbUtil.unwrapDb(schema.open())) {
+
+      final ReviewDbSchemaVersion u = updater.get();
+      final CurrentSchemaVersion version = getSchemaVersion(db);
+      if (version == null) {
+        try {
+          creator.create(db);
+        } catch (IOException | ConfigInvalidException e) {
+          throw new OrmException("Cannot initialize schema", e);
+        }
+
+      } else {
+        try {
+          u.check(ui, version, db);
+        } catch (SQLException e) {
+          throw new OrmException("Cannot upgrade schema", e);
+        }
+      }
+    }
+  }
+
+  @VisibleForTesting
+  public ReviewDbSchemaVersion getLatestSchemaVersion() {
+    return updater.get();
+  }
+
+  private CurrentSchemaVersion getSchemaVersion(ReviewDb db) {
+    try {
+      return db.schemaVersion().get(new CurrentSchemaVersion.Key());
+    } catch (OrmException e) {
+      return null;
+    }
+  }
+}
diff --git a/java/com/google/gerrit/server/schema/ReviewDbSchemaVersion.java b/java/com/google/gerrit/server/schema/ReviewDbSchemaVersion.java
new file mode 100644
index 0000000..10a2d39
--- /dev/null
+++ b/java/com/google/gerrit/server/schema/ReviewDbSchemaVersion.java
@@ -0,0 +1,216 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.schema;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.Lists;
+import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.UsedAt;
+import com.google.gwtorm.jdbc.JdbcExecutor;
+import com.google.gwtorm.jdbc.JdbcSchema;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.StatementExecutor;
+import com.google.inject.Provider;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/** A version of the database schema. */
+public abstract class ReviewDbSchemaVersion {
+  /** The current schema version. */
+  public static final Class<Schema_170> C = Schema_170.class;
+
+  public static int getBinaryVersion() {
+    return guessVersion(C);
+  }
+
+  private final Provider<? extends ReviewDbSchemaVersion> prior;
+  private final int versionNbr;
+
+  protected ReviewDbSchemaVersion(Provider<? extends ReviewDbSchemaVersion> prior) {
+    this.prior = prior;
+    this.versionNbr = guessVersion(getClass());
+  }
+
+  @UsedAt(UsedAt.Project.PLUGIN_DELETE_PROJECT)
+  public static int guessVersion(Class<?> c) {
+    String n = c.getName();
+    n = n.substring(n.lastIndexOf('_') + 1);
+    while (n.startsWith("0")) {
+      n = n.substring(1);
+    }
+    return Integer.parseInt(n);
+  }
+
+  /** @return the {@link CurrentSchemaVersion#versionNbr} this step targets. */
+  public final int getVersionNbr() {
+    return versionNbr;
+  }
+
+  @VisibleForTesting
+  public final ReviewDbSchemaVersion getPrior() {
+    return prior.get();
+  }
+
+  public final void check(UpdateUI ui, CurrentSchemaVersion curr, ReviewDb db)
+      throws OrmException, SQLException {
+    if (curr.versionNbr == versionNbr) {
+      // Nothing to do, we are at the correct schema.
+    } else if (curr.versionNbr > versionNbr) {
+      throw new OrmException(
+          "Cannot downgrade database schema from version "
+              + curr.versionNbr
+              + " to "
+              + versionNbr
+              + ".");
+    } else {
+      upgradeFrom(ui, curr, db);
+    }
+  }
+
+  /** Runs check on the prior schema version, and then upgrades. */
+  private void upgradeFrom(UpdateUI ui, CurrentSchemaVersion curr, ReviewDb db)
+      throws OrmException, SQLException {
+    List<ReviewDbSchemaVersion> pending = pending(curr.versionNbr);
+    updateSchema(pending, ui, db);
+    migrateData(pending, ui, curr, db);
+
+    JdbcSchema s = (JdbcSchema) db;
+    final List<String> pruneList = new ArrayList<>();
+    s.pruneSchema(
+        new StatementExecutor() {
+          @Override
+          public void execute(String sql) {
+            pruneList.add(sql);
+          }
+
+          @Override
+          public void close() {
+            // Do nothing.
+          }
+        });
+
+    try (JdbcExecutor e = new JdbcExecutor(s)) {
+      if (!pruneList.isEmpty()) {
+        ui.pruneSchema(e, pruneList);
+      }
+    }
+  }
+
+  private List<ReviewDbSchemaVersion> pending(int curr) {
+    List<ReviewDbSchemaVersion> r = Lists.newArrayListWithCapacity(versionNbr - curr);
+    for (ReviewDbSchemaVersion v = this; curr < v.getVersionNbr(); v = v.prior.get()) {
+      r.add(v);
+    }
+    Collections.reverse(r);
+    return r;
+  }
+
+  private void updateSchema(List<ReviewDbSchemaVersion> pending, UpdateUI ui, ReviewDb db)
+      throws OrmException, SQLException {
+    for (ReviewDbSchemaVersion v : pending) {
+      ui.message(String.format("Upgrading schema to %d ...", v.getVersionNbr()));
+      v.preUpdateSchema(db);
+    }
+
+    JdbcSchema s = (JdbcSchema) db;
+    try (JdbcExecutor e = new JdbcExecutor(s)) {
+      s.updateSchema(e);
+    }
+  }
+
+  /**
+   * Invoked before updateSchema adds new columns/tables.
+   *
+   * @param db open database handle.
+   * @throws OrmException if a Gerrit-specific exception occurred.
+   * @throws SQLException if an underlying SQL exception occurred.
+   */
+  protected void preUpdateSchema(ReviewDb db) throws OrmException, SQLException {}
+
+  private void migrateData(
+      List<ReviewDbSchemaVersion> pending, UpdateUI ui, CurrentSchemaVersion curr, ReviewDb db)
+      throws OrmException, SQLException {
+    for (ReviewDbSchemaVersion v : pending) {
+      Stopwatch sw = Stopwatch.createStarted();
+      ui.message(String.format("Migrating data to schema %d ...", v.getVersionNbr()));
+      v.migrateData(db, ui);
+      v.finish(curr, db);
+      ui.message(String.format("\t> Done (%.3f s)", sw.elapsed(TimeUnit.MILLISECONDS) / 1000d));
+    }
+  }
+
+  /**
+   * Invoked between updateSchema (adds new columns/tables) and pruneSchema (removes deleted
+   * columns/tables).
+   *
+   * @param db open database handle.
+   * @param ui interface for interacting with the user.
+   * @throws OrmException if a Gerrit-specific exception occurred.
+   * @throws SQLException if an underlying SQL exception occurred.
+   */
+  protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {}
+
+  /** Mark the current schema version. */
+  protected void finish(CurrentSchemaVersion curr, ReviewDb db) throws OrmException {
+    curr.versionNbr = versionNbr;
+    db.schemaVersion().update(Collections.singleton(curr));
+  }
+
+  /** Rename an existing table. */
+  protected static void renameTable(ReviewDb db, String from, String to) throws OrmException {
+    JdbcSchema s = (JdbcSchema) db;
+    try (JdbcExecutor e = new JdbcExecutor(s)) {
+      s.renameTable(e, from, to);
+    }
+  }
+
+  /** Rename an existing column. */
+  protected static void renameColumn(ReviewDb db, String table, String from, String to)
+      throws OrmException {
+    JdbcSchema s = (JdbcSchema) db;
+    try (JdbcExecutor e = new JdbcExecutor(s)) {
+      s.renameColumn(e, table, from, to);
+    }
+  }
+
+  /** Execute an SQL statement. */
+  protected static void execute(ReviewDb db, String sql) throws SQLException {
+    try (Statement s = newStatement(db)) {
+      s.execute(sql);
+    }
+  }
+
+  /** Open a new single statement. */
+  protected static Statement newStatement(ReviewDb db) throws SQLException {
+    return ((JdbcSchema) db).getConnection().createStatement();
+  }
+
+  /** Open a new prepared statement. */
+  protected static PreparedStatement prepareStatement(ReviewDb db, String sql) throws SQLException {
+    return ((JdbcSchema) db).getConnection().prepareStatement(sql);
+  }
+
+  /** Open a new statement executor. */
+  protected static JdbcExecutor newExecutor(ReviewDb db) throws OrmException {
+    return new JdbcExecutor(((JdbcSchema) db).getConnection());
+  }
+}
diff --git a/java/com/google/gerrit/server/schema/ReviewDbSchemaVersionCheck.java b/java/com/google/gerrit/server/schema/ReviewDbSchemaVersionCheck.java
new file mode 100644
index 0000000..12abc7e
--- /dev/null
+++ b/java/com/google/gerrit/server/schema/ReviewDbSchemaVersionCheck.java
@@ -0,0 +1,95 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.schema;
+
+import com.google.gerrit.extensions.events.LifecycleListener;
+import com.google.gerrit.lifecycle.LifecycleModule;
+import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.config.SitePaths;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
+import com.google.inject.Inject;
+import com.google.inject.Module;
+import com.google.inject.ProvisionException;
+
+/** Validates the current schema version. */
+public class ReviewDbSchemaVersionCheck implements LifecycleListener {
+  public static Module module() {
+    return new LifecycleModule() {
+      @Override
+      protected void configure() {
+        listener().to(ReviewDbSchemaVersionCheck.class);
+      }
+    };
+  }
+
+  private final SchemaFactory<ReviewDb> schema;
+  private final SitePaths site;
+
+  @Inject
+  public ReviewDbSchemaVersionCheck(SchemaFactory<ReviewDb> schemaFactory, SitePaths site) {
+    this.schema = schemaFactory;
+    this.site = site;
+  }
+
+  @Override
+  public void start() {
+    try (ReviewDb db = schema.open()) {
+      final CurrentSchemaVersion currentVer = getSchemaVersion(db);
+      final int expectedVer = ReviewDbSchemaVersion.getBinaryVersion();
+
+      if (currentVer == null) {
+        throw new ProvisionException(
+            "Schema not yet initialized."
+                + "  Run init to initialize the schema:\n"
+                + "$ java -jar gerrit.war init -d "
+                + site.site_path.toAbsolutePath());
+      }
+      if (currentVer.versionNbr < expectedVer) {
+        throw new ProvisionException(
+            "Unsupported schema version "
+                + currentVer.versionNbr
+                + "; expected schema version "
+                + expectedVer
+                + ".  Run init to upgrade:\n"
+                + "$ java -jar "
+                + site.gerrit_war.toAbsolutePath()
+                + " init -d "
+                + site.site_path.toAbsolutePath());
+      } else if (currentVer.versionNbr > expectedVer) {
+        throw new ProvisionException(
+            "Unsupported schema version "
+                + currentVer.versionNbr
+                + "; expected schema version "
+                + expectedVer
+                + ". Downgrade is not supported.");
+      }
+    } catch (OrmException e) {
+      throw new ProvisionException("Cannot read schema_version", e);
+    }
+  }
+
+  @Override
+  public void stop() {}
+
+  private CurrentSchemaVersion getSchemaVersion(ReviewDb db) {
+    try {
+      return db.schemaVersion().get(new CurrentSchemaVersion.Key());
+    } catch (OrmException e) {
+      return null;
+    }
+  }
+}
diff --git a/java/com/google/gerrit/server/schema/SchemaCreator.java b/java/com/google/gerrit/server/schema/SchemaCreator.java
deleted file mode 100644
index 13734c3..0000000
--- a/java/com/google/gerrit/server/schema/SchemaCreator.java
+++ /dev/null
@@ -1,275 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.schema;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.common.data.GroupReference;
-import com.google.gerrit.metrics.MetricMaker;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.Sequences;
-import com.google.gerrit.server.account.GroupUUID;
-import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.config.GerritServerId;
-import com.google.gerrit.server.config.SitePath;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gerrit.server.group.InternalGroup;
-import com.google.gerrit.server.group.db.AuditLogFormatter;
-import com.google.gerrit.server.group.db.GroupConfig;
-import com.google.gerrit.server.group.db.GroupNameNotes;
-import com.google.gerrit.server.group.db.InternalGroupCreation;
-import com.google.gerrit.server.group.db.InternalGroupUpdate;
-import com.google.gerrit.server.index.group.GroupIndex;
-import com.google.gerrit.server.index.group.GroupIndexCollection;
-import com.google.gerrit.server.notedb.NotesMigration;
-import com.google.gerrit.server.update.RefUpdateUtil;
-import com.google.gwtorm.jdbc.JdbcExecutor;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.server.OrmDuplicateKeyException;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Collections;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.BatchRefUpdate;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-
-/** Creates the current database schema and populates initial code rows. */
-public class SchemaCreator {
-  @SitePath private final Path site_path;
-
-  private final GitRepositoryManager repoManager;
-  private final AllProjectsCreator allProjectsCreator;
-  private final AllUsersCreator allUsersCreator;
-  private final AllUsersName allUsersName;
-  private final PersonIdent serverUser;
-  private final DataSourceType dataSourceType;
-  private final GroupIndexCollection indexCollection;
-  private final String serverId;
-
-  private final Config config;
-  private final MetricMaker metricMaker;
-  private final NotesMigration migration;
-  private final AllProjectsName allProjectsName;
-
-  @Inject
-  public SchemaCreator(
-      SitePaths site,
-      GitRepositoryManager repoManager,
-      AllProjectsCreator ap,
-      AllUsersCreator auc,
-      AllUsersName allUsersName,
-      @GerritPersonIdent PersonIdent au,
-      DataSourceType dst,
-      GroupIndexCollection ic,
-      @GerritServerId String serverId,
-      @GerritServerConfig Config config,
-      MetricMaker metricMaker,
-      NotesMigration migration,
-      AllProjectsName apName) {
-    this(
-        site.site_path,
-        repoManager,
-        ap,
-        auc,
-        allUsersName,
-        au,
-        dst,
-        ic,
-        serverId,
-        config,
-        metricMaker,
-        migration,
-        apName);
-  }
-
-  public SchemaCreator(
-      @SitePath Path site,
-      GitRepositoryManager repoManager,
-      AllProjectsCreator ap,
-      AllUsersCreator auc,
-      AllUsersName allUsersName,
-      @GerritPersonIdent PersonIdent au,
-      DataSourceType dst,
-      GroupIndexCollection ic,
-      String serverId,
-      Config config,
-      MetricMaker metricMaker,
-      NotesMigration migration,
-      AllProjectsName apName) {
-    site_path = site;
-    this.repoManager = repoManager;
-    allProjectsCreator = ap;
-    allUsersCreator = auc;
-    this.allUsersName = allUsersName;
-    serverUser = au;
-    dataSourceType = dst;
-    indexCollection = ic;
-    this.serverId = serverId;
-
-    this.config = config;
-    this.allProjectsName = apName;
-    this.migration = migration;
-    this.metricMaker = metricMaker;
-  }
-
-  public void create(ReviewDb db) throws OrmException, IOException, ConfigInvalidException {
-    final JdbcSchema jdbc = (JdbcSchema) db;
-    try (JdbcExecutor e = new JdbcExecutor(jdbc)) {
-      jdbc.updateSchema(e);
-    }
-
-    final CurrentSchemaVersion sVer = CurrentSchemaVersion.create();
-    sVer.versionNbr = SchemaVersion.getBinaryVersion();
-    db.schemaVersion().insert(Collections.singleton(sVer));
-
-    GroupReference admins = createGroupReference("Administrators");
-    GroupReference batchUsers = createGroupReference("Non-Interactive Users");
-
-    allProjectsCreator.setAdministrators(admins).setBatchUsers(batchUsers).create();
-    // We have to create the All-Users repository before we can use it to store the groups in it.
-    allUsersCreator.setAdministrators(admins).create();
-
-    // Don't rely on injection to construct Sequences, as it requires ReviewDb.
-    Sequences seqs =
-        new Sequences(
-            config,
-            () -> db,
-            migration,
-            repoManager,
-            GitReferenceUpdated.DISABLED,
-            allProjectsName,
-            allUsersName,
-            metricMaker);
-    try (Repository allUsersRepo = repoManager.openRepository(allUsersName)) {
-      createAdminsGroup(seqs, allUsersRepo, admins);
-      createBatchUsersGroup(seqs, allUsersRepo, batchUsers, admins.getUUID());
-    }
-
-    dataSourceType.getIndexScript().run(db);
-  }
-
-  private void createAdminsGroup(
-      Sequences seqs, Repository allUsersRepo, GroupReference groupReference)
-      throws OrmException, IOException, ConfigInvalidException {
-    InternalGroupCreation groupCreation = getGroupCreation(seqs, groupReference);
-    InternalGroupUpdate groupUpdate =
-        InternalGroupUpdate.builder().setDescription("Gerrit Site Administrators").build();
-
-    createGroup(allUsersRepo, groupCreation, groupUpdate);
-  }
-
-  private void createBatchUsersGroup(
-      Sequences seqs,
-      Repository allUsersRepo,
-      GroupReference groupReference,
-      AccountGroup.UUID adminsGroupUuid)
-      throws OrmException, IOException, ConfigInvalidException {
-    InternalGroupCreation groupCreation = getGroupCreation(seqs, groupReference);
-    InternalGroupUpdate groupUpdate =
-        InternalGroupUpdate.builder()
-            .setDescription("Users who perform batch actions on Gerrit")
-            .setOwnerGroupUUID(adminsGroupUuid)
-            .build();
-
-    createGroup(allUsersRepo, groupCreation, groupUpdate);
-  }
-
-  private void createGroup(
-      Repository allUsersRepo, InternalGroupCreation groupCreation, InternalGroupUpdate groupUpdate)
-      throws OrmException, ConfigInvalidException, IOException {
-    InternalGroup createdGroup = createGroupInNoteDb(allUsersRepo, groupCreation, groupUpdate);
-    index(createdGroup);
-  }
-
-  private InternalGroup createGroupInNoteDb(
-      Repository allUsersRepo, InternalGroupCreation groupCreation, InternalGroupUpdate groupUpdate)
-      throws ConfigInvalidException, IOException, OrmDuplicateKeyException {
-    // This method is only executed on a new server which doesn't have any accounts or groups.
-    AuditLogFormatter auditLogFormatter =
-        AuditLogFormatter.createBackedBy(ImmutableSet.of(), ImmutableSet.of(), serverId);
-
-    GroupConfig groupConfig =
-        GroupConfig.createForNewGroup(allUsersName, allUsersRepo, groupCreation);
-    groupConfig.setGroupUpdate(groupUpdate, auditLogFormatter);
-
-    AccountGroup.NameKey groupName = groupUpdate.getName().orElseGet(groupCreation::getNameKey);
-    GroupNameNotes groupNameNotes =
-        GroupNameNotes.forNewGroup(
-            allUsersName, allUsersRepo, groupCreation.getGroupUUID(), groupName);
-
-    commit(allUsersRepo, groupConfig, groupNameNotes);
-
-    return groupConfig
-        .getLoadedGroup()
-        .orElseThrow(() -> new IllegalStateException("Created group wasn't automatically loaded"));
-  }
-
-  private void commit(
-      Repository allUsersRepo, GroupConfig groupConfig, GroupNameNotes groupNameNotes)
-      throws IOException {
-    BatchRefUpdate batchRefUpdate = allUsersRepo.getRefDatabase().newBatchUpdate();
-    try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate(allUsersRepo, batchRefUpdate)) {
-      groupConfig.commit(metaDataUpdate);
-    }
-    // MetaDataUpdates unfortunately can't be reused. -> Create a new one.
-    try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate(allUsersRepo, batchRefUpdate)) {
-      groupNameNotes.commit(metaDataUpdate);
-    }
-    RefUpdateUtil.executeChecked(batchRefUpdate, allUsersRepo);
-  }
-
-  private MetaDataUpdate createMetaDataUpdate(
-      Repository allUsersRepo, @Nullable BatchRefUpdate batchRefUpdate) {
-    MetaDataUpdate metaDataUpdate =
-        new MetaDataUpdate(
-            GitReferenceUpdated.DISABLED, allUsersName, allUsersRepo, batchRefUpdate);
-    metaDataUpdate.getCommitBuilder().setAuthor(serverUser);
-    metaDataUpdate.getCommitBuilder().setCommitter(serverUser);
-    return metaDataUpdate;
-  }
-
-  private void index(InternalGroup group) throws IOException {
-    for (GroupIndex groupIndex : indexCollection.getWriteIndexes()) {
-      groupIndex.replace(group);
-    }
-  }
-
-  private GroupReference createGroupReference(String name) {
-    AccountGroup.UUID groupUuid = GroupUUID.make(name, serverUser);
-    return new GroupReference(groupUuid, name);
-  }
-
-  private InternalGroupCreation getGroupCreation(Sequences seqs, GroupReference groupReference)
-      throws OrmException {
-    int next = seqs.nextGroupId();
-    return InternalGroupCreation.builder()
-        .setNameKey(new AccountGroup.NameKey(groupReference.getName()))
-        .setId(new AccountGroup.Id(next))
-        .setGroupUUID(groupReference.getUUID())
-        .build();
-  }
-}
diff --git a/java/com/google/gerrit/server/schema/SchemaModule.java b/java/com/google/gerrit/server/schema/SchemaModule.java
deleted file mode 100644
index 9ce19fe..0000000
--- a/java/com/google/gerrit/server/schema/SchemaModule.java
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.schema;
-
-import static com.google.inject.Scopes.SINGLETON;
-
-import com.google.gerrit.extensions.config.FactoryModule;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.GerritPersonIdentProvider;
-import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.config.AllProjectsNameProvider;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.config.AllUsersNameProvider;
-import com.google.gerrit.server.config.AnonymousCowardName;
-import com.google.gerrit.server.config.AnonymousCowardNameProvider;
-import com.google.gerrit.server.config.GerritServerId;
-import com.google.gerrit.server.config.GerritServerIdProvider;
-import org.eclipse.jgit.lib.PersonIdent;
-
-/** Validate the schema and connect to Git. */
-public class SchemaModule extends FactoryModule {
-  @Override
-  protected void configure() {
-    bind(PersonIdent.class)
-        .annotatedWith(GerritPersonIdent.class)
-        .toProvider(GerritPersonIdentProvider.class);
-
-    bind(AllProjectsName.class).toProvider(AllProjectsNameProvider.class).in(SINGLETON);
-
-    bind(AllUsersName.class).toProvider(AllUsersNameProvider.class).in(SINGLETON);
-
-    bind(String.class)
-        .annotatedWith(AnonymousCowardName.class)
-        .toProvider(AnonymousCowardNameProvider.class);
-
-    bind(String.class)
-        .annotatedWith(GerritServerId.class)
-        .toProvider(GerritServerIdProvider.class)
-        .in(SINGLETON);
-  }
-}
diff --git a/java/com/google/gerrit/server/schema/SchemaUpdater.java b/java/com/google/gerrit/server/schema/SchemaUpdater.java
deleted file mode 100644
index 5ead6aa..0000000
--- a/java/com/google/gerrit/server/schema/SchemaUpdater.java
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.schema;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.reviewdb.server.ReviewDbUtil;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.config.AnonymousCowardName;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.group.SystemGroupBackend;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.SchemaFactory;
-import com.google.inject.AbstractModule;
-import com.google.inject.Guice;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.Key;
-import com.google.inject.Provider;
-import com.google.inject.Stage;
-import java.io.IOException;
-import java.sql.SQLException;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.PersonIdent;
-
-/** Creates or updates the current database schema. */
-public class SchemaUpdater {
-  private final SchemaFactory<ReviewDb> schema;
-  private final SchemaCreator creator;
-  private final Provider<SchemaVersion> updater;
-
-  @Inject
-  SchemaUpdater(
-      @ReviewDbFactory SchemaFactory<ReviewDb> schema, SchemaCreator creator, Injector parent) {
-    this.schema = schema;
-    this.creator = creator;
-    this.updater = buildInjector(parent).getProvider(SchemaVersion.class);
-  }
-
-  private static Injector buildInjector(Injector parent) {
-    // Use DEVELOPMENT mode to allow lazy initialization of the
-    // graph. This avoids touching ancient schema versions that
-    // are behind this installation's current version.
-    return Guice.createInjector(
-        Stage.DEVELOPMENT,
-        new AbstractModule() {
-          @Override
-          protected void configure() {
-            bind(SchemaVersion.class).to(SchemaVersion.C);
-
-            for (Key<?> k :
-                new Key<?>[] {
-                  Key.get(PersonIdent.class, GerritPersonIdent.class),
-                  Key.get(String.class, AnonymousCowardName.class),
-                  Key.get(Config.class, GerritServerConfig.class),
-                }) {
-              rebind(parent, k);
-            }
-
-            for (Class<?> c :
-                new Class<?>[] {
-                  AllProjectsName.class,
-                  AllUsersCreator.class,
-                  AllUsersName.class,
-                  GitRepositoryManager.class,
-                  SitePaths.class,
-                  SystemGroupBackend.class,
-                }) {
-              rebind(parent, Key.get(c));
-            }
-          }
-
-          private <T> void rebind(Injector parent, Key<T> c) {
-            bind(c).toProvider(parent.getProvider(c));
-          }
-        });
-  }
-
-  public void update(UpdateUI ui) throws OrmException {
-    try (ReviewDb db = ReviewDbUtil.unwrapDb(schema.open())) {
-
-      final SchemaVersion u = updater.get();
-      final CurrentSchemaVersion version = getSchemaVersion(db);
-      if (version == null) {
-        try {
-          creator.create(db);
-        } catch (IOException | ConfigInvalidException e) {
-          throw new OrmException("Cannot initialize schema", e);
-        }
-
-      } else {
-        try {
-          u.check(ui, version, db);
-        } catch (SQLException e) {
-          throw new OrmException("Cannot upgrade schema", e);
-        }
-      }
-    }
-  }
-
-  @VisibleForTesting
-  public SchemaVersion getLatestSchemaVersion() {
-    return updater.get();
-  }
-
-  private CurrentSchemaVersion getSchemaVersion(ReviewDb db) {
-    try {
-      return db.schemaVersion().get(new CurrentSchemaVersion.Key());
-    } catch (OrmException e) {
-      return null;
-    }
-  }
-}
diff --git a/java/com/google/gerrit/server/schema/SchemaVersion.java b/java/com/google/gerrit/server/schema/SchemaVersion.java
deleted file mode 100644
index 44533c9..0000000
--- a/java/com/google/gerrit/server/schema/SchemaVersion.java
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.schema;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Stopwatch;
-import com.google.common.collect.Lists;
-import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.UsedAt;
-import com.google.gwtorm.jdbc.JdbcExecutor;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.StatementExecutor;
-import com.google.inject.Provider;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-/** A version of the database schema. */
-public abstract class SchemaVersion {
-  /** The current schema version. */
-  public static final Class<Schema_170> C = Schema_170.class;
-
-  public static int getBinaryVersion() {
-    return guessVersion(C);
-  }
-
-  private final Provider<? extends SchemaVersion> prior;
-  private final int versionNbr;
-
-  protected SchemaVersion(Provider<? extends SchemaVersion> prior) {
-    this.prior = prior;
-    this.versionNbr = guessVersion(getClass());
-  }
-
-  @UsedAt(UsedAt.Project.PLUGIN_DELETE_PROJECT)
-  public static int guessVersion(Class<?> c) {
-    String n = c.getName();
-    n = n.substring(n.lastIndexOf('_') + 1);
-    while (n.startsWith("0")) {
-      n = n.substring(1);
-    }
-    return Integer.parseInt(n);
-  }
-
-  /** @return the {@link CurrentSchemaVersion#versionNbr} this step targets. */
-  public final int getVersionNbr() {
-    return versionNbr;
-  }
-
-  @VisibleForTesting
-  public final SchemaVersion getPrior() {
-    return prior.get();
-  }
-
-  public final void check(UpdateUI ui, CurrentSchemaVersion curr, ReviewDb db)
-      throws OrmException, SQLException {
-    if (curr.versionNbr == versionNbr) {
-      // Nothing to do, we are at the correct schema.
-    } else if (curr.versionNbr > versionNbr) {
-      throw new OrmException(
-          "Cannot downgrade database schema from version "
-              + curr.versionNbr
-              + " to "
-              + versionNbr
-              + ".");
-    } else {
-      upgradeFrom(ui, curr, db);
-    }
-  }
-
-  /** Runs check on the prior schema version, and then upgrades. */
-  private void upgradeFrom(UpdateUI ui, CurrentSchemaVersion curr, ReviewDb db)
-      throws OrmException, SQLException {
-    List<SchemaVersion> pending = pending(curr.versionNbr);
-    updateSchema(pending, ui, db);
-    migrateData(pending, ui, curr, db);
-
-    JdbcSchema s = (JdbcSchema) db;
-    final List<String> pruneList = new ArrayList<>();
-    s.pruneSchema(
-        new StatementExecutor() {
-          @Override
-          public void execute(String sql) {
-            pruneList.add(sql);
-          }
-
-          @Override
-          public void close() {
-            // Do nothing.
-          }
-        });
-
-    try (JdbcExecutor e = new JdbcExecutor(s)) {
-      if (!pruneList.isEmpty()) {
-        ui.pruneSchema(e, pruneList);
-      }
-    }
-  }
-
-  private List<SchemaVersion> pending(int curr) {
-    List<SchemaVersion> r = Lists.newArrayListWithCapacity(versionNbr - curr);
-    for (SchemaVersion v = this; curr < v.getVersionNbr(); v = v.prior.get()) {
-      r.add(v);
-    }
-    Collections.reverse(r);
-    return r;
-  }
-
-  private void updateSchema(List<SchemaVersion> pending, UpdateUI ui, ReviewDb db)
-      throws OrmException, SQLException {
-    for (SchemaVersion v : pending) {
-      ui.message(String.format("Upgrading schema to %d ...", v.getVersionNbr()));
-      v.preUpdateSchema(db);
-    }
-
-    JdbcSchema s = (JdbcSchema) db;
-    try (JdbcExecutor e = new JdbcExecutor(s)) {
-      s.updateSchema(e);
-    }
-  }
-
-  /**
-   * Invoked before updateSchema adds new columns/tables.
-   *
-   * @param db open database handle.
-   * @throws OrmException if a Gerrit-specific exception occurred.
-   * @throws SQLException if an underlying SQL exception occurred.
-   */
-  protected void preUpdateSchema(ReviewDb db) throws OrmException, SQLException {}
-
-  private void migrateData(
-      List<SchemaVersion> pending, UpdateUI ui, CurrentSchemaVersion curr, ReviewDb db)
-      throws OrmException, SQLException {
-    for (SchemaVersion v : pending) {
-      Stopwatch sw = Stopwatch.createStarted();
-      ui.message(String.format("Migrating data to schema %d ...", v.getVersionNbr()));
-      v.migrateData(db, ui);
-      v.finish(curr, db);
-      ui.message(String.format("\t> Done (%.3f s)", sw.elapsed(TimeUnit.MILLISECONDS) / 1000d));
-    }
-  }
-
-  /**
-   * Invoked between updateSchema (adds new columns/tables) and pruneSchema (removes deleted
-   * columns/tables).
-   *
-   * @param db open database handle.
-   * @param ui interface for interacting with the user.
-   * @throws OrmException if a Gerrit-specific exception occurred.
-   * @throws SQLException if an underlying SQL exception occurred.
-   */
-  protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {}
-
-  /** Mark the current schema version. */
-  protected void finish(CurrentSchemaVersion curr, ReviewDb db) throws OrmException {
-    curr.versionNbr = versionNbr;
-    db.schemaVersion().update(Collections.singleton(curr));
-  }
-
-  /** Rename an existing table. */
-  protected static void renameTable(ReviewDb db, String from, String to) throws OrmException {
-    JdbcSchema s = (JdbcSchema) db;
-    try (JdbcExecutor e = new JdbcExecutor(s)) {
-      s.renameTable(e, from, to);
-    }
-  }
-
-  /** Rename an existing column. */
-  protected static void renameColumn(ReviewDb db, String table, String from, String to)
-      throws OrmException {
-    JdbcSchema s = (JdbcSchema) db;
-    try (JdbcExecutor e = new JdbcExecutor(s)) {
-      s.renameColumn(e, table, from, to);
-    }
-  }
-
-  /** Execute an SQL statement. */
-  protected static void execute(ReviewDb db, String sql) throws SQLException {
-    try (Statement s = newStatement(db)) {
-      s.execute(sql);
-    }
-  }
-
-  /** Open a new single statement. */
-  protected static Statement newStatement(ReviewDb db) throws SQLException {
-    return ((JdbcSchema) db).getConnection().createStatement();
-  }
-
-  /** Open a new prepared statement. */
-  protected static PreparedStatement prepareStatement(ReviewDb db, String sql) throws SQLException {
-    return ((JdbcSchema) db).getConnection().prepareStatement(sql);
-  }
-
-  /** Open a new statement executor. */
-  protected static JdbcExecutor newExecutor(ReviewDb db) throws OrmException {
-    return new JdbcExecutor(((JdbcSchema) db).getConnection());
-  }
-}
diff --git a/java/com/google/gerrit/server/schema/SchemaVersionCheck.java b/java/com/google/gerrit/server/schema/SchemaVersionCheck.java
deleted file mode 100644
index bdc15f4..0000000
--- a/java/com/google/gerrit/server/schema/SchemaVersionCheck.java
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.schema;
-
-import com.google.gerrit.extensions.events.LifecycleListener;
-import com.google.gerrit.lifecycle.LifecycleModule;
-import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.SchemaFactory;
-import com.google.inject.Inject;
-import com.google.inject.Module;
-import com.google.inject.ProvisionException;
-
-/** Validates the current schema version. */
-public class SchemaVersionCheck implements LifecycleListener {
-  public static Module module() {
-    return new LifecycleModule() {
-      @Override
-      protected void configure() {
-        listener().to(SchemaVersionCheck.class);
-      }
-    };
-  }
-
-  private final SchemaFactory<ReviewDb> schema;
-  private final SitePaths site;
-
-  @Inject
-  public SchemaVersionCheck(SchemaFactory<ReviewDb> schemaFactory, SitePaths site) {
-    this.schema = schemaFactory;
-    this.site = site;
-  }
-
-  @Override
-  public void start() {
-    try (ReviewDb db = schema.open()) {
-      final CurrentSchemaVersion currentVer = getSchemaVersion(db);
-      final int expectedVer = SchemaVersion.getBinaryVersion();
-
-      if (currentVer == null) {
-        throw new ProvisionException(
-            "Schema not yet initialized."
-                + "  Run init to initialize the schema:\n"
-                + "$ java -jar gerrit.war init -d "
-                + site.site_path.toAbsolutePath());
-      }
-      if (currentVer.versionNbr < expectedVer) {
-        throw new ProvisionException(
-            "Unsupported schema version "
-                + currentVer.versionNbr
-                + "; expected schema version "
-                + expectedVer
-                + ".  Run init to upgrade:\n"
-                + "$ java -jar "
-                + site.gerrit_war.toAbsolutePath()
-                + " init -d "
-                + site.site_path.toAbsolutePath());
-      } else if (currentVer.versionNbr > expectedVer) {
-        throw new ProvisionException(
-            "Unsupported schema version "
-                + currentVer.versionNbr
-                + "; expected schema version "
-                + expectedVer
-                + ". Downgrade is not supported.");
-      }
-    } catch (OrmException e) {
-      throw new ProvisionException("Cannot read schema_version", e);
-    }
-  }
-
-  @Override
-  public void stop() {}
-
-  private CurrentSchemaVersion getSchemaVersion(ReviewDb db) {
-    try {
-      return db.schemaVersion().get(new CurrentSchemaVersion.Key());
-    } catch (OrmException e) {
-      return null;
-    }
-  }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_100.java b/java/com/google/gerrit/server/schema/Schema_100.java
index 0902194..b5105a9 100644
--- a/java/com/google/gerrit/server/schema/Schema_100.java
+++ b/java/com/google/gerrit/server/schema/Schema_100.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_100 extends SchemaVersion {
+public class Schema_100 extends ReviewDbSchemaVersion {
   @Inject
   Schema_100(Provider<Schema_99> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_101.java b/java/com/google/gerrit/server/schema/Schema_101.java
index ccbb2de..753d992 100644
--- a/java/com/google/gerrit/server/schema/Schema_101.java
+++ b/java/com/google/gerrit/server/schema/Schema_101.java
@@ -38,7 +38,7 @@
 import java.util.Map;
 import java.util.TreeMap;
 
-public class Schema_101 extends SchemaVersion {
+public class Schema_101 extends ReviewDbSchemaVersion {
 
   private static class PrimaryKey {
     String oldNameInDb;
diff --git a/java/com/google/gerrit/server/schema/Schema_102.java b/java/com/google/gerrit/server/schema/Schema_102.java
index 1c1aa55..2bd52c2 100644
--- a/java/com/google/gerrit/server/schema/Schema_102.java
+++ b/java/com/google/gerrit/server/schema/Schema_102.java
@@ -26,7 +26,7 @@
 import java.util.Set;
 import java.util.regex.Pattern;
 
-public class Schema_102 extends SchemaVersion {
+public class Schema_102 extends ReviewDbSchemaVersion {
   @Inject
   Schema_102(Provider<Schema_101> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_103.java b/java/com/google/gerrit/server/schema/Schema_103.java
index 60a5213..1906b66 100644
--- a/java/com/google/gerrit/server/schema/Schema_103.java
+++ b/java/com/google/gerrit/server/schema/Schema_103.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_103 extends SchemaVersion {
+public class Schema_103 extends ReviewDbSchemaVersion {
   @Inject
   Schema_103(Provider<Schema_102> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_104.java b/java/com/google/gerrit/server/schema/Schema_104.java
index bebdaca..9b4d67c 100644
--- a/java/com/google/gerrit/server/schema/Schema_104.java
+++ b/java/com/google/gerrit/server/schema/Schema_104.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_104 extends SchemaVersion {
+public class Schema_104 extends ReviewDbSchemaVersion {
   @Inject
   Schema_104(Provider<Schema_103> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_105.java b/java/com/google/gerrit/server/schema/Schema_105.java
index dd5e71a7..56e19ef 100644
--- a/java/com/google/gerrit/server/schema/Schema_105.java
+++ b/java/com/google/gerrit/server/schema/Schema_105.java
@@ -28,7 +28,7 @@
 import java.util.Map;
 import java.util.Set;
 
-public class Schema_105 extends SchemaVersion {
+public class Schema_105 extends ReviewDbSchemaVersion {
   private static final String TABLE = "changes";
 
   @Inject
diff --git a/java/com/google/gerrit/server/schema/Schema_106.java b/java/com/google/gerrit/server/schema/Schema_106.java
index 5bb3669..a3f99fc 100644
--- a/java/com/google/gerrit/server/schema/Schema_106.java
+++ b/java/com/google/gerrit/server/schema/Schema_106.java
@@ -40,7 +40,7 @@
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.lib.Repository;
 
-public class Schema_106 extends SchemaVersion {
+public class Schema_106 extends ReviewDbSchemaVersion {
   // we can use multiple threads per CPU as we can expect that threads will be
   // waiting for IO
   private static final int THREADS_PER_CPU = 4;
diff --git a/java/com/google/gerrit/server/schema/Schema_107.java b/java/com/google/gerrit/server/schema/Schema_107.java
index dd8868f..bef8c65 100644
--- a/java/com/google/gerrit/server/schema/Schema_107.java
+++ b/java/com/google/gerrit/server/schema/Schema_107.java
@@ -21,7 +21,7 @@
 import java.sql.SQLException;
 import java.sql.Statement;
 
-public class Schema_107 extends SchemaVersion {
+public class Schema_107 extends ReviewDbSchemaVersion {
 
   @Inject
   Schema_107(Provider<Schema_106> prior) {
diff --git a/java/com/google/gerrit/server/schema/Schema_108.java b/java/com/google/gerrit/server/schema/Schema_108.java
index 4e62460..b2ab042 100644
--- a/java/com/google/gerrit/server/schema/Schema_108.java
+++ b/java/com/google/gerrit/server/schema/Schema_108.java
@@ -24,7 +24,6 @@
 import com.google.gerrit.reviewdb.client.Change.Status;
 import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.client.Project.NameKey;
 import com.google.gerrit.reviewdb.client.RefNames;
 import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.git.GitRepositoryManager;
@@ -49,7 +48,7 @@
 import org.eclipse.jgit.revwalk.RevSort;
 import org.eclipse.jgit.revwalk.RevWalk;
 
-public class Schema_108 extends SchemaVersion {
+public class Schema_108 extends ReviewDbSchemaVersion {
   private final GitRepositoryManager repoManager;
 
   @Inject
@@ -145,8 +144,8 @@
 
   private SetMultimap<Project.NameKey, Change.Id> getOpenChangesByProject(ReviewDb db, UpdateUI ui)
       throws OrmException {
-    SortedSet<NameKey> projects = repoManager.list();
-    SortedSet<NameKey> nonExistentProjects = Sets.newTreeSet();
+    SortedSet<Project.NameKey> projects = repoManager.list();
+    SortedSet<Project.NameKey> nonExistentProjects = Sets.newTreeSet();
     SetMultimap<Project.NameKey, Change.Id> openByProject =
         MultimapBuilder.hashKeys().hashSetValues().build();
     for (Change c : db.changes().all()) {
@@ -155,7 +154,7 @@
         continue;
       }
 
-      NameKey projectKey = c.getProject();
+      Project.NameKey projectKey = c.getProject();
       if (!projects.contains(projectKey)) {
         nonExistentProjects.add(projectKey);
       } else {
diff --git a/java/com/google/gerrit/server/schema/Schema_109.java b/java/com/google/gerrit/server/schema/Schema_109.java
index c5a6015..f582741 100644
--- a/java/com/google/gerrit/server/schema/Schema_109.java
+++ b/java/com/google/gerrit/server/schema/Schema_109.java
@@ -20,7 +20,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_109 extends SchemaVersion {
+public class Schema_109 extends ReviewDbSchemaVersion {
   @Inject
   Schema_109(Provider<Schema_108> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_110.java b/java/com/google/gerrit/server/schema/Schema_110.java
index 9e0f112..6da10f6 100644
--- a/java/com/google/gerrit/server/schema/Schema_110.java
+++ b/java/com/google/gerrit/server/schema/Schema_110.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_110 extends SchemaVersion {
+public class Schema_110 extends ReviewDbSchemaVersion {
   @Inject
   Schema_110(Provider<Schema_109> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_111.java b/java/com/google/gerrit/server/schema/Schema_111.java
index 223fdb6..7ba48c2 100644
--- a/java/com/google/gerrit/server/schema/Schema_111.java
+++ b/java/com/google/gerrit/server/schema/Schema_111.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_111 extends SchemaVersion {
+public class Schema_111 extends ReviewDbSchemaVersion {
   @Inject
   Schema_111(Provider<Schema_110> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_112.java b/java/com/google/gerrit/server/schema/Schema_112.java
index 3e879bd..5a764d0 100644
--- a/java/com/google/gerrit/server/schema/Schema_112.java
+++ b/java/com/google/gerrit/server/schema/Schema_112.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_112 extends SchemaVersion {
+public class Schema_112 extends ReviewDbSchemaVersion {
   @Inject
   Schema_112(Provider<Schema_111> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_113.java b/java/com/google/gerrit/server/schema/Schema_113.java
index 32d655e..2876636 100644
--- a/java/com/google/gerrit/server/schema/Schema_113.java
+++ b/java/com/google/gerrit/server/schema/Schema_113.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_113 extends SchemaVersion {
+public class Schema_113 extends ReviewDbSchemaVersion {
   @Inject
   Schema_113(Provider<Schema_112> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_114.java b/java/com/google/gerrit/server/schema/Schema_114.java
index 85c93d2..7bee00c 100644
--- a/java/com/google/gerrit/server/schema/Schema_114.java
+++ b/java/com/google/gerrit/server/schema/Schema_114.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_114 extends SchemaVersion {
+public class Schema_114 extends ReviewDbSchemaVersion {
   @Inject
   Schema_114(Provider<Schema_113> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_115.java b/java/com/google/gerrit/server/schema/Schema_115.java
index 70bc921..28cfe22 100644
--- a/java/com/google/gerrit/server/schema/Schema_115.java
+++ b/java/com/google/gerrit/server/schema/Schema_115.java
@@ -51,7 +51,7 @@
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.revwalk.RevWalk;
 
-public class Schema_115 extends SchemaVersion {
+public class Schema_115 extends ReviewDbSchemaVersion {
   private final GitRepositoryManager mgr;
   private final AllUsersName allUsersName;
   private final PersonIdent serverUser;
diff --git a/java/com/google/gerrit/server/schema/Schema_116.java b/java/com/google/gerrit/server/schema/Schema_116.java
index 5b018a2..5174d92 100644
--- a/java/com/google/gerrit/server/schema/Schema_116.java
+++ b/java/com/google/gerrit/server/schema/Schema_116.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_116 extends SchemaVersion {
+public class Schema_116 extends ReviewDbSchemaVersion {
   @Inject
   Schema_116(Provider<Schema_115> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_117.java b/java/com/google/gerrit/server/schema/Schema_117.java
index 35e6c8a..d848bec 100644
--- a/java/com/google/gerrit/server/schema/Schema_117.java
+++ b/java/com/google/gerrit/server/schema/Schema_117.java
@@ -24,7 +24,7 @@
 import java.sql.Statement;
 import java.util.Set;
 
-public class Schema_117 extends SchemaVersion {
+public class Schema_117 extends ReviewDbSchemaVersion {
   @Inject
   Schema_117(Provider<Schema_116> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_118.java b/java/com/google/gerrit/server/schema/Schema_118.java
index 8c2c740..e55afda 100644
--- a/java/com/google/gerrit/server/schema/Schema_118.java
+++ b/java/com/google/gerrit/server/schema/Schema_118.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_118 extends SchemaVersion {
+public class Schema_118 extends ReviewDbSchemaVersion {
   @Inject
   Schema_118(Provider<Schema_117> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_119.java b/java/com/google/gerrit/server/schema/Schema_119.java
index e5a6405..9423d81 100644
--- a/java/com/google/gerrit/server/schema/Schema_119.java
+++ b/java/com/google/gerrit/server/schema/Schema_119.java
@@ -58,7 +58,7 @@
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.revwalk.RevWalk;
 
-public class Schema_119 extends SchemaVersion {
+public class Schema_119 extends ReviewDbSchemaVersion {
   private static final ImmutableMap<String, String> LEGACY_DISPLAYNAME_MAP =
       ImmutableMap.<String, String>of(
           "ANON_GIT", ANON_GIT,
diff --git a/java/com/google/gerrit/server/schema/Schema_120.java b/java/com/google/gerrit/server/schema/Schema_120.java
index f2f3b99..9a1c15b 100644
--- a/java/com/google/gerrit/server/schema/Schema_120.java
+++ b/java/com/google/gerrit/server/schema/Schema_120.java
@@ -39,18 +39,21 @@
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.transport.RefSpec;
 
-public class Schema_120 extends SchemaVersion {
+public class Schema_120 extends ReviewDbSchemaVersion {
 
   private final GitRepositoryManager mgr;
+  private final ProjectConfig.Factory projectConfigFactory;
   private final PersonIdent serverUser;
 
   @Inject
   Schema_120(
       Provider<Schema_119> prior,
       GitRepositoryManager mgr,
+      ProjectConfig.Factory projectConfigFactory,
       @GerritPersonIdent PersonIdent serverUser) {
     super(prior);
     this.mgr = mgr;
+    this.projectConfigFactory = projectConfigFactory;
     this.serverUser = serverUser;
   }
 
@@ -64,7 +67,7 @@
         md.getCommitBuilder().setAuthor(serverUser);
         md.getCommitBuilder().setCommitter(serverUser);
         md.setMessage("Added superproject subscription during upgrade");
-        ProjectConfig pc = ProjectConfig.read(md);
+        ProjectConfig pc = projectConfigFactory.read(md);
 
         SubscribeSection s = null;
         for (SubscribeSection s1 : pc.getSubscribeSections(subbranch)) {
diff --git a/java/com/google/gerrit/server/schema/Schema_121.java b/java/com/google/gerrit/server/schema/Schema_121.java
index 31b42fb..bb994ef 100644
--- a/java/com/google/gerrit/server/schema/Schema_121.java
+++ b/java/com/google/gerrit/server/schema/Schema_121.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_121 extends SchemaVersion {
+public class Schema_121 extends ReviewDbSchemaVersion {
   @Inject
   Schema_121(Provider<Schema_120> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_122.java b/java/com/google/gerrit/server/schema/Schema_122.java
index b5b799d..cce1419 100644
--- a/java/com/google/gerrit/server/schema/Schema_122.java
+++ b/java/com/google/gerrit/server/schema/Schema_122.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_122 extends SchemaVersion {
+public class Schema_122 extends ReviewDbSchemaVersion {
   @Inject
   Schema_122(Provider<Schema_121> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_123.java b/java/com/google/gerrit/server/schema/Schema_123.java
index 31cfd5d..cd84188 100644
--- a/java/com/google/gerrit/server/schema/Schema_123.java
+++ b/java/com/google/gerrit/server/schema/Schema_123.java
@@ -40,7 +40,7 @@
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.transport.ReceiveCommand;
 
-public class Schema_123 extends SchemaVersion {
+public class Schema_123 extends ReviewDbSchemaVersion {
   private final GitRepositoryManager repoManager;
   private final AllUsersName allUsersName;
 
diff --git a/java/com/google/gerrit/server/schema/Schema_124.java b/java/com/google/gerrit/server/schema/Schema_124.java
index 6164fd1..7e2fa42 100644
--- a/java/com/google/gerrit/server/schema/Schema_124.java
+++ b/java/com/google/gerrit/server/schema/Schema_124.java
@@ -50,7 +50,7 @@
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.revwalk.RevWalk;
 
-public class Schema_124 extends SchemaVersion {
+public class Schema_124 extends ReviewDbSchemaVersion {
   private final GitRepositoryManager repoManager;
   private final AllUsersName allUsersName;
   private final PersonIdent serverUser;
diff --git a/java/com/google/gerrit/server/schema/Schema_125.java b/java/com/google/gerrit/server/schema/Schema_125.java
index 7aab7c7..cc0d9e7 100644
--- a/java/com/google/gerrit/server/schema/Schema_125.java
+++ b/java/com/google/gerrit/server/schema/Schema_125.java
@@ -44,7 +44,7 @@
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.lib.Repository;
 
-public class Schema_125 extends SchemaVersion {
+public class Schema_125 extends ReviewDbSchemaVersion {
   private static final String COMMIT_MSG =
       "Assign default permissions on user branches\n"
           + "\n"
@@ -57,6 +57,7 @@
   private final AllUsersName allUsersName;
   private final AllProjectsName allProjectsName;
   private final SystemGroupBackend systemGroupBackend;
+  private final ProjectConfig.Factory projectConfigFactory;
   private final PersonIdent serverUser;
 
   @Inject
@@ -66,12 +67,14 @@
       AllUsersName allUsersName,
       AllProjectsName allProjectsName,
       SystemGroupBackend systemGroupBackend,
+      ProjectConfig.Factory projectConfigFactory,
       @GerritPersonIdent PersonIdent serverUser) {
     super(prior);
     this.repoManager = repoManager;
     this.allUsersName = allUsersName;
     this.allProjectsName = allProjectsName;
     this.systemGroupBackend = systemGroupBackend;
+    this.projectConfigFactory = projectConfigFactory;
     this.serverUser = serverUser;
   }
 
@@ -79,7 +82,7 @@
   protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
     try (Repository git = repoManager.openRepository(allUsersName);
         MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, git)) {
-      ProjectConfig config = ProjectConfig.read(md);
+      ProjectConfig config = projectConfigFactory.read(md);
 
       config
           .getAccessSection(RefNames.REFS_USERS + "*", true)
@@ -114,7 +117,7 @@
     while (parent != null) {
       try (Repository git = repoManager.openRepository(parent);
           MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, parent, git)) {
-        ProjectConfig parentConfig = ProjectConfig.read(md);
+        ProjectConfig parentConfig = projectConfigFactory.read(md);
         for (LabelType lt : parentConfig.getLabelSections().values()) {
           if (!labelTypes.containsKey(lt.getName())) {
             labelTypes.put(lt.getName(), lt);
diff --git a/java/com/google/gerrit/server/schema/Schema_126.java b/java/com/google/gerrit/server/schema/Schema_126.java
index 5dbda72..f3004ba 100644
--- a/java/com/google/gerrit/server/schema/Schema_126.java
+++ b/java/com/google/gerrit/server/schema/Schema_126.java
@@ -38,12 +38,13 @@
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.lib.Repository;
 
-public class Schema_126 extends SchemaVersion {
+public class Schema_126 extends ReviewDbSchemaVersion {
   private static final String COMMIT_MSG = "Fix default permissions on user branches";
 
   private final GitRepositoryManager repoManager;
   private final AllUsersName allUsersName;
   private final SystemGroupBackend systemGroupBackend;
+  private final ProjectConfig.Factory projectConfigFactory;
   private final PersonIdent serverUser;
 
   @Inject
@@ -52,11 +53,13 @@
       GitRepositoryManager repoManager,
       AllUsersName allUsersName,
       SystemGroupBackend systemGroupBackend,
+      ProjectConfig.Factory projectConfigFactory,
       @GerritPersonIdent PersonIdent serverUser) {
     super(prior);
     this.repoManager = repoManager;
     this.allUsersName = allUsersName;
     this.systemGroupBackend = systemGroupBackend;
+    this.projectConfigFactory = projectConfigFactory;
     this.serverUser = serverUser;
   }
 
@@ -64,7 +67,7 @@
   protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
     try (Repository git = repoManager.openRepository(allUsersName);
         MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, git)) {
-      ProjectConfig config = ProjectConfig.read(md);
+      ProjectConfig config = projectConfigFactory.read(md);
 
       String refsUsersShardedId = RefNames.REFS_USERS + "${" + RefPattern.USERID_SHARDED + "}";
       config.remove(config.getAccessSection(refsUsersShardedId));
diff --git a/java/com/google/gerrit/server/schema/Schema_127.java b/java/com/google/gerrit/server/schema/Schema_127.java
index d246b75..8e4175c 100644
--- a/java/com/google/gerrit/server/schema/Schema_127.java
+++ b/java/com/google/gerrit/server/schema/Schema_127.java
@@ -28,7 +28,7 @@
 import java.sql.Statement;
 import org.eclipse.jgit.lib.Config;
 
-public class Schema_127 extends SchemaVersion {
+public class Schema_127 extends ReviewDbSchemaVersion {
   private static final int MAX_BATCH_SIZE = 1000;
 
   private final SitePaths sitePaths;
diff --git a/java/com/google/gerrit/server/schema/Schema_128.java b/java/com/google/gerrit/server/schema/Schema_128.java
index bd6b76a..cd2718b 100644
--- a/java/com/google/gerrit/server/schema/Schema_128.java
+++ b/java/com/google/gerrit/server/schema/Schema_128.java
@@ -36,12 +36,13 @@
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.lib.Repository;
 
-public class Schema_128 extends SchemaVersion {
+public class Schema_128 extends ReviewDbSchemaVersion {
   private static final String COMMIT_MSG = "Add addPatchSet permission to all projects";
 
   private final GitRepositoryManager repoManager;
   private final AllProjectsName allProjectsName;
   private final SystemGroupBackend systemGroupBackend;
+  private final ProjectConfig.Factory projectConfigFactory;
   private final PersonIdent serverUser;
 
   @Inject
@@ -50,11 +51,13 @@
       GitRepositoryManager repoManager,
       AllProjectsName allProjectsName,
       SystemGroupBackend systemGroupBackend,
+      ProjectConfig.Factory projectConfigFactory,
       @GerritPersonIdent PersonIdent serverUser) {
     super(prior);
     this.repoManager = repoManager;
     this.allProjectsName = allProjectsName;
     this.systemGroupBackend = systemGroupBackend;
+    this.projectConfigFactory = projectConfigFactory;
     this.serverUser = serverUser;
   }
 
@@ -63,7 +66,7 @@
     try (Repository git = repoManager.openRepository(allProjectsName);
         MetaDataUpdate md =
             new MetaDataUpdate(GitReferenceUpdated.DISABLED, allProjectsName, git)) {
-      ProjectConfig config = ProjectConfig.read(md);
+      ProjectConfig config = projectConfigFactory.read(md);
 
       GroupReference registered = systemGroupBackend.getGroup(REGISTERED_USERS);
       AccessSection refsFor = config.getAccessSection("refs/for/*", true);
diff --git a/java/com/google/gerrit/server/schema/Schema_129.java b/java/com/google/gerrit/server/schema/Schema_129.java
index 73ce3c3..f7cd8c3 100644
--- a/java/com/google/gerrit/server/schema/Schema_129.java
+++ b/java/com/google/gerrit/server/schema/Schema_129.java
@@ -22,7 +22,7 @@
 import java.sql.SQLException;
 import java.sql.Statement;
 
-public class Schema_129 extends SchemaVersion {
+public class Schema_129 extends ReviewDbSchemaVersion {
 
   @Inject
   Schema_129(Provider<Schema_128> prior) {
diff --git a/java/com/google/gerrit/server/schema/Schema_130.java b/java/com/google/gerrit/server/schema/Schema_130.java
index 66f2177..0c9d79d 100644
--- a/java/com/google/gerrit/server/schema/Schema_130.java
+++ b/java/com/google/gerrit/server/schema/Schema_130.java
@@ -32,7 +32,7 @@
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.lib.Repository;
 
-public class Schema_130 extends SchemaVersion {
+public class Schema_130 extends ReviewDbSchemaVersion {
   private static final String COMMIT_MSG =
       "Remove force option from 'Push Annotated Tag' permission\n"
           + "\n"
diff --git a/java/com/google/gerrit/server/schema/Schema_131.java b/java/com/google/gerrit/server/schema/Schema_131.java
index 3755211..b37ae4b 100644
--- a/java/com/google/gerrit/server/schema/Schema_131.java
+++ b/java/com/google/gerrit/server/schema/Schema_131.java
@@ -33,20 +33,23 @@
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.lib.Repository;
 
-public class Schema_131 extends SchemaVersion {
+public class Schema_131 extends ReviewDbSchemaVersion {
   private static final String COMMIT_MSG =
       "Rename 'Push Annotated/Signed Tag' permission to 'Create Annotated/Signed Tag'";
 
   private final GitRepositoryManager repoManager;
+  private final ProjectConfig.Factory projectConfigFactory;
   private final PersonIdent serverUser;
 
   @Inject
   Schema_131(
       Provider<Schema_130> prior,
       GitRepositoryManager repoManager,
+      ProjectConfig.Factory projectConfigFactory,
       @GerritPersonIdent PersonIdent serverUser) {
     super(prior);
     this.repoManager = repoManager;
+    this.projectConfigFactory = projectConfigFactory;
     this.serverUser = serverUser;
   }
 
@@ -58,7 +61,7 @@
     for (Project.NameKey projectName : repoList) {
       try (Repository git = repoManager.openRepository(projectName);
           MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, projectName, git)) {
-        ProjectConfig config = ProjectConfig.read(md);
+        ProjectConfig config = projectConfigFactory.read(md);
         if (config.hasLegacyPermissions()) {
           md.getCommitBuilder().setAuthor(serverUser);
           md.getCommitBuilder().setCommitter(serverUser);
diff --git a/java/com/google/gerrit/server/schema/Schema_132.java b/java/com/google/gerrit/server/schema/Schema_132.java
index 7c1cde8..72ec590 100644
--- a/java/com/google/gerrit/server/schema/Schema_132.java
+++ b/java/com/google/gerrit/server/schema/Schema_132.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_132 extends SchemaVersion {
+public class Schema_132 extends ReviewDbSchemaVersion {
   @Inject
   Schema_132(Provider<Schema_131> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_133.java b/java/com/google/gerrit/server/schema/Schema_133.java
index 31d330b..29cd6e9 100644
--- a/java/com/google/gerrit/server/schema/Schema_133.java
+++ b/java/com/google/gerrit/server/schema/Schema_133.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_133 extends SchemaVersion {
+public class Schema_133 extends ReviewDbSchemaVersion {
   @Inject
   Schema_133(Provider<Schema_132> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_134.java b/java/com/google/gerrit/server/schema/Schema_134.java
index fa01ff3..298ac03 100644
--- a/java/com/google/gerrit/server/schema/Schema_134.java
+++ b/java/com/google/gerrit/server/schema/Schema_134.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_134 extends SchemaVersion {
+public class Schema_134 extends ReviewDbSchemaVersion {
   @Inject
   Schema_134(Provider<Schema_133> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_135.java b/java/com/google/gerrit/server/schema/Schema_135.java
index 66224c2..03ef84a 100644
--- a/java/com/google/gerrit/server/schema/Schema_135.java
+++ b/java/com/google/gerrit/server/schema/Schema_135.java
@@ -41,13 +41,14 @@
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.lib.Repository;
 
-public class Schema_135 extends SchemaVersion {
+public class Schema_135 extends ReviewDbSchemaVersion {
   private static final String COMMIT_MSG =
       "Allow admins and project owners to create refs/meta/config";
 
   private final GitRepositoryManager repoManager;
   private final AllProjectsName allProjectsName;
   private final SystemGroupBackend systemGroupBackend;
+  private final ProjectConfig.Factory projectConfigFactory;
   private final PersonIdent serverUser;
 
   @Inject
@@ -56,11 +57,13 @@
       GitRepositoryManager repoManager,
       AllProjectsName allProjectsName,
       SystemGroupBackend systemGroupBackend,
+      ProjectConfig.Factory projectConfigFactory,
       @GerritPersonIdent PersonIdent serverUser) {
     super(prior);
     this.repoManager = repoManager;
     this.allProjectsName = allProjectsName;
     this.systemGroupBackend = systemGroupBackend;
+    this.projectConfigFactory = projectConfigFactory;
     this.serverUser = serverUser;
   }
 
@@ -69,7 +72,7 @@
     try (Repository git = repoManager.openRepository(allProjectsName);
         MetaDataUpdate md =
             new MetaDataUpdate(GitReferenceUpdated.DISABLED, allProjectsName, git)) {
-      ProjectConfig config = ProjectConfig.read(md);
+      ProjectConfig config = projectConfigFactory.read(md);
 
       AccessSection meta = config.getAccessSection(RefNames.REFS_CONFIG, true);
       Permission createRefsMetaConfigPermission = meta.getPermission(Permission.CREATE, true);
diff --git a/java/com/google/gerrit/server/schema/Schema_136.java b/java/com/google/gerrit/server/schema/Schema_136.java
index a4b1c82..11eda7b 100644
--- a/java/com/google/gerrit/server/schema/Schema_136.java
+++ b/java/com/google/gerrit/server/schema/Schema_136.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_136 extends SchemaVersion {
+public class Schema_136 extends ReviewDbSchemaVersion {
   @Inject
   Schema_136(Provider<Schema_135> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_137.java b/java/com/google/gerrit/server/schema/Schema_137.java
index 1b4102f..a6ea83b 100644
--- a/java/com/google/gerrit/server/schema/Schema_137.java
+++ b/java/com/google/gerrit/server/schema/Schema_137.java
@@ -18,7 +18,7 @@
 import com.google.inject.Provider;
 
 /* change the type of SystemConfig#sitePath to CLOB */
-public class Schema_137 extends SchemaVersion {
+public class Schema_137 extends ReviewDbSchemaVersion {
   @Inject
   Schema_137(Provider<Schema_136> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_138.java b/java/com/google/gerrit/server/schema/Schema_138.java
index f824ee1..61d55ec 100644
--- a/java/com/google/gerrit/server/schema/Schema_138.java
+++ b/java/com/google/gerrit/server/schema/Schema_138.java
@@ -18,7 +18,7 @@
 import com.google.inject.Provider;
 
 /* Add resolved field to PatchLineComment */
-public class Schema_138 extends SchemaVersion {
+public class Schema_138 extends ReviewDbSchemaVersion {
   @Inject
   Schema_138(Provider<Schema_137> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_139.java b/java/com/google/gerrit/server/schema/Schema_139.java
index cdde7e4..a234be5 100644
--- a/java/com/google/gerrit/server/schema/Schema_139.java
+++ b/java/com/google/gerrit/server/schema/Schema_139.java
@@ -54,7 +54,7 @@
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.revwalk.RevWalk;
 
-public class Schema_139 extends SchemaVersion {
+public class Schema_139 extends ReviewDbSchemaVersion {
   private static final String MSG = "Migrate project watches to git";
 
   private final GitRepositoryManager repoManager;
diff --git a/java/com/google/gerrit/server/schema/Schema_140.java b/java/com/google/gerrit/server/schema/Schema_140.java
index bdc5f55..f59368c 100644
--- a/java/com/google/gerrit/server/schema/Schema_140.java
+++ b/java/com/google/gerrit/server/schema/Schema_140.java
@@ -18,7 +18,7 @@
 import com.google.inject.Provider;
 
 /** Remove ChangeMessage sequence. */
-public class Schema_140 extends SchemaVersion {
+public class Schema_140 extends ReviewDbSchemaVersion {
   @Inject
   Schema_140(Provider<Schema_139> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_141.java b/java/com/google/gerrit/server/schema/Schema_141.java
index c081ea9..ce1c910 100644
--- a/java/com/google/gerrit/server/schema/Schema_141.java
+++ b/java/com/google/gerrit/server/schema/Schema_141.java
@@ -18,7 +18,7 @@
 import com.google.inject.Provider;
 
 /** Add status field to account. */
-public class Schema_141 extends SchemaVersion {
+public class Schema_141 extends ReviewDbSchemaVersion {
   @Inject
   Schema_141(Provider<Schema_140> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_142.java b/java/com/google/gerrit/server/schema/Schema_142.java
index e67ae2f..9e06c52 100644
--- a/java/com/google/gerrit/server/schema/Schema_142.java
+++ b/java/com/google/gerrit/server/schema/Schema_142.java
@@ -29,7 +29,7 @@
 import java.sql.SQLException;
 import java.sql.Statement;
 
-public class Schema_142 extends SchemaVersion {
+public class Schema_142 extends ReviewDbSchemaVersion {
   private static final int MAX_BATCH_SIZE = 1000;
 
   @Inject
diff --git a/java/com/google/gerrit/server/schema/Schema_143.java b/java/com/google/gerrit/server/schema/Schema_143.java
index b190b29..10d108f 100644
--- a/java/com/google/gerrit/server/schema/Schema_143.java
+++ b/java/com/google/gerrit/server/schema/Schema_143.java
@@ -18,7 +18,7 @@
 import com.google.inject.Provider;
 
 /** Add isPrivate field to change. */
-public class Schema_143 extends SchemaVersion {
+public class Schema_143 extends ReviewDbSchemaVersion {
   @Inject
   Schema_143(Provider<Schema_142> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_144.java b/java/com/google/gerrit/server/schema/Schema_144.java
index bb0cbca..0aad504 100644
--- a/java/com/google/gerrit/server/schema/Schema_144.java
+++ b/java/com/google/gerrit/server/schema/Schema_144.java
@@ -37,7 +37,7 @@
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.lib.Repository;
 
-public class Schema_144 extends SchemaVersion {
+public class Schema_144 extends ReviewDbSchemaVersion {
   private static final String COMMIT_MSG = "Import external IDs from ReviewDb";
 
   private final GitRepositoryManager repoManager;
diff --git a/java/com/google/gerrit/server/schema/Schema_145.java b/java/com/google/gerrit/server/schema/Schema_145.java
index 6ccb5d8..1207632 100644
--- a/java/com/google/gerrit/server/schema/Schema_145.java
+++ b/java/com/google/gerrit/server/schema/Schema_145.java
@@ -24,7 +24,7 @@
 import java.sql.SQLException;
 
 /** Create account_external_ids_byEmail index. */
-public class Schema_145 extends SchemaVersion {
+public class Schema_145 extends ReviewDbSchemaVersion {
 
   @Inject
   Schema_145(Provider<Schema_144> prior) {
diff --git a/java/com/google/gerrit/server/schema/Schema_146.java b/java/com/google/gerrit/server/schema/Schema_146.java
index 503ed7b..2930408 100644
--- a/java/com/google/gerrit/server/schema/Schema_146.java
+++ b/java/com/google/gerrit/server/schema/Schema_146.java
@@ -54,7 +54,7 @@
  * commit with the registration date as commit time is inserted (if such a commit doesn't exist
  * yet).
  */
-public class Schema_146 extends SchemaVersion {
+public class Schema_146 extends ReviewDbSchemaVersion {
   private static final String CREATE_ACCOUNT_MSG = "Create Account";
 
   private final GitRepositoryManager repoManager;
diff --git a/java/com/google/gerrit/server/schema/Schema_147.java b/java/com/google/gerrit/server/schema/Schema_147.java
index c507fa6..f317e9a 100644
--- a/java/com/google/gerrit/server/schema/Schema_147.java
+++ b/java/com/google/gerrit/server/schema/Schema_147.java
@@ -38,7 +38,7 @@
 import org.eclipse.jgit.lib.Repository;
 
 /** Delete user branches for which no account exists. */
-public class Schema_147 extends SchemaVersion {
+public class Schema_147 extends ReviewDbSchemaVersion {
   private final GitRepositoryManager repoManager;
   private final AllUsersName allUsersName;
 
diff --git a/java/com/google/gerrit/server/schema/Schema_148.java b/java/com/google/gerrit/server/schema/Schema_148.java
index 9433da8..949dd5a 100644
--- a/java/com/google/gerrit/server/schema/Schema_148.java
+++ b/java/com/google/gerrit/server/schema/Schema_148.java
@@ -33,7 +33,7 @@
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.lib.Repository;
 
-public class Schema_148 extends SchemaVersion {
+public class Schema_148 extends ReviewDbSchemaVersion {
   private static final String COMMIT_MSG = "Make account IDs of external IDs human-readable";
 
   private final GitRepositoryManager repoManager;
diff --git a/java/com/google/gerrit/server/schema/Schema_149.java b/java/com/google/gerrit/server/schema/Schema_149.java
index f1ccaa6..156091b 100644
--- a/java/com/google/gerrit/server/schema/Schema_149.java
+++ b/java/com/google/gerrit/server/schema/Schema_149.java
@@ -18,7 +18,7 @@
 import com.google.inject.Provider;
 
 /** Add workInProgress field to change. */
-public class Schema_149 extends SchemaVersion {
+public class Schema_149 extends ReviewDbSchemaVersion {
   @Inject
   Schema_149(Provider<Schema_148> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_150.java b/java/com/google/gerrit/server/schema/Schema_150.java
index 456a01a..71736f3 100644
--- a/java/com/google/gerrit/server/schema/Schema_150.java
+++ b/java/com/google/gerrit/server/schema/Schema_150.java
@@ -18,7 +18,7 @@
 import com.google.inject.Provider;
 
 /** Drop ACCOUNT_EXTERNAL_IDS table. */
-public class Schema_150 extends SchemaVersion {
+public class Schema_150 extends ReviewDbSchemaVersion {
   @Inject
   Schema_150(Provider<Schema_149> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_151.java b/java/com/google/gerrit/server/schema/Schema_151.java
index 41d8a32..0e8700f 100644
--- a/java/com/google/gerrit/server/schema/Schema_151.java
+++ b/java/com/google/gerrit/server/schema/Schema_151.java
@@ -29,7 +29,7 @@
 import java.util.Optional;
 
 /** A schema which adds the 'created on' field to groups. */
-public class Schema_151 extends SchemaVersion {
+public class Schema_151 extends ReviewDbSchemaVersion {
   @Inject
   protected Schema_151(Provider<Schema_150> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_152.java b/java/com/google/gerrit/server/schema/Schema_152.java
index c5150a0..b605e90 100644
--- a/java/com/google/gerrit/server/schema/Schema_152.java
+++ b/java/com/google/gerrit/server/schema/Schema_152.java
@@ -24,7 +24,7 @@
 import java.sql.SQLException;
 
 /** Drop unused indexes from accounts table. */
-public class Schema_152 extends SchemaVersion {
+public class Schema_152 extends ReviewDbSchemaVersion {
   @Inject
   Schema_152(Provider<Schema_151> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_153.java b/java/com/google/gerrit/server/schema/Schema_153.java
index 28aeb17..7d1f63e 100644
--- a/java/com/google/gerrit/server/schema/Schema_153.java
+++ b/java/com/google/gerrit/server/schema/Schema_153.java
@@ -21,7 +21,7 @@
 import com.google.inject.Provider;
 
 /** Add reviewStarted field to change. */
-public class Schema_153 extends SchemaVersion {
+public class Schema_153 extends ReviewDbSchemaVersion {
   @Inject
   Schema_153(Provider<Schema_152> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_154.java b/java/com/google/gerrit/server/schema/Schema_154.java
index fab1693..8c97010 100644
--- a/java/com/google/gerrit/server/schema/Schema_154.java
+++ b/java/com/google/gerrit/server/schema/Schema_154.java
@@ -47,7 +47,7 @@
 import org.eclipse.jgit.lib.TextProgressMonitor;
 
 /** Migrate accounts to NoteDb. */
-public class Schema_154 extends SchemaVersion {
+public class Schema_154 extends ReviewDbSchemaVersion {
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
 
   private static final String TABLE = "accounts";
diff --git a/java/com/google/gerrit/server/schema/Schema_155.java b/java/com/google/gerrit/server/schema/Schema_155.java
index ec16e06..812d7a6 100644
--- a/java/com/google/gerrit/server/schema/Schema_155.java
+++ b/java/com/google/gerrit/server/schema/Schema_155.java
@@ -26,7 +26,7 @@
 import java.sql.SQLException;
 
 /** Create account sequence in NoteDb */
-public class Schema_155 extends SchemaVersion {
+public class Schema_155 extends ReviewDbSchemaVersion {
   private final GitRepositoryManager repoManager;
   private final AllUsersName allUsersName;
 
diff --git a/java/com/google/gerrit/server/schema/Schema_156.java b/java/com/google/gerrit/server/schema/Schema_156.java
index fd8fc00..237161c 100644
--- a/java/com/google/gerrit/server/schema/Schema_156.java
+++ b/java/com/google/gerrit/server/schema/Schema_156.java
@@ -18,7 +18,7 @@
 import com.google.inject.Provider;
 
 /** Add revertOf field to change. */
-public class Schema_156 extends SchemaVersion {
+public class Schema_156 extends ReviewDbSchemaVersion {
   @Inject
   Schema_156(Provider<Schema_155> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_157.java b/java/com/google/gerrit/server/schema/Schema_157.java
index f5c5b59..20a8c4b 100644
--- a/java/com/google/gerrit/server/schema/Schema_157.java
+++ b/java/com/google/gerrit/server/schema/Schema_157.java
@@ -24,7 +24,7 @@
 import java.sql.SQLException;
 
 /** Drop unused indexes from accounts table. */
-public class Schema_157 extends SchemaVersion {
+public class Schema_157 extends ReviewDbSchemaVersion {
   @Inject
   Schema_157(Provider<Schema_156> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_158.java b/java/com/google/gerrit/server/schema/Schema_158.java
index ea85444..3b7d9e8 100644
--- a/java/com/google/gerrit/server/schema/Schema_158.java
+++ b/java/com/google/gerrit/server/schema/Schema_158.java
@@ -18,7 +18,7 @@
 import com.google.inject.Provider;
 
 /** Drop ACCOUNTS table. */
-public class Schema_158 extends SchemaVersion {
+public class Schema_158 extends ReviewDbSchemaVersion {
   @Inject
   Schema_158(Provider<Schema_157> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_159.java b/java/com/google/gerrit/server/schema/Schema_159.java
index d6e37d7..ddb5765 100644
--- a/java/com/google/gerrit/server/schema/Schema_159.java
+++ b/java/com/google/gerrit/server/schema/Schema_159.java
@@ -21,7 +21,7 @@
 import com.google.inject.Provider;
 
 /** Migrate draft changes to private or wip changes. */
-public class Schema_159 extends SchemaVersion {
+public class Schema_159 extends ReviewDbSchemaVersion {
 
   private enum DraftWorkflowMigrationStrategy {
     PRIVATE,
diff --git a/java/com/google/gerrit/server/schema/Schema_160.java b/java/com/google/gerrit/server/schema/Schema_160.java
index eb8b70f..10f5c9d 100644
--- a/java/com/google/gerrit/server/schema/Schema_160.java
+++ b/java/com/google/gerrit/server/schema/Schema_160.java
@@ -60,7 +60,7 @@
  * <p>Other menus containing {@code is:draft} in other positions are not affected; this is still a
  * valid predicate that matches no changes.
  */
-public class Schema_160 extends SchemaVersion {
+public class Schema_160 extends ReviewDbSchemaVersion {
   @VisibleForTesting static final ImmutableList<String> DEFAULT_DRAFT_ITEMS;
 
   static {
diff --git a/java/com/google/gerrit/server/schema/Schema_161.java b/java/com/google/gerrit/server/schema/Schema_161.java
index 3077720..4627abe 100644
--- a/java/com/google/gerrit/server/schema/Schema_161.java
+++ b/java/com/google/gerrit/server/schema/Schema_161.java
@@ -39,7 +39,7 @@
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.transport.ReceiveCommand;
 
-public class Schema_161 extends SchemaVersion {
+public class Schema_161 extends ReviewDbSchemaVersion {
   private static final String MUTE_LABEL = "mute";
 
   private final GitRepositoryManager repoManager;
diff --git a/java/com/google/gerrit/server/schema/Schema_162.java b/java/com/google/gerrit/server/schema/Schema_162.java
index 7406bc6..3d3a192 100644
--- a/java/com/google/gerrit/server/schema/Schema_162.java
+++ b/java/com/google/gerrit/server/schema/Schema_162.java
@@ -30,10 +30,11 @@
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.lib.Repository;
 
-public class Schema_162 extends SchemaVersion {
+public class Schema_162 extends ReviewDbSchemaVersion {
   private final GitRepositoryManager repoManager;
   private final AllProjectsName allProjectsName;
   private final AllUsersName allUsersName;
+  private final ProjectConfig.Factory projectConfigFactory;
   private final PersonIdent serverUser;
 
   @Inject
@@ -42,11 +43,13 @@
       GitRepositoryManager repoManager,
       AllProjectsName allProjectsName,
       AllUsersName allUsersName,
+      ProjectConfig.Factory projectConfigFactory,
       @GerritPersonIdent PersonIdent serverUser) {
     super(prior);
     this.repoManager = repoManager;
     this.allProjectsName = allProjectsName;
     this.allUsersName = allUsersName;
+    this.projectConfigFactory = projectConfigFactory;
     this.serverUser = serverUser;
   }
 
@@ -54,7 +57,7 @@
   protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
     try (Repository git = repoManager.openRepository(allUsersName);
         MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, git)) {
-      ProjectConfig cfg = ProjectConfig.read(md);
+      ProjectConfig cfg = projectConfigFactory.read(md);
       if (allProjectsName.equals(cfg.getProject().getParent(allProjectsName))) {
         return;
       }
diff --git a/java/com/google/gerrit/server/schema/Schema_163.java b/java/com/google/gerrit/server/schema/Schema_163.java
index ae05774..9eb5d5e 100644
--- a/java/com/google/gerrit/server/schema/Schema_163.java
+++ b/java/com/google/gerrit/server/schema/Schema_163.java
@@ -26,7 +26,7 @@
 import java.sql.SQLException;
 
 /** Create group sequence in NoteDb */
-public class Schema_163 extends SchemaVersion {
+public class Schema_163 extends ReviewDbSchemaVersion {
   private final GitRepositoryManager repoManager;
   private final AllUsersName allUsersName;
 
diff --git a/java/com/google/gerrit/server/schema/Schema_164.java b/java/com/google/gerrit/server/schema/Schema_164.java
index 8525478..b6c3118 100644
--- a/java/com/google/gerrit/server/schema/Schema_164.java
+++ b/java/com/google/gerrit/server/schema/Schema_164.java
@@ -38,12 +38,13 @@
 import org.eclipse.jgit.lib.Repository;
 
 /** Grant read on group branches */
-public class Schema_164 extends SchemaVersion {
+public class Schema_164 extends ReviewDbSchemaVersion {
   private static final String COMMIT_MSG = "Grant read permissions on group branches";
 
   private final GitRepositoryManager repoManager;
   private final AllUsersName allUsersName;
   private final SystemGroupBackend systemGroupBackend;
+  private final ProjectConfig.Factory projectConfigFactory;
   private final PersonIdent serverUser;
 
   @Inject
@@ -52,11 +53,13 @@
       GitRepositoryManager repoManager,
       AllUsersName allUsersName,
       SystemGroupBackend systemGroupBackend,
+      ProjectConfig.Factory projectConfigFactory,
       @GerritPersonIdent PersonIdent serverUser) {
     super(prior);
     this.repoManager = repoManager;
     this.allUsersName = allUsersName;
     this.systemGroupBackend = systemGroupBackend;
+    this.projectConfigFactory = projectConfigFactory;
     this.serverUser = serverUser;
   }
 
@@ -68,7 +71,7 @@
       md.getCommitBuilder().setCommitter(serverUser);
       md.setMessage(COMMIT_MSG);
 
-      ProjectConfig config = ProjectConfig.read(md);
+      ProjectConfig config = projectConfigFactory.read(md);
       AccessSection groups = config.getAccessSection(RefNames.REFS_GROUPS + "*", true);
       grant(
           config,
diff --git a/java/com/google/gerrit/server/schema/Schema_165.java b/java/com/google/gerrit/server/schema/Schema_165.java
index cd6da55..d80c770 100644
--- a/java/com/google/gerrit/server/schema/Schema_165.java
+++ b/java/com/google/gerrit/server/schema/Schema_165.java
@@ -41,13 +41,14 @@
 import org.eclipse.jgit.lib.Repository;
 
 /** Make default Label-Code-Review permission on user branches exclusive. */
-public class Schema_165 extends SchemaVersion {
+public class Schema_165 extends ReviewDbSchemaVersion {
   private static final String COMMIT_MSG =
       "Make default Label-Code-Review permission on user branches exclusive";
 
   private final GitRepositoryManager repoManager;
   private final AllUsersName allUsersName;
   private final SystemGroupBackend systemGroupBackend;
+  private final ProjectConfig.Factory projectConfigFactory;
   private final PersonIdent serverUser;
 
   @Inject
@@ -56,11 +57,13 @@
       GitRepositoryManager repoManager,
       AllUsersName allUsersName,
       SystemGroupBackend systemGroupBackend,
+      ProjectConfig.Factory projectConfigFactory,
       @GerritPersonIdent PersonIdent serverUser) {
     super(prior);
     this.repoManager = repoManager;
     this.allUsersName = allUsersName;
     this.systemGroupBackend = systemGroupBackend;
+    this.projectConfigFactory = projectConfigFactory;
     this.serverUser = serverUser;
   }
 
@@ -68,7 +71,7 @@
   protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
     try (Repository git = repoManager.openRepository(allUsersName);
         MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, git)) {
-      ProjectConfig config = ProjectConfig.read(md);
+      ProjectConfig config = projectConfigFactory.read(md);
       Optional<Permission> permission = findDefaultPermission(config);
       if (!permission.isPresent()) {
         // the default permission was not found, hence it cannot be fixed
diff --git a/java/com/google/gerrit/server/schema/Schema_166.java b/java/com/google/gerrit/server/schema/Schema_166.java
index aa6f4e6..901df56 100644
--- a/java/com/google/gerrit/server/schema/Schema_166.java
+++ b/java/com/google/gerrit/server/schema/Schema_166.java
@@ -28,7 +28,7 @@
 import org.eclipse.jgit.lib.Repository;
 
 /** Set HEAD for All-Users to refs/meta/config. */
-public class Schema_166 extends SchemaVersion {
+public class Schema_166 extends ReviewDbSchemaVersion {
   private final GitRepositoryManager repoManager;
   private final AllUsersName allUsersName;
 
diff --git a/java/com/google/gerrit/server/schema/Schema_167.java b/java/com/google/gerrit/server/schema/Schema_167.java
index a5066cc..44d89f9 100644
--- a/java/com/google/gerrit/server/schema/Schema_167.java
+++ b/java/com/google/gerrit/server/schema/Schema_167.java
@@ -24,6 +24,7 @@
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.common.data.GroupDescription;
 import com.google.gerrit.common.data.GroupReference;
+import com.google.gerrit.git.RefUpdateUtil;
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.reviewdb.client.RefNames;
@@ -39,7 +40,6 @@
 import com.google.gerrit.server.group.SystemGroupBackend;
 import com.google.gerrit.server.group.db.AuditLogFormatter;
 import com.google.gerrit.server.group.db.GroupNameNotes;
-import com.google.gerrit.server.update.RefUpdateUtil;
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
@@ -60,7 +60,7 @@
 import org.eclipse.jgit.lib.Repository;
 
 /** Migrate groups from ReviewDb to NoteDb. */
-public class Schema_167 extends SchemaVersion {
+public class Schema_167 extends ReviewDbSchemaVersion {
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
 
   private final GitRepositoryManager repoManager;
diff --git a/java/com/google/gerrit/server/schema/Schema_168.java b/java/com/google/gerrit/server/schema/Schema_168.java
index 3ea8468..fff4049 100644
--- a/java/com/google/gerrit/server/schema/Schema_168.java
+++ b/java/com/google/gerrit/server/schema/Schema_168.java
@@ -18,7 +18,7 @@
 import com.google.inject.Provider;
 
 /** Drop group tables. */
-public class Schema_168 extends SchemaVersion {
+public class Schema_168 extends ReviewDbSchemaVersion {
   @Inject
   Schema_168(Provider<Schema_167> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_169.java b/java/com/google/gerrit/server/schema/Schema_169.java
index 2779d47..11601e4 100644
--- a/java/com/google/gerrit/server/schema/Schema_169.java
+++ b/java/com/google/gerrit/server/schema/Schema_169.java
@@ -35,7 +35,7 @@
 import org.eclipse.jgit.lib.TextProgressMonitor;
 
 /** Migrate NoteDb inline comments to JSON format. */
-public class Schema_169 extends SchemaVersion {
+public class Schema_169 extends ReviewDbSchemaVersion {
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
   private final CommentJsonMigrator migrator;
   private final GitRepositoryManager repoManager;
diff --git a/java/com/google/gerrit/server/schema/Schema_170.java b/java/com/google/gerrit/server/schema/Schema_170.java
index c87fa3e..6a86494 100644
--- a/java/com/google/gerrit/server/schema/Schema_170.java
+++ b/java/com/google/gerrit/server/schema/Schema_170.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_170 extends SchemaVersion {
+public class Schema_170 extends ReviewDbSchemaVersion {
   @Inject
   Schema_170(Provider<Schema_169> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_83.java b/java/com/google/gerrit/server/schema/Schema_83.java
index decbfb1..95b7e6f 100644
--- a/java/com/google/gerrit/server/schema/Schema_83.java
+++ b/java/com/google/gerrit/server/schema/Schema_83.java
@@ -18,14 +18,14 @@
 import com.google.inject.Provider;
 import com.google.inject.ProvisionException;
 
-public class Schema_83 extends SchemaVersion {
+public class Schema_83 extends ReviewDbSchemaVersion {
 
   @Inject
   Schema_83() {
     super(
-        new Provider<SchemaVersion>() {
+        new Provider<ReviewDbSchemaVersion>() {
           @Override
-          public SchemaVersion get() {
+          public ReviewDbSchemaVersion get() {
             throw new ProvisionException("Upgrade first to 2.8 or 2.9");
           }
         });
diff --git a/java/com/google/gerrit/server/schema/Schema_84.java b/java/com/google/gerrit/server/schema/Schema_84.java
index c96f650..415b2e3 100644
--- a/java/com/google/gerrit/server/schema/Schema_84.java
+++ b/java/com/google/gerrit/server/schema/Schema_84.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_84 extends SchemaVersion {
+public class Schema_84 extends ReviewDbSchemaVersion {
 
   @Inject
   Schema_84(Provider<Schema_83> prior) {
diff --git a/java/com/google/gerrit/server/schema/Schema_85.java b/java/com/google/gerrit/server/schema/Schema_85.java
index e24e67c..ee8fbdb 100644
--- a/java/com/google/gerrit/server/schema/Schema_85.java
+++ b/java/com/google/gerrit/server/schema/Schema_85.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_85 extends SchemaVersion {
+public class Schema_85 extends ReviewDbSchemaVersion {
   @Inject
   Schema_85(Provider<Schema_84> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_86.java b/java/com/google/gerrit/server/schema/Schema_86.java
index d758189..e468345 100644
--- a/java/com/google/gerrit/server/schema/Schema_86.java
+++ b/java/com/google/gerrit/server/schema/Schema_86.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_86 extends SchemaVersion {
+public class Schema_86 extends ReviewDbSchemaVersion {
   @Inject
   Schema_86(Provider<Schema_85> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_87.java b/java/com/google/gerrit/server/schema/Schema_87.java
index 5865af0..79884ba 100644
--- a/java/com/google/gerrit/server/schema/Schema_87.java
+++ b/java/com/google/gerrit/server/schema/Schema_87.java
@@ -28,7 +28,7 @@
 import java.util.Optional;
 import java.util.Set;
 
-public class Schema_87 extends SchemaVersion {
+public class Schema_87 extends ReviewDbSchemaVersion {
   @Inject
   Schema_87(Provider<Schema_86> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_88.java b/java/com/google/gerrit/server/schema/Schema_88.java
index 0a7f14c..d5e9994 100644
--- a/java/com/google/gerrit/server/schema/Schema_88.java
+++ b/java/com/google/gerrit/server/schema/Schema_88.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_88 extends SchemaVersion {
+public class Schema_88 extends ReviewDbSchemaVersion {
   @Inject
   Schema_88(Provider<Schema_87> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_89.java b/java/com/google/gerrit/server/schema/Schema_89.java
index de84993..3d352da 100644
--- a/java/com/google/gerrit/server/schema/Schema_89.java
+++ b/java/com/google/gerrit/server/schema/Schema_89.java
@@ -23,7 +23,7 @@
 import com.google.inject.Provider;
 import java.sql.SQLException;
 
-public class Schema_89 extends SchemaVersion {
+public class Schema_89 extends ReviewDbSchemaVersion {
   @Inject
   Schema_89(Provider<Schema_88> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_90.java b/java/com/google/gerrit/server/schema/Schema_90.java
index d8f02ae..3831f33 100644
--- a/java/com/google/gerrit/server/schema/Schema_90.java
+++ b/java/com/google/gerrit/server/schema/Schema_90.java
@@ -20,7 +20,7 @@
 import java.sql.SQLException;
 import java.sql.Statement;
 
-public class Schema_90 extends SchemaVersion {
+public class Schema_90 extends ReviewDbSchemaVersion {
   @Inject
   Schema_90(Provider<Schema_89> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_91.java b/java/com/google/gerrit/server/schema/Schema_91.java
index 173793e..6dd2d58 100644
--- a/java/com/google/gerrit/server/schema/Schema_91.java
+++ b/java/com/google/gerrit/server/schema/Schema_91.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_91 extends SchemaVersion {
+public class Schema_91 extends ReviewDbSchemaVersion {
   @Inject
   Schema_91(Provider<Schema_90> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_92.java b/java/com/google/gerrit/server/schema/Schema_92.java
index 5f5c141..9af33c0 100644
--- a/java/com/google/gerrit/server/schema/Schema_92.java
+++ b/java/com/google/gerrit/server/schema/Schema_92.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_92 extends SchemaVersion {
+public class Schema_92 extends ReviewDbSchemaVersion {
   @Inject
   Schema_92(Provider<Schema_91> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_93.java b/java/com/google/gerrit/server/schema/Schema_93.java
index 3132aa4..e9a6691 100644
--- a/java/com/google/gerrit/server/schema/Schema_93.java
+++ b/java/com/google/gerrit/server/schema/Schema_93.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_93 extends SchemaVersion {
+public class Schema_93 extends ReviewDbSchemaVersion {
   @Inject
   Schema_93(Provider<Schema_92> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_94.java b/java/com/google/gerrit/server/schema/Schema_94.java
index d4a189f..1551650 100644
--- a/java/com/google/gerrit/server/schema/Schema_94.java
+++ b/java/com/google/gerrit/server/schema/Schema_94.java
@@ -20,7 +20,7 @@
 import java.sql.SQLException;
 import java.sql.Statement;
 
-public class Schema_94 extends SchemaVersion {
+public class Schema_94 extends ReviewDbSchemaVersion {
   @Inject
   Schema_94(Provider<Schema_93> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_95.java b/java/com/google/gerrit/server/schema/Schema_95.java
index 0ce0294..19dfa97 100644
--- a/java/com/google/gerrit/server/schema/Schema_95.java
+++ b/java/com/google/gerrit/server/schema/Schema_95.java
@@ -22,7 +22,7 @@
 import java.sql.SQLException;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 
-public class Schema_95 extends SchemaVersion {
+public class Schema_95 extends ReviewDbSchemaVersion {
   private final AllUsersCreator allUsersCreator;
 
   @Inject
diff --git a/java/com/google/gerrit/server/schema/Schema_96.java b/java/com/google/gerrit/server/schema/Schema_96.java
index bf19213..2eb9a87 100644
--- a/java/com/google/gerrit/server/schema/Schema_96.java
+++ b/java/com/google/gerrit/server/schema/Schema_96.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_96 extends SchemaVersion {
+public class Schema_96 extends ReviewDbSchemaVersion {
   @Inject
   Schema_96(Provider<Schema_95> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_97.java b/java/com/google/gerrit/server/schema/Schema_97.java
index 0670377..98f548e 100644
--- a/java/com/google/gerrit/server/schema/Schema_97.java
+++ b/java/com/google/gerrit/server/schema/Schema_97.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_97 extends SchemaVersion {
+public class Schema_97 extends ReviewDbSchemaVersion {
   @Inject
   Schema_97(Provider<Schema_96> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_98.java b/java/com/google/gerrit/server/schema/Schema_98.java
index eec3c9f..8a7498f 100644
--- a/java/com/google/gerrit/server/schema/Schema_98.java
+++ b/java/com/google/gerrit/server/schema/Schema_98.java
@@ -20,7 +20,7 @@
 import java.sql.SQLException;
 import java.sql.Statement;
 
-public class Schema_98 extends SchemaVersion {
+public class Schema_98 extends ReviewDbSchemaVersion {
   @Inject
   Schema_98(Provider<Schema_97> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/schema/Schema_99.java b/java/com/google/gerrit/server/schema/Schema_99.java
index b7fab7f..ca3a959 100644
--- a/java/com/google/gerrit/server/schema/Schema_99.java
+++ b/java/com/google/gerrit/server/schema/Schema_99.java
@@ -17,7 +17,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-public class Schema_99 extends SchemaVersion {
+public class Schema_99 extends ReviewDbSchemaVersion {
   @Inject
   Schema_99(Provider<Schema_98> prior) {
     super(prior);
diff --git a/java/com/google/gerrit/server/submit/LocalMergeSuperSetComputation.java b/java/com/google/gerrit/server/submit/LocalMergeSuperSetComputation.java
index 9efb976..66463be 100644
--- a/java/com/google/gerrit/server/submit/LocalMergeSuperSetComputation.java
+++ b/java/com/google/gerrit/server/submit/LocalMergeSuperSetComputation.java
@@ -37,6 +37,7 @@
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.project.ProjectState;
 import com.google.gerrit.server.query.change.ChangeData;
+import com.google.gerrit.server.query.change.ChangeIsVisibleToPredicate;
 import com.google.gerrit.server.query.change.InternalChangeQuery;
 import com.google.gerrit.server.submit.MergeOpRepoManager.OpenRepo;
 import com.google.gwtorm.server.OrmException;
@@ -87,20 +88,23 @@
 
   private final PermissionBackend permissionBackend;
   private final Provider<InternalChangeQuery> queryProvider;
-  private final Map<QueryKey, List<ChangeData>> queryCache;
+  private final Map<QueryKey, ImmutableList<ChangeData>> queryCache;
   private final Map<Branch.NameKey, Optional<RevCommit>> heads;
   private final ProjectCache projectCache;
+  private final ChangeIsVisibleToPredicate changeIsVisibleToPredicate;
 
   @Inject
   LocalMergeSuperSetComputation(
       PermissionBackend permissionBackend,
       Provider<InternalChangeQuery> queryProvider,
-      ProjectCache projectCache) {
+      ProjectCache projectCache,
+      ChangeIsVisibleToPredicate changeIsVisibleToPredicate) {
     this.projectCache = projectCache;
     this.permissionBackend = permissionBackend;
     this.queryProvider = queryProvider;
     this.queryCache = new HashMap<>();
     this.heads = new HashMap<>();
+    this.changeIsVisibleToPredicate = changeIsVisibleToPredicate;
   }
 
   @Override
@@ -147,10 +151,11 @@
 
       Set<String> visibleHashes =
           walkChangesByHashes(visibleCommits, Collections.emptySet(), or, b);
-      Iterables.addAll(visibleChanges, byCommitsOnBranchNotMerged(or, db, b, visibleHashes));
-
       Set<String> nonVisibleHashes = walkChangesByHashes(nonVisibleCommits, visibleHashes, or, b);
-      Iterables.addAll(nonVisibleChanges, byCommitsOnBranchNotMerged(or, db, b, nonVisibleHashes));
+
+      ChangeSet partialSet = byCommitsOnBranchNotMerged(or, db, b, visibleHashes, nonVisibleHashes);
+      Iterables.addAll(visibleChanges, partialSet.changes());
+      Iterables.addAll(nonVisibleChanges, partialSet.nonVisibleChanges());
     }
 
     return new ChangeSet(visibleChanges, nonVisibleChanges);
@@ -206,24 +211,41 @@
     return str.type;
   }
 
-  private List<ChangeData> byCommitsOnBranchNotMerged(
+  private ChangeSet byCommitsOnBranchNotMerged(
+      OpenRepo or,
+      ReviewDb db,
+      Branch.NameKey branch,
+      Set<String> visibleHashes,
+      Set<String> nonVisibleHashes)
+      throws OrmException, IOException {
+    List<ChangeData> potentiallyVisibleChanges =
+        byCommitsOnBranchNotMerged(or, db, branch, visibleHashes);
+    List<ChangeData> invisibleChanges =
+        new ArrayList<>(byCommitsOnBranchNotMerged(or, db, branch, nonVisibleHashes));
+    List<ChangeData> visibleChanges = new ArrayList<>(potentiallyVisibleChanges.size());
+    for (ChangeData cd : potentiallyVisibleChanges) {
+      if (changeIsVisibleToPredicate.match(cd)) {
+        visibleChanges.add(cd);
+      } else {
+        invisibleChanges.add(cd);
+      }
+    }
+    return new ChangeSet(visibleChanges, invisibleChanges);
+  }
+
+  private ImmutableList<ChangeData> byCommitsOnBranchNotMerged(
       OpenRepo or, ReviewDb db, Branch.NameKey branch, Set<String> hashes)
       throws OrmException, IOException {
     if (hashes.isEmpty()) {
       return ImmutableList.of();
     }
     QueryKey k = QueryKey.create(branch, hashes);
-    List<ChangeData> cached = queryCache.get(k);
-    if (cached != null) {
-      return cached;
+    if (queryCache.containsKey(k)) {
+      return queryCache.get(k);
     }
-
-    List<ChangeData> result = new ArrayList<>();
-    Iterable<ChangeData> destChanges =
-        queryProvider.get().byCommitsOnBranchNotMerged(or.repo, db, branch, hashes);
-    for (ChangeData chd : destChanges) {
-      result.add(chd);
-    }
+    ImmutableList<ChangeData> result =
+        ImmutableList.copyOf(
+            queryProvider.get().byCommitsOnBranchNotMerged(or.repo, db, branch, hashes));
     queryCache.put(k, result);
     return result;
   }
diff --git a/java/com/google/gerrit/server/submit/MergeOp.java b/java/com/google/gerrit/server/submit/MergeOp.java
index e27863f9..8e018a5 100644
--- a/java/com/google/gerrit/server/submit/MergeOp.java
+++ b/java/com/google/gerrit/server/submit/MergeOp.java
@@ -42,6 +42,7 @@
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.RestApiException;
+import com.google.gerrit.git.LockFailureException;
 import com.google.gerrit.metrics.Counter0;
 import com.google.gerrit.metrics.Description;
 import com.google.gerrit.metrics.MetricMaker;
@@ -57,7 +58,6 @@
 import com.google.gerrit.server.InternalUser;
 import com.google.gerrit.server.change.NotifyUtil;
 import com.google.gerrit.server.git.CodeReviewCommit;
-import com.google.gerrit.server.git.LockFailureException;
 import com.google.gerrit.server.git.MergeTip;
 import com.google.gerrit.server.git.validators.MergeValidationException;
 import com.google.gerrit.server.git.validators.MergeValidators;
diff --git a/java/com/google/gerrit/server/submit/SubmitStrategy.java b/java/com/google/gerrit/server/submit/SubmitStrategy.java
index 4cefd7d..6511d25 100644
--- a/java/com/google/gerrit/server/submit/SubmitStrategy.java
+++ b/java/com/google/gerrit/server/submit/SubmitStrategy.java
@@ -46,6 +46,7 @@
 import com.google.gerrit.server.logging.RequestId;
 import com.google.gerrit.server.patch.PatchSetInfoFactory;
 import com.google.gerrit.server.project.ProjectCache;
+import com.google.gerrit.server.project.ProjectConfig;
 import com.google.gerrit.server.project.ProjectState;
 import com.google.gerrit.server.query.change.InternalChangeQuery;
 import com.google.gerrit.server.submit.MergeOp.CommitStatus;
@@ -115,6 +116,7 @@
     final OnSubmitValidators.Factory onSubmitValidatorsFactory;
     final TagCache tagCache;
     final Provider<InternalChangeQuery> queryProvider;
+    final ProjectConfig.Factory projectConfigFactory;
 
     final Branch.NameKey destBranch;
     final CodeReviewRevWalk rw;
@@ -154,6 +156,7 @@
         OnSubmitValidators.Factory onSubmitValidatorsFactory,
         TagCache tagCache,
         Provider<InternalChangeQuery> queryProvider,
+        ProjectConfig.Factory projectConfigFactory,
         @Assisted Branch.NameKey destBranch,
         @Assisted CommitStatus commitStatus,
         @Assisted CodeReviewRevWalk rw,
@@ -176,6 +179,7 @@
       this.repoManager = repoManager;
       this.cmUtil = cmUtil;
       this.labelNormalizer = labelNormalizer;
+      this.projectConfigFactory = projectConfigFactory;
       this.patchSetInfoFactory = patchSetInfoFactory;
       this.psUtil = psUtil;
       this.projectCache = projectCache;
diff --git a/java/com/google/gerrit/server/submit/SubmitStrategyOp.java b/java/com/google/gerrit/server/submit/SubmitStrategyOp.java
index 8a4fbfb..3be4c31 100644
--- a/java/com/google/gerrit/server/submit/SubmitStrategyOp.java
+++ b/java/com/google/gerrit/server/submit/SubmitStrategyOp.java
@@ -145,7 +145,7 @@
     if (RefNames.REFS_CONFIG.equals(refName)) {
       logger.atFine().log("Loading new configuration from %s", RefNames.REFS_CONFIG);
       try {
-        ProjectConfig cfg = new ProjectConfig(getProject());
+        ProjectConfig cfg = args.projectConfigFactory.create(getProject());
         cfg.load(ctx.getRevWalk(), commit);
       } catch (Exception e) {
         throw new IntegrationException(
diff --git a/java/com/google/gerrit/server/update/RefUpdateUtil.java b/java/com/google/gerrit/server/update/RefUpdateUtil.java
deleted file mode 100644
index 3e33677..0000000
--- a/java/com/google/gerrit/server/update/RefUpdateUtil.java
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright (C) 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.update;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.gerrit.server.git.LockFailureException;
-import java.io.IOException;
-import org.eclipse.jgit.internal.JGitText;
-import org.eclipse.jgit.lib.BatchRefUpdate;
-import org.eclipse.jgit.lib.NullProgressMonitor;
-import org.eclipse.jgit.lib.RefUpdate;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevWalk;
-import org.eclipse.jgit.transport.ReceiveCommand;
-
-/** Static utilities for working with JGit's ref update APIs. */
-public class RefUpdateUtil {
-  /**
-   * Execute a batch ref update, throwing a checked exception if not all updates succeeded.
-   *
-   * <p>Creates a new {@link RevWalk} used only for this operation.
-   *
-   * @param bru batch update; should already have been executed.
-   * @param repo repository that created {@code bru}.
-   * @throws LockFailureException if the transaction was aborted due to lock failure; see {@link
-   *     #checkResults(BatchRefUpdate)} for details.
-   * @throws IOException if any result was not {@code OK}.
-   */
-  public static void executeChecked(BatchRefUpdate bru, Repository repo) throws IOException {
-    try (RevWalk rw = new RevWalk(repo)) {
-      executeChecked(bru, rw);
-    }
-  }
-
-  /**
-   * Execute a batch ref update, throwing a checked exception if not all updates succeeded.
-   *
-   * @param bru batch update; should already have been executed.
-   * @param rw walk for executing the update.
-   * @throws LockFailureException if the transaction was aborted due to lock failure; see {@link
-   *     #checkResults(BatchRefUpdate)} for details.
-   * @throws IOException if any result was not {@code OK}.
-   */
-  public static void executeChecked(BatchRefUpdate bru, RevWalk rw) throws IOException {
-    bru.execute(rw, NullProgressMonitor.INSTANCE);
-    checkResults(bru);
-  }
-
-  /**
-   * Check results of all commands in the update batch, reducing to a single exception if there was
-   * a failure.
-   *
-   * <p>Throws {@link LockFailureException} if at least one command failed with {@code
-   * LOCK_FAILURE}, and the entire transaction was aborted, i.e. any non-{@code LOCK_FAILURE}
-   * results, if there were any, failed with "transaction aborted".
-   *
-   * <p>In particular, if the underlying ref database does not {@link
-   * org.eclipse.jgit.lib.RefDatabase#performsAtomicTransactions() perform atomic transactions},
-   * then a combination of {@code LOCK_FAILURE} on one ref and {@code OK} or another result on other
-   * refs will <em>not</em> throw {@code LockFailureException}.
-   *
-   * @param bru batch update; should already have been executed.
-   * @throws LockFailureException if the transaction was aborted due to lock failure.
-   * @throws IOException if any result was not {@code OK}.
-   */
-  @VisibleForTesting
-  static void checkResults(BatchRefUpdate bru) throws IOException {
-    if (bru.getCommands().isEmpty()) {
-      return;
-    }
-
-    int lockFailure = 0;
-    int aborted = 0;
-    int failure = 0;
-
-    for (ReceiveCommand cmd : bru.getCommands()) {
-      if (cmd.getResult() != ReceiveCommand.Result.OK) {
-        failure++;
-      }
-      if (cmd.getResult() == ReceiveCommand.Result.LOCK_FAILURE) {
-        lockFailure++;
-      } else if (cmd.getResult() == ReceiveCommand.Result.REJECTED_OTHER_REASON
-          && JGitText.get().transactionAborted.equals(cmd.getMessage())) {
-        aborted++;
-      }
-    }
-
-    if (lockFailure + aborted == bru.getCommands().size()) {
-      throw new LockFailureException("Update aborted with one or more lock failures: " + bru, bru);
-    } else if (failure > 0) {
-      throw new IOException("Update failed: " + bru);
-    }
-  }
-
-  /**
-   * Delete a single ref, throwing a checked exception on failure.
-   *
-   * <p>Does not require that the ref have any particular old value. Succeeds as a no-op if the ref
-   * did not exist.
-   *
-   * @param repo repository.
-   * @param refName ref name to delete.
-   * @throws LockFailureException if a low-level lock failure (e.g. compare-and-swap failure)
-   *     occurs.
-   * @throws IOException if an error occurred.
-   */
-  public static void deleteChecked(Repository repo, String refName) throws IOException {
-    RefUpdate ru = repo.updateRef(refName);
-    ru.setForceUpdate(true);
-    switch (ru.delete()) {
-      case FORCED:
-        // Ref was deleted.
-        return;
-
-      case NEW:
-        // Ref didn't exist (yes, really).
-        return;
-
-      case LOCK_FAILURE:
-        throw new LockFailureException("Failed to delete " + refName + ": " + ru.getResult(), ru);
-
-        // Not really failures, but should not be the result of a deletion, so the best option is to
-        // throw.
-      case NO_CHANGE:
-      case FAST_FORWARD:
-      case RENAMED:
-      case NOT_ATTEMPTED:
-
-      case IO_FAILURE:
-      case REJECTED:
-      case REJECTED_CURRENT_BRANCH:
-      case REJECTED_MISSING_OBJECT:
-      case REJECTED_OTHER_REASON:
-      default:
-        throw new IOException("Failed to delete " + refName + ": " + ru.getResult());
-    }
-  }
-
-  private RefUpdateUtil() {}
-}
diff --git a/java/com/google/gerrit/server/update/RetryHelper.java b/java/com/google/gerrit/server/update/RetryHelper.java
index 10e3455..c8d338b 100644
--- a/java/com/google/gerrit/server/update/RetryHelper.java
+++ b/java/com/google/gerrit/server/update/RetryHelper.java
@@ -34,13 +34,13 @@
 import com.google.common.flogger.FluentLogger;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.extensions.restapi.RestApiException;
+import com.google.gerrit.git.LockFailureException;
 import com.google.gerrit.metrics.Counter1;
 import com.google.gerrit.metrics.Description;
 import com.google.gerrit.metrics.Field;
 import com.google.gerrit.metrics.Histogram1;
 import com.google.gerrit.metrics.MetricMaker;
 import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.git.LockFailureException;
 import com.google.gerrit.server.notedb.NotesMigration;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
diff --git a/java/com/google/gerrit/server/update/ReviewDbBatchUpdate.java b/java/com/google/gerrit/server/update/ReviewDbBatchUpdate.java
index c06447d..b859895 100644
--- a/java/com/google/gerrit/server/update/ReviewDbBatchUpdate.java
+++ b/java/com/google/gerrit/server/update/ReviewDbBatchUpdate.java
@@ -30,6 +30,7 @@
 import com.google.common.util.concurrent.MoreExecutors;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.RestApiException;
+import com.google.gerrit.git.LockFailureException;
 import com.google.gerrit.metrics.Description;
 import com.google.gerrit.metrics.Description.Units;
 import com.google.gerrit.metrics.Field;
@@ -48,7 +49,6 @@
 import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.InsertedObject;
-import com.google.gerrit.server.git.LockFailureException;
 import com.google.gerrit.server.index.change.ChangeIndexer;
 import com.google.gerrit.server.logging.TraceContext;
 import com.google.gerrit.server.notedb.ChangeNotes;
diff --git a/java/com/google/gerrit/sshd/BUILD b/java/com/google/gerrit/sshd/BUILD
index 8e1f112..e2826ff 100644
--- a/java/com/google/gerrit/sshd/BUILD
+++ b/java/com/google/gerrit/sshd/BUILD
@@ -20,7 +20,6 @@
         "//java/com/google/gerrit/server/schema",
         "//java/com/google/gerrit/server/util/time",
         "//java/com/google/gerrit/util/cli",
-        "//java/org/eclipse/jgit:server",
         "//lib:args4j",
         "//lib:gson",
         "//lib:guava",
diff --git a/java/com/google/gerrit/testing/InMemoryDatabase.java b/java/com/google/gerrit/testing/InMemoryDatabase.java
index 66a5290..b489652 100644
--- a/java/com/google/gerrit/testing/InMemoryDatabase.java
+++ b/java/com/google/gerrit/testing/InMemoryDatabase.java
@@ -22,8 +22,8 @@
 import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
 import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.index.IndexModule;
-import com.google.gerrit.server.schema.SchemaCreator;
-import com.google.gerrit.server.schema.SchemaVersion;
+import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
+import com.google.gerrit.server.schema.ReviewDbSchemaVersion;
 import com.google.gwtorm.jdbc.Database;
 import com.google.gwtorm.jdbc.SimpleDataSource;
 import com.google.gwtorm.server.OrmException;
@@ -61,7 +61,7 @@
     }
   }
 
-  private final SchemaCreator schemaCreator;
+  private final ReviewDbSchemaCreator schemaCreator;
   private final Instance dbInstance;
 
   private boolean created;
@@ -85,7 +85,7 @@
                 }
               }
             });
-    this.schemaCreator = childInjector.getInstance(SchemaCreator.class);
+    this.schemaCreator = childInjector.getInstance(ReviewDbSchemaCreator.class);
     Instance dbInstanceFromInjector = childInjector.getInstance(Instance.class);
     if (dbInstanceFromInjector != null) {
       this.dbInstance = dbInstanceFromInjector;
@@ -95,7 +95,7 @@
     }
   }
 
-  InMemoryDatabase(SchemaCreator schemaCreator) throws OrmException {
+  InMemoryDatabase(ReviewDbSchemaCreator schemaCreator) throws OrmException {
     this.schemaCreator = schemaCreator;
     this.dbInstance = new Instance();
   }
@@ -133,7 +133,7 @@
   }
 
   public void assertSchemaVersion() throws OrmException {
-    assertThat(getSchemaVersion().versionNbr).isEqualTo(SchemaVersion.getBinaryVersion());
+    assertThat(getSchemaVersion().versionNbr).isEqualTo(ReviewDbSchemaVersion.getBinaryVersion());
   }
 
   public static class Instance {
diff --git a/java/com/google/gerrit/testing/InMemoryModule.java b/java/com/google/gerrit/testing/InMemoryModule.java
index 18dfea0..fc17816 100644
--- a/java/com/google/gerrit/testing/InMemoryModule.java
+++ b/java/com/google/gerrit/testing/InMemoryModule.java
@@ -85,7 +85,7 @@
 import com.google.gerrit.server.schema.InMemoryAccountPatchReviewStore;
 import com.google.gerrit.server.schema.NotesMigrationSchemaFactory;
 import com.google.gerrit.server.schema.ReviewDbFactory;
-import com.google.gerrit.server.schema.SchemaCreator;
+import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
 import com.google.gerrit.server.securestore.DefaultSecureStore;
 import com.google.gerrit.server.securestore.SecureStore;
 import com.google.gerrit.server.ssh.NoSshKeyCache;
@@ -188,7 +188,7 @@
     // Configs, only FileBasedConfig.
     bind(Path.class).annotatedWith(SitePath.class).toInstance(Paths.get("."));
     bind(Config.class).annotatedWith(GerritServerConfig.class).toInstance(cfg);
-    bind(GerritOptions.class).toInstance(new GerritOptions(cfg, false, false, false));
+    bind(GerritOptions.class).toInstance(new GerritOptions(false, false, false));
     bind(PersonIdent.class)
         .annotatedWith(GerritPersonIdent.class)
         .toProvider(GerritPersonIdentProvider.class);
@@ -303,7 +303,7 @@
 
   @Provides
   @Singleton
-  InMemoryDatabase getInMemoryDatabase(SchemaCreator schemaCreator) throws OrmException {
+  InMemoryDatabase getInMemoryDatabase(ReviewDbSchemaCreator schemaCreator) throws OrmException {
     return new InMemoryDatabase(schemaCreator);
   }
 
diff --git a/java/com/google/gerrit/testing/InMemoryTestEnvironment.java b/java/com/google/gerrit/testing/InMemoryTestEnvironment.java
index cebd139..02be071 100644
--- a/java/com/google/gerrit/testing/InMemoryTestEnvironment.java
+++ b/java/com/google/gerrit/testing/InMemoryTestEnvironment.java
@@ -21,7 +21,7 @@
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountManager;
 import com.google.gerrit.server.account.AuthRequest;
-import com.google.gerrit.server.schema.SchemaCreator;
+import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
 import com.google.gerrit.server.util.RequestContext;
 import com.google.gerrit.server.util.ThreadLocalRequestContext;
 import com.google.gwtorm.server.SchemaFactory;
@@ -50,7 +50,7 @@
   @Inject private AccountManager accountManager;
   @Inject private IdentifiedUser.GenericFactory userFactory;
   @Inject private SchemaFactory<ReviewDb> schemaFactory;
-  @Inject private SchemaCreator schemaCreator;
+  @Inject private ReviewDbSchemaCreator schemaCreator;
   @Inject private ThreadLocalRequestContext requestContext;
   // Only for use in setting up/tearing down injector.
   @Inject private InMemoryDatabase inMemoryDatabase;
diff --git a/java/com/google/gerrit/testing/NoteDbMode.java b/java/com/google/gerrit/testing/NoteDbMode.java
index d4a7c7e..e46acc3 100644
--- a/java/com/google/gerrit/testing/NoteDbMode.java
+++ b/java/com/google/gerrit/testing/NoteDbMode.java
@@ -52,7 +52,7 @@
       value = System.getProperty(SYS_PROP);
     }
     if (Strings.isNullOrEmpty(value)) {
-      return OFF;
+      return ON;
     }
     value = value.toUpperCase().replace("-", "_");
     NoteDbMode mode = Enums.getIfPresent(NoteDbMode.class, value).orNull();
diff --git a/java/com/google/gwtexpui/clippy/BUILD b/java/com/google/gwtexpui/clippy/BUILD
deleted file mode 100644
index 80b6767..0000000
--- a/java/com/google/gwtexpui/clippy/BUILD
+++ /dev/null
@@ -1,23 +0,0 @@
-load("//tools/bzl:gwt.bzl", "gwt_module")
-
-gwt_module(
-    name = "clippy",
-    srcs = glob(["client/*.java"]),
-    data = [
-        "//lib:LICENSE-clippy",
-        "//lib:LICENSE-silk_icons",
-    ],
-    gwt_xml = "Clippy.gwt.xml",
-    resources = [
-        "client/CopyableLabelText.properties",
-        "client/clippy.css",
-        "client/clippy.swf",
-        "client/page_white_copy.png",
-    ],
-    visibility = ["//visibility:public"],
-    deps = [
-        "//java/com/google/gwtexpui/safehtml",
-        "//java/com/google/gwtexpui/user:agent",
-        "//lib/gwt:user-neverlink",
-    ],
-)
diff --git a/java/com/google/gwtexpui/clippy/Clippy.gwt.xml b/java/com/google/gwtexpui/clippy/Clippy.gwt.xml
deleted file mode 100644
index 0e9b072..0000000
--- a/java/com/google/gwtexpui/clippy/Clippy.gwt.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<!--
- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<module>
-  <inherits name='com.google.gwt.resources.Resources'/>
-  <inherits name="com.google.gwtexpui.safehtml.SafeHtml"/>
-  <inherits name="com.google.gwtexpui.user.User"/>
-</module>
diff --git a/java/com/google/gwtexpui/clippy/client/ClippyCss.java b/java/com/google/gwtexpui/clippy/client/ClippyCss.java
deleted file mode 100644
index 0d340ff..0000000
--- a/java/com/google/gwtexpui/clippy/client/ClippyCss.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.clippy.client;
-
-import com.google.gwt.resources.client.CssResource;
-
-public interface ClippyCss extends CssResource {
-  String label();
-
-  String copier();
-
-  String swf();
-}
diff --git a/java/com/google/gwtexpui/clippy/client/ClippyResources.java b/java/com/google/gwtexpui/clippy/client/ClippyResources.java
deleted file mode 100644
index a97b392..0000000
--- a/java/com/google/gwtexpui/clippy/client/ClippyResources.java
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.clippy.client;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.resources.client.ClientBundle;
-import com.google.gwt.resources.client.DataResource;
-import com.google.gwt.resources.client.DataResource.DoNotEmbed;
-import com.google.gwt.resources.client.ImageResource;
-
-public interface ClippyResources extends ClientBundle {
-  ClippyResources I = GWT.create(ClippyResources.class);
-
-  @Source("clippy.css")
-  ClippyCss css();
-
-  @Source("clippy.swf")
-  @DoNotEmbed
-  DataResource swf();
-
-  @Source("page_white_copy.png")
-  ImageResource clipboard();
-}
diff --git a/java/com/google/gwtexpui/clippy/client/CopyableLabel.java b/java/com/google/gwtexpui/clippy/client/CopyableLabel.java
deleted file mode 100644
index 7b70c6a..0000000
--- a/java/com/google/gwtexpui/clippy/client/CopyableLabel.java
+++ /dev/null
@@ -1,315 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.clippy.client;
-
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.Style.Display;
-import com.google.gwt.event.dom.client.BlurEvent;
-import com.google.gwt.event.dom.client.BlurHandler;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.event.dom.client.KeyUpEvent;
-import com.google.gwt.event.dom.client.KeyUpHandler;
-import com.google.gwt.event.dom.client.MouseOutEvent;
-import com.google.gwt.event.dom.client.MouseOutHandler;
-import com.google.gwt.http.client.URL;
-import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HasText;
-import com.google.gwt.user.client.ui.InlineLabel;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwtexpui.safehtml.client.SafeHtml;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-import com.google.gwtexpui.user.client.Tooltip;
-import com.google.gwtexpui.user.client.UserAgent;
-
-/**
- * Label which permits the user to easily copy the complete content.
- *
- * <p>If the Flash plugin is available a "movie" is embedded that provides one-click copying of the
- * content onto the system clipboard. The label (if visible) can also be clicked, switching from a
- * label to an input box, allowing the user to copy the text with a keyboard shortcut.
- */
-public class CopyableLabel extends Composite implements HasText {
-  private static final int SWF_WIDTH = 110;
-  private static final int SWF_HEIGHT = 14;
-  private static boolean flashEnabled = true;
-
-  static {
-    ClippyResources.I.css().ensureInjected();
-  }
-
-  public static boolean isFlashEnabled() {
-    return flashEnabled;
-  }
-
-  public static void setFlashEnabled(boolean on) {
-    flashEnabled = on;
-  }
-
-  private static String swfUrl() {
-    return ClippyResources.I.swf().getSafeUri().asString();
-  }
-
-  private final FlowPanel content;
-  private String text;
-  private int visibleLen;
-  private Label textLabel;
-  private TextBox textBox;
-  private Button copier;
-  private Element swf;
-
-  public CopyableLabel() {
-    this("");
-  }
-
-  /**
-   * Create a new label
-   *
-   * @param str initial content
-   */
-  public CopyableLabel(String str) {
-    this(str, true);
-  }
-
-  /**
-   * Create a new label
-   *
-   * @param str initial content
-   * @param showLabel if true, the content is shown, if false it is hidden from view and only the
-   *     copy icon is displayed.
-   */
-  public CopyableLabel(String str, boolean showLabel) {
-    content = new FlowPanel();
-    initWidget(content);
-
-    text = str;
-    visibleLen = text.length();
-
-    if (showLabel) {
-      textLabel = new InlineLabel(getText());
-      textLabel.setStyleName(ClippyResources.I.css().label());
-      textLabel.addClickHandler(
-          new ClickHandler() {
-            @Override
-            public void onClick(ClickEvent event) {
-              showTextBox();
-            }
-          });
-      content.add(textLabel);
-    }
-
-    if (UserAgent.hasJavaScriptClipboard()) {
-      copier =
-          new Button(
-              new SafeHtmlBuilder()
-                  .openElement("img")
-                  .setAttribute("src", ClippyResources.I.clipboard().getSafeUri().asString())
-                  .setWidth(14)
-                  .setHeight(14)
-                  .closeSelf());
-      copier.setStyleName(ClippyResources.I.css().copier());
-      Tooltip.addStyle(copier);
-      Tooltip.setLabel(copier, CopyableLabelText.I.tooltip());
-      copier.addClickHandler(
-          new ClickHandler() {
-            @Override
-            public void onClick(ClickEvent event) {
-              copy();
-            }
-          });
-      copier.addMouseOutHandler(
-          new MouseOutHandler() {
-            @Override
-            public void onMouseOut(MouseOutEvent event) {
-              Tooltip.setLabel(copier, CopyableLabelText.I.tooltip());
-            }
-          });
-
-      FlowPanel p = new FlowPanel();
-      p.getElement().getStyle().setDisplay(Display.INLINE_BLOCK);
-      p.add(copier);
-      content.add(p);
-    } else {
-      embedMovie();
-    }
-  }
-
-  /**
-   * Change the text which is displayed in the clickable label.
-   *
-   * @param text the new preview text, should be shorter than the original text which would be
-   *     copied to the clipboard.
-   */
-  public void setPreviewText(String text) {
-    if (textLabel != null) {
-      textLabel.setText(text);
-    }
-  }
-
-  private void embedMovie() {
-    if (copier == null && flashEnabled && !text.isEmpty() && UserAgent.Flash.isInstalled()) {
-      final String flashVars = "text=" + URL.encodeQueryString(getText());
-      final SafeHtmlBuilder h = new SafeHtmlBuilder();
-
-      h.openElement("div");
-      h.setStyleName(ClippyResources.I.css().swf());
-
-      h.openElement("object");
-      h.setWidth(SWF_WIDTH);
-      h.setHeight(SWF_HEIGHT);
-      h.setAttribute("classid", "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000");
-      h.paramElement("movie", swfUrl());
-      h.paramElement("FlashVars", flashVars);
-
-      h.openElement("embed");
-      h.setWidth(SWF_WIDTH);
-      h.setHeight(SWF_HEIGHT);
-      h.setAttribute("wmode", "transparent");
-      h.setAttribute("type", "application/x-shockwave-flash");
-      h.setAttribute("src", swfUrl());
-      h.setAttribute("FlashVars", flashVars);
-      h.closeSelf();
-
-      h.closeElement("object");
-      h.closeElement("div");
-
-      if (swf != null) {
-        getElement().removeChild(swf);
-      }
-      DOM.appendChild(getElement(), swf = SafeHtml.parse(h));
-    }
-  }
-
-  @Override
-  public String getText() {
-    return text;
-  }
-
-  @Override
-  public void setText(String newText) {
-    text = newText;
-    visibleLen = newText.length();
-
-    if (textLabel != null) {
-      textLabel.setText(getText());
-    }
-    if (textBox != null) {
-      textBox.setText(getText());
-      textBox.selectAll();
-    }
-    embedMovie();
-  }
-
-  private void showTextBox() {
-    if (textBox == null) {
-      textBox = new TextBox();
-      textBox.setText(getText());
-      textBox.setVisibleLength(visibleLen);
-      textBox.setReadOnly(true);
-      textBox.addKeyPressHandler(
-          new KeyPressHandler() {
-            @Override
-            public void onKeyPress(KeyPressEvent event) {
-              if (event.isControlKeyDown() || event.isMetaKeyDown()) {
-                switch (event.getCharCode()) {
-                  case 'c':
-                  case 'x':
-                    textBox.addKeyUpHandler(
-                        new KeyUpHandler() {
-                          @Override
-                          public void onKeyUp(KeyUpEvent event) {
-                            Scheduler.get()
-                                .scheduleDeferred(
-                                    new Command() {
-                                      @Override
-                                      public void execute() {
-                                        hideTextBox();
-                                      }
-                                    });
-                          }
-                        });
-                    break;
-                }
-              }
-            }
-          });
-      textBox.addBlurHandler(
-          new BlurHandler() {
-            @Override
-            public void onBlur(BlurEvent event) {
-              hideTextBox();
-            }
-          });
-      content.insert(textBox, 1);
-    }
-
-    textLabel.setVisible(false);
-    textBox.setVisible(true);
-    Scheduler.get()
-        .scheduleDeferred(
-            new Command() {
-              @Override
-              public void execute() {
-                textBox.selectAll();
-                textBox.setFocus(true);
-              }
-            });
-  }
-
-  private void hideTextBox() {
-    if (textBox != null) {
-      textBox.removeFromParent();
-      textBox = null;
-    }
-    textLabel.setVisible(true);
-  }
-
-  private void copy() {
-    TextBox t = new TextBox();
-    try {
-      t.setText(getText());
-      content.add(t);
-      t.setFocus(true);
-      t.selectAll();
-
-      boolean ok = execCommand("copy");
-      Tooltip.setLabel(copier, ok ? CopyableLabelText.I.copied() : CopyableLabelText.I.failed());
-      if (!ok) {
-        // Disable JavaScript clipboard and try flash movie in another instance.
-        UserAgent.disableJavaScriptClipboard();
-      }
-    } finally {
-      t.removeFromParent();
-    }
-  }
-
-  private static boolean execCommand(String command) {
-    try {
-      return nativeExec(command);
-    } catch (Exception e) {
-      return false;
-    }
-  }
-
-  private static native boolean nativeExec(String c) /*-{ return !! $doc.execCommand(c) }-*/;
-}
diff --git a/java/com/google/gwtexpui/clippy/client/CopyableLabelText.java b/java/com/google/gwtexpui/clippy/client/CopyableLabelText.java
deleted file mode 100644
index ff36541..0000000
--- a/java/com/google/gwtexpui/clippy/client/CopyableLabelText.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.clippy.client;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.i18n.client.Constants;
-
-interface CopyableLabelText extends Constants {
-  CopyableLabelText I = GWT.create(CopyableLabelText.class);
-
-  String tooltip();
-
-  String copied();
-
-  String failed();
-}
diff --git a/java/com/google/gwtexpui/clippy/client/CopyableLabelText.properties b/java/com/google/gwtexpui/clippy/client/CopyableLabelText.properties
deleted file mode 100644
index cf93bfa..0000000
--- a/java/com/google/gwtexpui/clippy/client/CopyableLabelText.properties
+++ /dev/null
@@ -1,3 +0,0 @@
-tooltip = Copy to clipboard
-copied = Copied
-failed = Failed !
diff --git a/java/com/google/gwtexpui/clippy/client/clippy.css b/java/com/google/gwtexpui/clippy/client/clippy.css
deleted file mode 100644
index b25e006..0000000
--- a/java/com/google/gwtexpui/clippy/client/clippy.css
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-.label {
-  vertical-align: top;
-}
-.swf, .copier {
-  margin-left: 5px;
-  height: 14px;
-  width: 14px;
-}
-.swf {
-  display: inline-block !important;
-  overflow: hidden;
-}
-.copier {
-  display: inline-block;
-  font-size: 12px;
-  vertical-align: top;
-  padding: 0;
-  border: 0;
-  background-color: inherit;
-  cursor: pointer;
-}
-.copier:focus {
-  outline: none;
-}
diff --git a/java/com/google/gwtexpui/clippy/client/clippy.swf b/java/com/google/gwtexpui/clippy/client/clippy.swf
deleted file mode 100644
index e46886c..0000000
--- a/java/com/google/gwtexpui/clippy/client/clippy.swf
+++ /dev/null
Binary files differ
diff --git a/java/com/google/gwtexpui/clippy/client/page_white_copy.png b/java/com/google/gwtexpui/clippy/client/page_white_copy.png
deleted file mode 100644
index a9f31a2..0000000
--- a/java/com/google/gwtexpui/clippy/client/page_white_copy.png
+++ /dev/null
Binary files differ
diff --git a/java/com/google/gwtexpui/css/BUILD b/java/com/google/gwtexpui/css/BUILD
deleted file mode 100644
index 6c2fc71..0000000
--- a/java/com/google/gwtexpui/css/BUILD
+++ /dev/null
@@ -1,9 +0,0 @@
-load("//tools/bzl:gwt.bzl", "gwt_module")
-
-java_library(
-    name = "css",
-    srcs = glob(["rebind/*.java"]),
-    resources = ["CSS.gwt.xml"],
-    visibility = ["//visibility:public"],
-    deps = ["//lib/gwt:dev"],
-)
diff --git a/java/com/google/gwtexpui/css/CSS.gwt.xml b/java/com/google/gwtexpui/css/CSS.gwt.xml
deleted file mode 100644
index b385987..0000000
--- a/java/com/google/gwtexpui/css/CSS.gwt.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<!--
- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<module>
-  <define-linker name='cachecss' class='com.google.gwtexpui.css.rebind.CssLinker'/>
-  <add-linker name='cachecss'/>
-</module>
diff --git a/java/com/google/gwtexpui/css/rebind/CssLinker.java b/java/com/google/gwtexpui/css/rebind/CssLinker.java
deleted file mode 100644
index 6ef5d7b..0000000
--- a/java/com/google/gwtexpui/css/rebind/CssLinker.java
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.css.rebind;
-
-import com.google.gwt.core.ext.LinkerContext;
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.linker.AbstractLinker;
-import com.google.gwt.core.ext.linker.Artifact;
-import com.google.gwt.core.ext.linker.ArtifactSet;
-import com.google.gwt.core.ext.linker.LinkerOrder;
-import com.google.gwt.core.ext.linker.PublicResource;
-import com.google.gwt.core.ext.linker.impl.StandardLinkerContext;
-import com.google.gwt.core.ext.linker.impl.StandardStylesheetReference;
-import com.google.gwt.dev.util.Util;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashMap;
-
-@LinkerOrder(LinkerOrder.Order.PRE)
-public class CssLinker extends AbstractLinker {
-  @Override
-  public String getDescription() {
-    return "CssLinker";
-  }
-
-  @Override
-  public ArtifactSet link(final TreeLogger logger, LinkerContext context, ArtifactSet artifacts)
-      throws UnableToCompleteException {
-    final ArtifactSet returnTo = new ArtifactSet();
-    int index = 0;
-
-    final HashMap<String, PublicResource> css = new HashMap<>();
-
-    for (StandardStylesheetReference ssr :
-        artifacts.<StandardStylesheetReference>find(StandardStylesheetReference.class)) {
-      css.put(ssr.getSrc(), null);
-    }
-    for (PublicResource pr : artifacts.<PublicResource>find(PublicResource.class)) {
-      if (css.containsKey(pr.getPartialPath())) {
-        css.put(pr.getPartialPath(), new CssPubRsrc(name(logger, pr), pr));
-      }
-    }
-
-    for (Artifact<?> a : artifacts) {
-      if (a instanceof PublicResource) {
-        final PublicResource r = (PublicResource) a;
-        if (css.containsKey(r.getPartialPath())) {
-          a = css.get(r.getPartialPath());
-        }
-      } else if (a instanceof StandardStylesheetReference) {
-        final StandardStylesheetReference r = (StandardStylesheetReference) a;
-        final PublicResource p = css.get(r.getSrc());
-        a = new StandardStylesheetReference(p.getPartialPath(), index);
-      }
-
-      returnTo.add(a);
-      index++;
-    }
-    return returnTo;
-  }
-
-  private String name(TreeLogger logger, PublicResource r) throws UnableToCompleteException {
-    byte[] out;
-    try (ByteArrayOutputStream tmp = new ByteArrayOutputStream();
-        InputStream in = r.getContents(logger)) {
-      final byte[] buf = new byte[2048];
-      int n;
-      while ((n = in.read(buf)) >= 0) {
-        tmp.write(buf, 0, n);
-      }
-      out = tmp.toByteArray();
-    } catch (IOException e) {
-      final UnableToCompleteException ute = new UnableToCompleteException();
-      ute.initCause(e);
-      throw ute;
-    }
-
-    String base = r.getPartialPath();
-    final int s = base.lastIndexOf('/');
-    if (0 < s) {
-      base = base.substring(0, s + 1);
-    } else {
-      base = "";
-    }
-    return base + Util.computeStrongName(out) + ".cache.css";
-  }
-
-  private static class CssPubRsrc extends PublicResource {
-    private static final long serialVersionUID = 1L;
-    private final PublicResource src;
-
-    CssPubRsrc(String partialPath, PublicResource r) {
-      super(StandardLinkerContext.class, partialPath);
-      src = r;
-    }
-
-    @Override
-    public InputStream getContents(TreeLogger logger) throws UnableToCompleteException {
-      return src.getContents(logger);
-    }
-
-    @Override
-    public long getLastModified() {
-      return src.getLastModified();
-    }
-  }
-}
diff --git a/java/com/google/gwtexpui/globalkey/BUILD b/java/com/google/gwtexpui/globalkey/BUILD
deleted file mode 100644
index c637194..0000000
--- a/java/com/google/gwtexpui/globalkey/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-load("//tools/bzl:gwt.bzl", "gwt_module")
-
-gwt_module(
-    name = "globalkey",
-    srcs = glob(["client/*.java"]),
-    gwt_xml = "GlobalKey.gwt.xml",
-    resources = [
-        "client/KeyConstants.properties",
-        "client/key.css",
-    ],
-    visibility = ["//visibility:public"],
-    deps = [
-        "//java/com/google/gwtexpui/safehtml",
-        "//java/com/google/gwtexpui/user:agent",
-        "//lib/gwt:user",
-    ],
-)
diff --git a/java/com/google/gwtexpui/globalkey/GlobalKey.gwt.xml b/java/com/google/gwtexpui/globalkey/GlobalKey.gwt.xml
deleted file mode 100644
index 771050f..0000000
--- a/java/com/google/gwtexpui/globalkey/GlobalKey.gwt.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<!--
- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<module>
-  <inherits name='com.google.gwt.resources.Resources'/>
-  <inherits name='com.google.gwtexpui.user.User'/>
-  <inherits name='com.google.gwtexpui.safehtml.SafeHtml'/>
-</module>
diff --git a/java/com/google/gwtexpui/globalkey/client/CompoundKeyCommand.java b/java/com/google/gwtexpui/globalkey/client/CompoundKeyCommand.java
deleted file mode 100644
index 5a4f6aa..0000000
--- a/java/com/google/gwtexpui/globalkey/client/CompoundKeyCommand.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.globalkey.client;
-
-import com.google.gwt.event.dom.client.KeyPressEvent;
-
-public final class CompoundKeyCommand extends KeyCommand {
-  final KeyCommandSet set;
-
-  public CompoundKeyCommand(int mask, char key, String help, KeyCommandSet s) {
-    super(mask, key, help);
-    set = s;
-  }
-
-  public CompoundKeyCommand(int mask, int key, String help, KeyCommandSet s) {
-    super(mask, key, help);
-    set = s;
-  }
-
-  public KeyCommandSet getSet() {
-    return set;
-  }
-
-  @Override
-  public void onKeyPress(KeyPressEvent event) {
-    GlobalKey.temporaryWithTimeout(set);
-  }
-}
diff --git a/java/com/google/gwtexpui/globalkey/client/DocWidget.java b/java/com/google/gwtexpui/globalkey/client/DocWidget.java
deleted file mode 100644
index 320010e..0000000
--- a/java/com/google/gwtexpui/globalkey/client/DocWidget.java
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.globalkey.client;
-
-import com.google.gwt.dom.client.Document;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.Node;
-import com.google.gwt.event.dom.client.HasKeyPressHandlers;
-import com.google.gwt.event.dom.client.HasMouseMoveHandlers;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.event.dom.client.MouseMoveEvent;
-import com.google.gwt.event.dom.client.MouseMoveHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.Widget;
-
-public class DocWidget extends Widget implements HasKeyPressHandlers, HasMouseMoveHandlers {
-  private static DocWidget me;
-
-  public static DocWidget get() {
-    if (me == null) {
-      me = new DocWidget();
-    }
-    return me;
-  }
-
-  private DocWidget() {
-    setElement((Element) docnode());
-    onAttach();
-    RootPanel.detachOnWindowClose(this);
-  }
-
-  @Override
-  public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) {
-    return addDomHandler(handler, KeyPressEvent.getType());
-  }
-
-  @Override
-  public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler) {
-    return addDomHandler(handler, MouseMoveEvent.getType());
-  }
-
-  private static Node docnode() {
-    return Document.get();
-  }
-}
diff --git a/java/com/google/gwtexpui/globalkey/client/GlobalKey.java b/java/com/google/gwtexpui/globalkey/client/GlobalKey.java
deleted file mode 100644
index cbaca61..0000000
--- a/java/com/google/gwtexpui/globalkey/client/GlobalKey.java
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.globalkey.client;
-
-import com.google.gwt.event.dom.client.DomEvent;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyDownEvent;
-import com.google.gwt.event.dom.client.KeyDownHandler;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.Widget;
-
-public class GlobalKey {
-  public static final KeyPressHandler STOP_PROPAGATION = DomEvent::stopPropagation;
-
-  private static State global;
-  static State active;
-  private static CloseHandler<PopupPanel> restoreGlobal;
-  private static Timer restoreTimer;
-
-  static {
-    KeyResources.I.css().ensureInjected();
-  }
-
-  private static void initEvents() {
-    if (active == null) {
-      DocWidget.get()
-          .addKeyPressHandler(
-              new KeyPressHandler() {
-                @Override
-                public void onKeyPress(KeyPressEvent event) {
-                  final KeyCommandSet s = active.live;
-                  if (s != active.all) {
-                    active.live = active.all;
-                    restoreTimer.cancel();
-                  }
-                  s.onKeyPress(event);
-                }
-              });
-
-      restoreTimer =
-          new Timer() {
-            @Override
-            public void run() {
-              active.live = active.all;
-            }
-          };
-
-      global = new State(null);
-      active = global;
-    }
-  }
-
-  private static void initDialog() {
-    if (restoreGlobal == null) {
-      restoreGlobal =
-          new CloseHandler<PopupPanel>() {
-            @Override
-            public void onClose(CloseEvent<PopupPanel> event) {
-              active = global;
-            }
-          };
-    }
-  }
-
-  static void temporaryWithTimeout(KeyCommandSet s) {
-    active.live = s;
-    restoreTimer.schedule(250);
-  }
-
-  public static void dialog(PopupPanel panel) {
-    initEvents();
-    initDialog();
-    assert panel.isShowing();
-    assert active == global;
-    active = new State(panel);
-    active.add(new HidePopupPanelCommand(0, KeyCodes.KEY_ESCAPE, panel));
-    panel.addCloseHandler(restoreGlobal);
-    panel.addDomHandler(
-        new KeyDownHandler() {
-          @Override
-          public void onKeyDown(KeyDownEvent event) {
-            if (event.getNativeKeyCode() == KeyCodes.KEY_ESCAPE) {
-              panel.hide();
-            }
-          }
-        },
-        KeyDownEvent.getType());
-  }
-
-  public static HandlerRegistration addApplication(Widget widget, KeyCommand appKey) {
-    initEvents();
-    final State state = stateFor(widget);
-    state.add(appKey);
-    return new HandlerRegistration() {
-      @Override
-      public void removeHandler() {
-        state.remove(appKey);
-      }
-    };
-  }
-
-  public static HandlerRegistration add(Widget widget, KeyCommandSet cmdSet) {
-    initEvents();
-    final State state = stateFor(widget);
-    state.add(cmdSet);
-    return new HandlerRegistration() {
-      @Override
-      public void removeHandler() {
-        state.remove(cmdSet);
-      }
-    };
-  }
-
-  private static State stateFor(Widget w) {
-    while (w != null) {
-      if (w == active.root) {
-        return active;
-      }
-      w = w.getParent();
-    }
-    return global;
-  }
-
-  public static void filter(KeyCommandFilter filter) {
-    active.filter(filter);
-    if (active != global) {
-      global.filter(filter);
-    }
-  }
-
-  private GlobalKey() {}
-
-  static class State {
-    final Widget root;
-    final KeyCommandSet app;
-    final KeyCommandSet all;
-    KeyCommandSet live;
-
-    State(Widget r) {
-      root = r;
-
-      app = new KeyCommandSet(KeyConstants.I.applicationSection());
-      app.add(ShowHelpCommand.INSTANCE);
-
-      all = new KeyCommandSet();
-      all.add(app);
-
-      live = all;
-    }
-
-    void add(KeyCommand k) {
-      app.add(k);
-      all.add(k);
-    }
-
-    void remove(KeyCommand k) {
-      app.remove(k);
-      all.remove(k);
-    }
-
-    void add(KeyCommandSet s) {
-      all.add(s);
-    }
-
-    void remove(KeyCommandSet s) {
-      all.remove(s);
-    }
-
-    void filter(KeyCommandFilter f) {
-      all.filter(f);
-    }
-  }
-}
diff --git a/java/com/google/gwtexpui/globalkey/client/HidePopupPanelCommand.java b/java/com/google/gwtexpui/globalkey/client/HidePopupPanelCommand.java
deleted file mode 100644
index 8222f8b..0000000
--- a/java/com/google/gwtexpui/globalkey/client/HidePopupPanelCommand.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.globalkey.client;
-
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.user.client.ui.PopupPanel;
-
-/** Hides the given popup panel when invoked. */
-public class HidePopupPanelCommand extends KeyCommand {
-  private final PopupPanel panel;
-
-  public HidePopupPanelCommand(int mask, int key, PopupPanel panel) {
-    super(mask, key, KeyConstants.I.closeCurrentDialog());
-    this.panel = panel;
-  }
-
-  @Override
-  public void onKeyPress(KeyPressEvent event) {
-    panel.hide();
-  }
-}
diff --git a/java/com/google/gwtexpui/globalkey/client/KeyCommand.java b/java/com/google/gwtexpui/globalkey/client/KeyCommand.java
deleted file mode 100644
index f1c92e0..0000000
--- a/java/com/google/gwtexpui/globalkey/client/KeyCommand.java
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.globalkey.client;
-
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwtexpui.safehtml.client.SafeHtml;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-
-public abstract class KeyCommand implements KeyPressHandler {
-  public static final int M_CTRL = 1 << 16;
-  public static final int M_ALT = 2 << 16;
-  public static final int M_META = 4 << 16;
-  public static final int M_SHIFT = 8 << 16;
-
-  public static boolean same(KeyCommand a, KeyCommand b) {
-    return a.getClass() == b.getClass() && a.helpText.equals(b.helpText) && a.sibling == b.sibling;
-  }
-
-  final int keyMask;
-  private final String helpText;
-  KeyCommand sibling;
-
-  public KeyCommand(int mask, int key, String help) {
-    this(mask, (char) key, help);
-  }
-
-  public KeyCommand(int mask, char key, String help) {
-    assert help != null;
-    keyMask = mask | key;
-    helpText = help;
-  }
-
-  public String getHelpText() {
-    return helpText;
-  }
-
-  SafeHtml describeKeyStroke() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-
-    if ((keyMask & M_CTRL) == M_CTRL) {
-      modifier(b, KeyConstants.I.keyCtrl());
-    }
-    if ((keyMask & M_ALT) == M_ALT) {
-      modifier(b, KeyConstants.I.keyAlt());
-    }
-    if ((keyMask & M_META) == M_META) {
-      modifier(b, KeyConstants.I.keyMeta());
-    }
-    if ((keyMask & M_SHIFT) == M_SHIFT) {
-      modifier(b, KeyConstants.I.keyShift());
-    }
-
-    final char c = (char) (keyMask & 0xffff);
-    switch (c) {
-      case KeyCodes.KEY_ENTER:
-        namedKey(b, KeyConstants.I.keyEnter());
-        break;
-      case KeyCodes.KEY_ESCAPE:
-        namedKey(b, KeyConstants.I.keyEsc());
-        break;
-      case KeyCodes.KEY_LEFT:
-        namedKey(b, KeyConstants.I.keyLeft());
-        break;
-      case KeyCodes.KEY_RIGHT:
-        namedKey(b, KeyConstants.I.keyRight());
-        break;
-      default:
-        b.openSpan();
-        b.setStyleName(KeyResources.I.css().helpKey());
-        b.append(String.valueOf(c));
-        b.closeSpan();
-        break;
-    }
-
-    return b;
-  }
-
-  private void modifier(SafeHtmlBuilder b, String name) {
-    namedKey(b, name);
-    b.append(" + ");
-  }
-
-  private void namedKey(SafeHtmlBuilder b, String name) {
-    b.append('<');
-    b.openSpan();
-    b.setStyleName(KeyResources.I.css().helpKey());
-    b.append(name);
-    b.closeSpan();
-    b.append(">");
-  }
-}
diff --git a/java/com/google/gwtexpui/globalkey/client/KeyCommandFilter.java b/java/com/google/gwtexpui/globalkey/client/KeyCommandFilter.java
deleted file mode 100644
index 4b67260..0000000
--- a/java/com/google/gwtexpui/globalkey/client/KeyCommandFilter.java
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.globalkey.client;
-
-public interface KeyCommandFilter {
-  boolean include(KeyCommand key);
-}
diff --git a/java/com/google/gwtexpui/globalkey/client/KeyCommandSet.java b/java/com/google/gwtexpui/globalkey/client/KeyCommandSet.java
deleted file mode 100644
index 90aa419..0000000
--- a/java/com/google/gwtexpui/globalkey/client/KeyCommandSet.java
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.globalkey.client;
-
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-public class KeyCommandSet implements KeyPressHandler {
-  private final Map<Integer, KeyCommand> map;
-  private List<KeyCommandSet> sets;
-  private String name;
-
-  public KeyCommandSet() {
-    this("");
-  }
-
-  public KeyCommandSet(String setName) {
-    map = new HashMap<>();
-    name = setName;
-  }
-
-  public String getName() {
-    return name;
-  }
-
-  public void setName(String setName) {
-    assert setName != null;
-    name = setName;
-  }
-
-  public boolean isEmpty() {
-    return map.isEmpty();
-  }
-
-  public void add(KeyCommand a, KeyCommand b) {
-    add(a);
-    add(b);
-    pair(a, b);
-  }
-
-  public void pair(KeyCommand a, KeyCommand b) {
-    a.sibling = b;
-    b.sibling = a;
-  }
-
-  public void add(KeyCommand k) {
-    assert !map.containsKey(k.keyMask)
-        : "Key " + k.describeKeyStroke().asString() + " already registered";
-    if (!map.containsKey(k.keyMask)) {
-      map.put(k.keyMask, k);
-    }
-  }
-
-  public void remove(KeyCommand k) {
-    assert map.get(k.keyMask) == k;
-    map.remove(k.keyMask);
-  }
-
-  public void add(KeyCommandSet set) {
-    if (sets == null) {
-      sets = new ArrayList<>();
-    }
-    assert !sets.contains(set);
-    sets.add(set);
-    for (KeyCommand k : set.map.values()) {
-      add(k);
-    }
-  }
-
-  public void remove(KeyCommandSet set) {
-    assert sets != null;
-    assert sets.contains(set);
-    sets.remove(set);
-    for (KeyCommand k : set.map.values()) {
-      remove(k);
-    }
-  }
-
-  public void filter(KeyCommandFilter filter) {
-    if (sets != null) {
-      for (KeyCommandSet s : sets) {
-        s.filter(filter);
-      }
-    }
-    for (Iterator<KeyCommand> i = map.values().iterator(); i.hasNext(); ) {
-      final KeyCommand kc = i.next();
-      if (!filter.include(kc)) {
-        i.remove();
-      } else if (kc instanceof CompoundKeyCommand) {
-        ((CompoundKeyCommand) kc).set.filter(filter);
-      }
-    }
-  }
-
-  public Collection<KeyCommand> getKeys() {
-    return map.values();
-  }
-
-  public Collection<KeyCommandSet> getSets() {
-    return sets != null ? sets : Collections.<KeyCommandSet>emptyList();
-  }
-
-  @Override
-  public void onKeyPress(KeyPressEvent event) {
-    final KeyCommand k = map.get(toMask(event));
-    if (k != null) {
-      event.preventDefault();
-      event.stopPropagation();
-      k.onKeyPress(event);
-    }
-  }
-
-  static int toMask(KeyPressEvent event) {
-    int mask = event.getUnicodeCharCode();
-    if (mask == 0) {
-      mask = event.getNativeEvent().getKeyCode();
-    }
-    if (event.isControlKeyDown()) {
-      mask |= KeyCommand.M_CTRL;
-    }
-    if (event.isMetaKeyDown()) {
-      mask |= KeyCommand.M_META;
-    }
-    return mask;
-  }
-}
diff --git a/java/com/google/gwtexpui/globalkey/client/KeyConstants.java b/java/com/google/gwtexpui/globalkey/client/KeyConstants.java
deleted file mode 100644
index 209b170..0000000
--- a/java/com/google/gwtexpui/globalkey/client/KeyConstants.java
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.globalkey.client;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.i18n.client.Constants;
-
-public interface KeyConstants extends Constants {
-  KeyConstants I = GWT.create(KeyConstants.class);
-
-  String applicationSection();
-
-  String showHelp();
-
-  String closeCurrentDialog();
-
-  String keyboardShortcuts();
-
-  String closeButton();
-
-  String orOtherKey();
-
-  String thenOtherKey();
-
-  String keyCtrl();
-
-  String keyAlt();
-
-  String keyMeta();
-
-  String keyShift();
-
-  String keyEnter();
-
-  String keyEsc();
-
-  String keyLeft();
-
-  String keyRight();
-}
diff --git a/java/com/google/gwtexpui/globalkey/client/KeyConstants.properties b/java/com/google/gwtexpui/globalkey/client/KeyConstants.properties
deleted file mode 100644
index 76a0318..0000000
--- a/java/com/google/gwtexpui/globalkey/client/KeyConstants.properties
+++ /dev/null
@@ -1,17 +0,0 @@
-applicationSection = Application
-showHelp = Open shortcut help
-closeCurrentDialog = Close current dialog
-
-keyboardShortcuts = Keyboard Shortcuts
-closeButton = Close
-orOtherKey = or
-thenOtherKey = then
-
-keyCtrl = Ctrl
-keyAlt = Alt
-keyMeta = Meta
-keyShift = Shift
-keyEnter = Enter
-keyEsc = Esc
-keyLeft = Left
-keyRight = Right
diff --git a/java/com/google/gwtexpui/globalkey/client/KeyCss.java b/java/com/google/gwtexpui/globalkey/client/KeyCss.java
deleted file mode 100644
index 658af57..0000000
--- a/java/com/google/gwtexpui/globalkey/client/KeyCss.java
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.globalkey.client;
-
-import com.google.gwt.resources.client.CssResource;
-
-public interface KeyCss extends CssResource {
-  String helpPopup();
-
-  String helpHeader();
-
-  String helpHeaderGlue();
-
-  String helpTable();
-
-  String helpTableGlue();
-
-  String helpGroup();
-
-  String helpKeyStroke();
-
-  String helpSeparator();
-
-  String helpKey();
-}
diff --git a/java/com/google/gwtexpui/globalkey/client/KeyHelpPopup.java b/java/com/google/gwtexpui/globalkey/client/KeyHelpPopup.java
deleted file mode 100644
index 20d093e..0000000
--- a/java/com/google/gwtexpui/globalkey/client/KeyHelpPopup.java
+++ /dev/null
@@ -1,233 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.globalkey.client;
-
-import static java.util.Comparator.comparing;
-import static java.util.stream.Collectors.toList;
-
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyDownEvent;
-import com.google.gwt.event.dom.client.KeyDownHandler;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.FocusPanel;
-import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
-import com.google.gwt.user.client.ui.HasHorizontalAlignment;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwtexpui.safehtml.client.SafeHtml;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-public class KeyHelpPopup extends PopupPanel implements KeyPressHandler, KeyDownHandler {
-  private final FocusPanel focus;
-
-  public KeyHelpPopup() {
-    super(true /* autohide */, true /* modal */);
-    setStyleName(KeyResources.I.css().helpPopup());
-
-    final Anchor closer = new Anchor(KeyConstants.I.closeButton());
-    closer.addClickHandler(
-        new ClickHandler() {
-          @Override
-          public void onClick(ClickEvent event) {
-            hide();
-          }
-        });
-
-    final Grid header = new Grid(1, 3);
-    header.setStyleName(KeyResources.I.css().helpHeader());
-    header.setText(0, 0, KeyConstants.I.keyboardShortcuts());
-    header.setWidget(0, 2, closer);
-
-    final CellFormatter fmt = header.getCellFormatter();
-    fmt.addStyleName(0, 1, KeyResources.I.css().helpHeaderGlue());
-    fmt.setHorizontalAlignment(0, 2, HasHorizontalAlignment.ALIGN_RIGHT);
-
-    final Grid lists = new Grid(0, 7);
-    lists.setStyleName(KeyResources.I.css().helpTable());
-    populate(lists);
-    lists.getCellFormatter().addStyleName(0, 3, KeyResources.I.css().helpTableGlue());
-
-    final FlowPanel body = new FlowPanel();
-    body.add(header);
-    body.getElement().appendChild(DOM.createElement("hr"));
-    body.add(lists);
-
-    focus = new FocusPanel(body);
-    focus.getElement().getStyle().setProperty("outline", "0px");
-    focus.getElement().setAttribute("hideFocus", "true");
-    focus.addKeyPressHandler(this);
-    focus.addKeyDownHandler(this);
-    add(focus);
-  }
-
-  @Override
-  public void setVisible(boolean show) {
-    super.setVisible(show);
-    if (show) {
-      focus.setFocus(true);
-    }
-  }
-
-  @Override
-  public void onKeyPress(KeyPressEvent event) {
-    if (KeyCommandSet.toMask(event) == ShowHelpCommand.INSTANCE.keyMask) {
-      // Block the '?' key from triggering us to show right after
-      // we just hide ourselves.
-      //
-      event.stopPropagation();
-      event.preventDefault();
-    }
-    hide();
-  }
-
-  @Override
-  public void onKeyDown(KeyDownEvent event) {
-    if (event.getNativeKeyCode() == KeyCodes.KEY_ESCAPE) {
-      hide();
-    }
-  }
-
-  private void populate(Grid lists) {
-    int[] end = new int[5];
-    int column = 0;
-    for (KeyCommandSet set : combinedSetsByName()) {
-      int row = end[column];
-      row = formatGroup(lists, row, column, set);
-      end[column] = row;
-      if (column == 0) {
-        column = 4;
-      } else {
-        column = 0;
-      }
-    }
-  }
-
-  /**
-   * @return an ordered collection of KeyCommandSet, combining sets which share the same name, so
-   *     that each set name appears at most once.
-   */
-  private static Collection<KeyCommandSet> combinedSetsByName() {
-    LinkedHashMap<String, KeyCommandSet> byName = new LinkedHashMap<>();
-    for (KeyCommandSet set : GlobalKey.active.all.getSets()) {
-      KeyCommandSet v = byName.get(set.getName());
-      if (v == null) {
-        v = new KeyCommandSet(set.getName());
-        byName.put(v.getName(), v);
-      }
-      v.add(set);
-    }
-    return byName.values();
-  }
-
-  private int formatGroup(Grid lists, int row, int col, KeyCommandSet set) {
-    if (set.isEmpty()) {
-      return row;
-    }
-
-    if (lists.getRowCount() < row + 1) {
-      lists.resizeRows(row + 1);
-    }
-    lists.setText(row, col + 2, set.getName());
-    lists.getCellFormatter().addStyleName(row, col + 2, KeyResources.I.css().helpGroup());
-    row++;
-
-    return formatKeys(lists, row, col, set, null);
-  }
-
-  private int formatKeys(final Grid lists, int row, int col, KeyCommandSet set, SafeHtml prefix) {
-    final CellFormatter fmt = lists.getCellFormatter();
-    final List<KeyCommand> keys = sort(set);
-    if (lists.getRowCount() < row + keys.size()) {
-      lists.resizeRows(row + keys.size());
-    }
-
-    Map<KeyCommand, Integer> rows = new HashMap<>();
-    FORMAT_KEYS:
-    for (int i = 0; i < keys.size(); i++) {
-      final KeyCommand k = keys.get(i);
-      if (rows.containsKey(k)) {
-        continue;
-      }
-
-      if (k instanceof CompoundKeyCommand) {
-        final SafeHtmlBuilder b = new SafeHtmlBuilder();
-        b.append(k.describeKeyStroke());
-        row = formatKeys(lists, row, col, ((CompoundKeyCommand) k).getSet(), b);
-        continue;
-      }
-
-      for (int prior = 0; prior < i; prior++) {
-        if (KeyCommand.same(keys.get(prior), k)) {
-          final int r = rows.get(keys.get(prior));
-          final SafeHtmlBuilder b = new SafeHtmlBuilder();
-          b.append(SafeHtml.get(lists, r, col + 0));
-          b.append(" ");
-          b.append(KeyConstants.I.orOtherKey());
-          b.append(" ");
-          if (prefix != null) {
-            b.append(prefix);
-            b.append(" ");
-            b.append(KeyConstants.I.thenOtherKey());
-            b.append(" ");
-          }
-          b.append(k.describeKeyStroke());
-          SafeHtml.set(lists, r, col + 0, b);
-          rows.put(k, r);
-          continue FORMAT_KEYS;
-        }
-      }
-
-      SafeHtmlBuilder b = new SafeHtmlBuilder();
-      String t = k.getHelpText();
-      if (prefix != null) {
-        b.append(prefix);
-        b.append(" ");
-        b.append(KeyConstants.I.thenOtherKey());
-        b.append(" ");
-      }
-      b.append(k.describeKeyStroke());
-      if (k.sibling != null) {
-        b.append(" / ").append(k.sibling.describeKeyStroke());
-        t += " / " + k.sibling.getHelpText();
-        rows.put(k.sibling, row);
-      }
-      SafeHtml.set(lists, row, col + 0, b);
-      lists.setText(row, col + 1, ":");
-      lists.setText(row, col + 2, t);
-      rows.put(k, row);
-
-      fmt.addStyleName(row, col + 0, KeyResources.I.css().helpKeyStroke());
-      fmt.addStyleName(row, col + 1, KeyResources.I.css().helpSeparator());
-      row++;
-    }
-
-    return row;
-  }
-
-  private List<KeyCommand> sort(KeyCommandSet set) {
-    return set.getKeys().stream().sorted(comparing(KeyCommand::getHelpText)).collect(toList());
-  }
-}
diff --git a/java/com/google/gwtexpui/globalkey/client/KeyResources.java b/java/com/google/gwtexpui/globalkey/client/KeyResources.java
deleted file mode 100644
index 562e12d..0000000
--- a/java/com/google/gwtexpui/globalkey/client/KeyResources.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.globalkey.client;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.resources.client.ClientBundle;
-
-public interface KeyResources extends ClientBundle {
-  KeyResources I = GWT.create(KeyResources.class);
-
-  @Source("key.css")
-  KeyCss css();
-}
diff --git a/java/com/google/gwtexpui/globalkey/client/NpTextArea.java b/java/com/google/gwtexpui/globalkey/client/NpTextArea.java
deleted file mode 100644
index fd0da74..0000000
--- a/java/com/google/gwtexpui/globalkey/client/NpTextArea.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.globalkey.client;
-
-import com.google.gwt.user.client.ui.TextArea;
-
-public class NpTextArea extends TextArea {
-  public NpTextArea() {
-    addKeyPressHandler(GlobalKey.STOP_PROPAGATION);
-  }
-
-  public void setSpellCheck(boolean spell) {
-    getElement().setPropertyBoolean("spellcheck", spell);
-  }
-}
diff --git a/java/com/google/gwtexpui/globalkey/client/NpTextBox.java b/java/com/google/gwtexpui/globalkey/client/NpTextBox.java
deleted file mode 100644
index 1392675..0000000
--- a/java/com/google/gwtexpui/globalkey/client/NpTextBox.java
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.globalkey.client;
-
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.user.client.ui.TextBox;
-
-public class NpTextBox extends TextBox {
-  public NpTextBox() {
-    addKeyPressHandler(GlobalKey.STOP_PROPAGATION);
-  }
-
-  public NpTextBox(Element element) {
-    super(element);
-    addKeyPressHandler(GlobalKey.STOP_PROPAGATION);
-  }
-}
diff --git a/java/com/google/gwtexpui/globalkey/client/ShowHelpCommand.java b/java/com/google/gwtexpui/globalkey/client/ShowHelpCommand.java
deleted file mode 100644
index 08217f4..0000000
--- a/java/com/google/gwtexpui/globalkey/client/ShowHelpCommand.java
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.globalkey.client;
-
-import com.google.gwt.event.dom.client.FocusEvent;
-import com.google.gwt.event.dom.client.FocusHandler;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.event.shared.EventBus;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.event.shared.SimpleEventBus;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.PopupPanel.PositionCallback;
-
-public class ShowHelpCommand extends KeyCommand {
-  public static final ShowHelpCommand INSTANCE = new ShowHelpCommand();
-  private static final EventBus BUS = new SimpleEventBus();
-  private static KeyHelpPopup current;
-
-  public static HandlerRegistration addFocusHandler(FocusHandler fh) {
-    return BUS.addHandler(FocusEvent.getType(), fh);
-  }
-
-  public ShowHelpCommand() {
-    super(0, '?', KeyConstants.I.showHelp());
-  }
-
-  @Override
-  public void onKeyPress(KeyPressEvent event) {
-    if (current != null) {
-      // Already open? Close the dialog.
-      //
-      current.hide();
-      return;
-    }
-
-    final KeyHelpPopup help = new KeyHelpPopup();
-    help.addCloseHandler(
-        new CloseHandler<PopupPanel>() {
-          @Override
-          public void onClose(CloseEvent<PopupPanel> event) {
-            current = null;
-            BUS.fireEvent(new FocusEvent() {});
-          }
-        });
-    current = help;
-    help.setPopupPositionAndShow(
-        new PositionCallback() {
-          @Override
-          public void setPosition(int pWidth, int pHeight) {
-            final int left = (Window.getClientWidth() - pWidth) >> 1;
-            final int wLeft = Window.getScrollLeft();
-            final int wTop = Window.getScrollTop();
-            help.setPopupPosition(wLeft + left, wTop + 50);
-          }
-        });
-  }
-}
diff --git a/java/com/google/gwtexpui/globalkey/client/key.css b/java/com/google/gwtexpui/globalkey/client/key.css
deleted file mode 100644
index 755e686..0000000
--- a/java/com/google/gwtexpui/globalkey/client/key.css
+++ /dev/null
@@ -1,99 +0,0 @@
-/* Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@external .popupContent;
-
-.helpPopup {
-  background: #000000 none repeat scroll 0 50%;
-  color: #ffffff;
-  font-family: arial,sans-serif;
-  font-weight: bold;
-  overflow: hidden;
-  text-align: left;
-  text-shadow: 1px 1px 7px #000000;
-  width: 92%;
-  z-index: 1002;
-  opacity: 0.85;
-  border-radius: 10px;
- }
-
-@if user.agent safari {
-  .helpPopup {
-    \-webkit-border-radius: 10px;
-  }
-}
-@if user.agent gecko1_8 {
-  .helpPopup {
-    \-moz-border-radius: 10px;
-  }
-}
-
-.helpPopup .popupContent {
-  margin: 10px;
-}
-
-.helpPopup hr {
-  width: 100%;
-}
-
-.helpHeader {
-  width: 100%;
-}
-
-.helpHeader td {
-  white-space: nowrap;
-  color: #ffffff;
-}
-
-.helpHeader a,
-.helpHeader a:visited,
-.helpHeader a:hover {
-  color: #dddd00;
-}
-
-.helpHeaderGlue {
-  width: 100%;
-}
-
-.helpTable {
-  width: 90%;
-}
-.helpTable td {
-  vertical-align: top;
-  white-space: nowrap;
-}
-
-.helpTableGlue {
-  width: 25px;
-}
-
-.helpGroup {
-  color: #dddd00;
-  text-align: left;
-}
-
-.helpKeyStroke {
-  text-align: right;
-}
-
-.helpSeparator {
-  width: 0.5em;
-  text-align: center;
-  font-weight: bold;
-}
-
-.helpKey {
-  color: #dddd00;
-}
diff --git a/java/com/google/gwtexpui/progress/BUILD b/java/com/google/gwtexpui/progress/BUILD
deleted file mode 100644
index 74caa57..0000000
--- a/java/com/google/gwtexpui/progress/BUILD
+++ /dev/null
@@ -1,10 +0,0 @@
-load("//tools/bzl:gwt.bzl", "gwt_module")
-
-gwt_module(
-    name = "progress",
-    srcs = glob(["client/*.java"]),
-    gwt_xml = "Progress.gwt.xml",
-    resources = ["client/progress.css"],
-    visibility = ["//visibility:public"],
-    deps = ["//lib/gwt:user"],
-)
diff --git a/java/com/google/gwtexpui/progress/Progress.gwt.xml b/java/com/google/gwtexpui/progress/Progress.gwt.xml
deleted file mode 100644
index 0df8928..0000000
--- a/java/com/google/gwtexpui/progress/Progress.gwt.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<!--
- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<module>
-  <inherits name='com.google.gwt.resources.Resources'/>
-  <inherits name="com.google.gwt.user.User"/>
-</module>
diff --git a/java/com/google/gwtexpui/progress/client/ProgressBar.java b/java/com/google/gwtexpui/progress/client/ProgressBar.java
deleted file mode 100644
index f133e4d..0000000
--- a/java/com/google/gwtexpui/progress/client/ProgressBar.java
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.progress.client;
-
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Label;
-
-/**
- * A simple progress bar with a text label.
- *
- * <p>The bar is 200 pixels wide and 20 pixels high. To keep the implementation simple and
- * lightweight this dimensions are fixed and shouldn't be modified by style overrides in client code
- * or CSS.
- */
-public class ProgressBar extends Composite {
-  static {
-    ProgressResources.I.css().ensureInjected();
-  }
-
-  private final String callerText;
-  private final Label bar;
-  private final Label msg;
-  private int value;
-
-  /** Create a bar with no message text. */
-  public ProgressBar() {
-    this("");
-  }
-
-  /** Create a bar displaying the specified message. */
-  public ProgressBar(String text) {
-    if (text == null || text.length() == 0) {
-      callerText = "";
-    } else {
-      callerText = text + " ";
-    }
-
-    final FlowPanel body = new FlowPanel();
-    body.setStyleName(ProgressResources.I.css().container());
-
-    msg = new Label(callerText);
-    msg.setStyleName(ProgressResources.I.css().text());
-    body.add(msg);
-
-    bar = new Label("");
-    bar.setStyleName(ProgressResources.I.css().bar());
-    body.add(bar);
-
-    initWidget(body);
-  }
-
-  /** @return the current value of the progress meter. */
-  public int getValue() {
-    return value;
-  }
-
-  /** Update the bar's percent completion. */
-  public void setValue(int pComplete) {
-    assert 0 <= pComplete && pComplete <= 100;
-    value = pComplete;
-    bar.setWidth(2 * pComplete + "px");
-    msg.setText(callerText + pComplete + "%");
-  }
-}
diff --git a/java/com/google/gwtexpui/progress/client/ProgressCss.java b/java/com/google/gwtexpui/progress/client/ProgressCss.java
deleted file mode 100644
index ec27490..0000000
--- a/java/com/google/gwtexpui/progress/client/ProgressCss.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.progress.client;
-
-import com.google.gwt.resources.client.CssResource;
-
-public interface ProgressCss extends CssResource {
-  String container();
-
-  String text();
-
-  String bar();
-}
diff --git a/java/com/google/gwtexpui/progress/client/ProgressResources.java b/java/com/google/gwtexpui/progress/client/ProgressResources.java
deleted file mode 100644
index 6bcf2c4..0000000
--- a/java/com/google/gwtexpui/progress/client/ProgressResources.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.progress.client;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.resources.client.ClientBundle;
-
-public interface ProgressResources extends ClientBundle {
-  ProgressResources I = GWT.create(ProgressResources.class);
-
-  @Source("progress.css")
-  ProgressCss css();
-}
diff --git a/java/com/google/gwtexpui/progress/client/progress.css b/java/com/google/gwtexpui/progress/client/progress.css
deleted file mode 100644
index 683396e..0000000
--- a/java/com/google/gwtexpui/progress/client/progress.css
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-.container {
-  position: relative;
-  border: 1px solid #6B90DA;
-  height: 20px;
-  width: 200px;
-}
-
-.text {
-  position: absolute;
-  bottom: 0;
-  left: 0;
-  z-index: 2;
-  width: 200px;
-  padding-bottom: 3px;
-  text-align: center;
-  font-weight: bold;
-  font-style: italic;
-  font-size: smaller;
-}
-
-.bar {
-  background: #F0F7F9;
-  border-right: 1px solid #D0D7D9;
-  position: absolute;
-  top: 0;
-  left: 0;
-  height: 20px;
-}
diff --git a/java/com/google/gwtexpui/safehtml/BUILD b/java/com/google/gwtexpui/safehtml/BUILD
deleted file mode 100644
index af85c33..0000000
--- a/java/com/google/gwtexpui/safehtml/BUILD
+++ /dev/null
@@ -1,10 +0,0 @@
-load("//tools/bzl:gwt.bzl", "gwt_module")
-
-gwt_module(
-    name = "safehtml",
-    srcs = glob(["client/*.java"]),
-    gwt_xml = "SafeHtml.gwt.xml",
-    resources = ["client/safehtml.css"],
-    visibility = ["//visibility:public"],
-    deps = ["//lib/gwt:user"],
-)
diff --git a/java/com/google/gwtexpui/safehtml/SafeHtml.gwt.xml b/java/com/google/gwtexpui/safehtml/SafeHtml.gwt.xml
deleted file mode 100644
index 0df8928..0000000
--- a/java/com/google/gwtexpui/safehtml/SafeHtml.gwt.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<!--
- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<module>
-  <inherits name='com.google.gwt.resources.Resources'/>
-  <inherits name="com.google.gwt.user.User"/>
-</module>
diff --git a/java/com/google/gwtexpui/safehtml/client/AttMap.java b/java/com/google/gwtexpui/safehtml/client/AttMap.java
deleted file mode 100644
index c93a78b..0000000
--- a/java/com/google/gwtexpui/safehtml/client/AttMap.java
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-/** Lightweight map of names/values for element attribute construction. */
-class AttMap {
-  private static final Tag ANY = new AnyTag();
-  private static final HashMap<String, Tag> TAGS;
-
-  static {
-    final Tag src = new SrcTag();
-    TAGS = new HashMap<>();
-    TAGS.put("a", new AnchorTag());
-    TAGS.put("form", new FormTag());
-    TAGS.put("img", src);
-    TAGS.put("script", src);
-    TAGS.put("frame", src);
-  }
-
-  private final ArrayList<String> names = new ArrayList<>();
-  private final ArrayList<String> values = new ArrayList<>();
-
-  private Tag tag = ANY;
-  private int live;
-
-  void reset(String tagName) {
-    tag = TAGS.get(tagName.toLowerCase());
-    if (tag == null) {
-      tag = ANY;
-    }
-    live = 0;
-  }
-
-  void onto(Buffer raw, SafeHtmlBuilder esc) {
-    for (int i = 0; i < live; i++) {
-      final String v = values.get(i);
-      if (v.length() > 0) {
-        raw.append(" ");
-        raw.append(names.get(i));
-        raw.append("=\"");
-        esc.append(v);
-        raw.append("\"");
-      }
-    }
-  }
-
-  String get(String name) {
-    name = name.toLowerCase();
-
-    for (int i = 0; i < live; i++) {
-      if (name.equals(names.get(i))) {
-        return values.get(i);
-      }
-    }
-    return "";
-  }
-
-  void set(String name, String value) {
-    name = name.toLowerCase();
-    tag.assertSafe(name, value);
-
-    for (int i = 0; i < live; i++) {
-      if (name.equals(names.get(i))) {
-        values.set(i, value);
-        return;
-      }
-    }
-
-    final int i = live++;
-    if (names.size() < live) {
-      names.add(name);
-      values.add(value);
-    } else {
-      names.set(i, name);
-      values.set(i, value);
-    }
-  }
-
-  private static void assertNotJavascriptUrl(String value) {
-    if (value.startsWith("#")) {
-      // common in GWT, and safe, so bypass further checks
-
-    } else if (value.trim().toLowerCase().startsWith("javascript:")) {
-      // possibly unsafe, we could have random user code here
-      // we can't tell if its safe or not so we refuse to accept
-      //
-      throw new RuntimeException("javascript unsafe in href: " + value);
-    }
-  }
-
-  private interface Tag {
-    void assertSafe(String name, String value);
-  }
-
-  private static class AnyTag implements Tag {
-    @Override
-    public void assertSafe(String name, String value) {}
-  }
-
-  private static class AnchorTag implements Tag {
-    @Override
-    public void assertSafe(String name, String value) {
-      if ("href".equals(name)) {
-        assertNotJavascriptUrl(value);
-      }
-    }
-  }
-
-  private static class FormTag implements Tag {
-    @Override
-    public void assertSafe(String name, String value) {
-      if ("action".equals(name)) {
-        assertNotJavascriptUrl(value);
-      }
-    }
-  }
-
-  private static class SrcTag implements Tag {
-    @Override
-    public void assertSafe(String name, String value) {
-      if ("src".equals(name)) {
-        assertNotJavascriptUrl(value);
-      }
-    }
-  }
-}
diff --git a/java/com/google/gwtexpui/safehtml/client/Buffer.java b/java/com/google/gwtexpui/safehtml/client/Buffer.java
deleted file mode 100644
index 12389b4..0000000
--- a/java/com/google/gwtexpui/safehtml/client/Buffer.java
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-interface Buffer {
-  void append(boolean v);
-
-  void append(char v);
-
-  void append(int v);
-
-  void append(long v);
-
-  void append(float v);
-
-  void append(double v);
-
-  void append(String v);
-
-  @Override
-  String toString();
-}
diff --git a/java/com/google/gwtexpui/safehtml/client/BufferDirect.java b/java/com/google/gwtexpui/safehtml/client/BufferDirect.java
deleted file mode 100644
index c6e1d30..0000000
--- a/java/com/google/gwtexpui/safehtml/client/BufferDirect.java
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-final class BufferDirect implements Buffer {
-  private final StringBuilder strbuf = new StringBuilder();
-
-  boolean isEmpty() {
-    return strbuf.length() == 0;
-  }
-
-  @Override
-  public void append(boolean v) {
-    strbuf.append(v);
-  }
-
-  @Override
-  public void append(char v) {
-    strbuf.append(v);
-  }
-
-  @Override
-  public void append(int v) {
-    strbuf.append(v);
-  }
-
-  @Override
-  public void append(long v) {
-    strbuf.append(v);
-  }
-
-  @Override
-  public void append(float v) {
-    strbuf.append(v);
-  }
-
-  @Override
-  public void append(double v) {
-    strbuf.append(v);
-  }
-
-  @Override
-  public void append(String v) {
-    strbuf.append(v);
-  }
-
-  @Override
-  public String toString() {
-    return strbuf.toString();
-  }
-}
diff --git a/java/com/google/gwtexpui/safehtml/client/BufferSealElement.java b/java/com/google/gwtexpui/safehtml/client/BufferSealElement.java
deleted file mode 100644
index bdd9801..0000000
--- a/java/com/google/gwtexpui/safehtml/client/BufferSealElement.java
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-final class BufferSealElement implements Buffer {
-  private final SafeHtmlBuilder shb;
-
-  BufferSealElement(SafeHtmlBuilder safeHtmlBuilder) {
-    shb = safeHtmlBuilder;
-  }
-
-  @Override
-  public void append(boolean v) {
-    shb.sealElement().append(v);
-  }
-
-  @Override
-  public void append(char v) {
-    shb.sealElement().append(v);
-  }
-
-  @Override
-  public void append(double v) {
-    shb.sealElement().append(v);
-  }
-
-  @Override
-  public void append(float v) {
-    shb.sealElement().append(v);
-  }
-
-  @Override
-  public void append(int v) {
-    shb.sealElement().append(v);
-  }
-
-  @Override
-  public void append(long v) {
-    shb.sealElement().append(v);
-  }
-
-  @Override
-  public void append(String v) {
-    shb.sealElement().append(v);
-  }
-
-  @Override
-  public String toString() {
-    return shb.sealElement().toString();
-  }
-}
diff --git a/java/com/google/gwtexpui/safehtml/client/FindReplace.java b/java/com/google/gwtexpui/safehtml/client/FindReplace.java
deleted file mode 100644
index 4fb3246..0000000
--- a/java/com/google/gwtexpui/safehtml/client/FindReplace.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-import com.google.gwt.regexp.shared.RegExp;
-
-/** A Find/Replace pair used against the {@link SafeHtml} block of text. */
-public interface FindReplace {
-  /** @return regular expression to match substrings with; should be treated as immutable. */
-  RegExp pattern();
-
-  /**
-   * Find and replace a single instance of this pattern in an input.
-   *
-   * <p><b>WARNING:</b> No XSS sanitization is done on the return value of this method, e.g. this
-   * value may be passed directly to {@link SafeHtml#replaceAll(String, String)}. Implementations
-   * must sanitize output appropriately.
-   *
-   * @param input input string.
-   * @return result of regular expression replacement.
-   * @throws IllegalArgumentException if the input could not be safely sanitized.
-   */
-  String replace(String input);
-}
diff --git a/java/com/google/gwtexpui/safehtml/client/HighlightSuggestOracle.java b/java/com/google/gwtexpui/safehtml/client/HighlightSuggestOracle.java
deleted file mode 100644
index 758521f..0000000
--- a/java/com/google/gwtexpui/safehtml/client/HighlightSuggestOracle.java
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-import static java.util.Comparator.comparing;
-import static java.util.stream.Collectors.toList;
-
-import com.google.gwt.user.client.ui.SuggestOracle;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * A suggestion oracle that tries to highlight the matched text.
- *
- * <p>Suggestions supplied by the implementation of {@link #onRequestSuggestions(Request, Callback)}
- * are modified to wrap all occurrences of the {@link
- * com.google.gwt.user.client.ui.SuggestOracle.Request#getQuery()} substring in HTML {@code
- * &lt;strong&gt;} tags, so they can be emphasized to the user.
- */
-public abstract class HighlightSuggestOracle extends SuggestOracle {
-  private static String escape(String ds) {
-    return new SafeHtmlBuilder().append(ds).asString();
-  }
-
-  @Override
-  public final boolean isDisplayStringHTML() {
-    return true;
-  }
-
-  @Override
-  public final void requestSuggestions(Request request, Callback cb) {
-    onRequestSuggestions(
-        request,
-        new Callback() {
-          @Override
-          public void onSuggestionsReady(Request request, Response response) {
-            final String qpat = getQueryPattern(request.getQuery());
-            final boolean html = isHTML();
-            final ArrayList<Suggestion> r = new ArrayList<>();
-            for (Suggestion s : response.getSuggestions()) {
-              r.add(new BoldSuggestion(qpat, s, html));
-            }
-            cb.onSuggestionsReady(request, new Response(r));
-          }
-        });
-  }
-
-  protected String getQueryPattern(String query) {
-    return query;
-  }
-
-  /**
-   * @return true if {@link
-   *     com.google.gwt.user.client.ui.SuggestOracle.Suggestion#getDisplayString()} returns HTML;
-   *     false if the text must be escaped before evaluating in an HTML like context.
-   */
-  protected boolean isHTML() {
-    return false;
-  }
-
-  /** Compute the suggestions and return them for display. */
-  protected abstract void onRequestSuggestions(Request request, Callback done);
-
-  private static class BoldSuggestion implements Suggestion {
-    private final Suggestion suggestion;
-    private final String displayString;
-
-    BoldSuggestion(String qstr, Suggestion s, boolean html) {
-      suggestion = s;
-
-      String ds = s.getDisplayString();
-      if (!html) {
-        ds = escape(ds);
-      }
-
-      if (qstr != null && !qstr.isEmpty()) {
-        StringBuilder pattern = new StringBuilder();
-        for (String qterm : splitQuery(qstr)) {
-          qterm = escape(qterm);
-          // We now surround qstr by <strong>. But the chosen approach is not too
-          // smooth, if qstr is small (e.g.: "t") and this small qstr may occur in
-          // escapes (e.g.: "Tim &lt;email@example.org&gt;"). Those escapes will
-          // get <strong>-ed as well (e.g.: "&lt;" -> "&<strong>l</strong>t;"). But
-          // as repairing those mangled escapes is easier than not mangling them in
-          // the first place, we repair them afterwards.
-          if (pattern.length() > 0) {
-            pattern.append("|");
-          }
-          pattern.append(qterm);
-        }
-
-        ds = sgi(ds, "(" + pattern.toString() + ")", "<strong>$1</strong>");
-
-        // Repairing <strong>-ed escapes.
-        ds = sgi(ds, "(&[a-z]*)<strong>([a-z]*)</strong>([a-z]*;)", "$1$2$3");
-      }
-
-      displayString = ds;
-    }
-
-    /**
-     * Split the query by whitespace and filter out query terms which are substrings of other query
-     * terms.
-     */
-    private static List<String> splitQuery(String query) {
-      List<String> queryTerms =
-          Arrays.stream(query.split("\\s+")).sorted(comparing(String::length)).collect(toList());
-
-      List<String> result = new ArrayList<>();
-      for (String s : queryTerms) {
-        boolean add = true;
-        for (String queryTerm : result) {
-          if (queryTerm.toLowerCase().contains(s.toLowerCase())) {
-            add = false;
-            break;
-          }
-        }
-        if (add) {
-          result.add(s);
-        }
-      }
-      return result;
-    }
-
-    private static native String sgi(String inString, String pat, String newHtml)
-        /*-{ return inString.replace(RegExp(pat, 'gi'), newHtml); }-*/ ;
-
-    @Override
-    public String getDisplayString() {
-      return displayString;
-    }
-
-    @Override
-    public String getReplacementString() {
-      return suggestion.getReplacementString();
-    }
-  }
-}
diff --git a/java/com/google/gwtexpui/safehtml/client/LinkFindReplace.java b/java/com/google/gwtexpui/safehtml/client/LinkFindReplace.java
deleted file mode 100644
index cf0e51d..0000000
--- a/java/com/google/gwtexpui/safehtml/client/LinkFindReplace.java
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-import com.google.gwt.regexp.shared.RegExp;
-
-/**
- * A Find/Replace pair whose replacement string is a link.
- *
- * <p>It is safe to pass arbitrary user-provided links to this class. Links are sanitized as
- * follows:
- *
- * <ul>
- *   <li>Only http(s) and mailto links are supported; any other scheme results in an {@link
- *       IllegalArgumentException} from {@link #replace(String)}.
- *   <li>Special characters in the link after regex replacement are escaped with {@link
- *       SafeHtmlBuilder}.
- * </ul>
- */
-public class LinkFindReplace implements FindReplace {
-  public static boolean hasValidScheme(String link) {
-    int colon = link.indexOf(':');
-    if (colon < 0) {
-      return true;
-    }
-    String scheme = link.substring(0, colon);
-    return "http".equalsIgnoreCase(scheme)
-        || "https".equalsIgnoreCase(scheme)
-        || "mailto".equalsIgnoreCase(scheme);
-  }
-
-  private RegExp pat;
-  private String link;
-
-  protected LinkFindReplace() {}
-
-  /**
-   * @param find regular expression pattern to match substrings with.
-   * @param link replacement link href. Capture groups within {@code find} can be referenced with
-   *     {@code $<i>n</i>}.
-   */
-  public LinkFindReplace(String find, String link) {
-    this.pat = RegExp.compile(find);
-    this.link = link;
-  }
-
-  @Override
-  public RegExp pattern() {
-    return pat;
-  }
-
-  @Override
-  public String replace(String input) {
-    String href = pat.replace(input, link);
-    if (!hasValidScheme(href)) {
-      throw new IllegalArgumentException("Invalid scheme (" + toString() + "): " + href);
-    }
-    return new SafeHtmlBuilder()
-        .openAnchor()
-        .setAttribute("href", href)
-        .append(SafeHtml.asis(input))
-        .closeAnchor()
-        .asString();
-  }
-
-  @Override
-  public String toString() {
-    return "find = " + pat.getSource() + ", link = " + link;
-  }
-}
diff --git a/java/com/google/gwtexpui/safehtml/client/RawFindReplace.java b/java/com/google/gwtexpui/safehtml/client/RawFindReplace.java
deleted file mode 100644
index dc39af6..0000000
--- a/java/com/google/gwtexpui/safehtml/client/RawFindReplace.java
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-import com.google.gwt.regexp.shared.RegExp;
-
-/**
- * A Find/Replace pair whose replacement string is arbitrary HTML.
- *
- * <p><b>WARNING:</b> This class is not safe used with user-provided patterns.
- */
-public class RawFindReplace implements FindReplace {
-  private RegExp pat;
-  private String replace;
-
-  protected RawFindReplace() {}
-
-  /**
-   * @param find regular expression pattern to match substrings with.
-   * @param replace replacement expression. Capture groups within {@code find} can be referenced
-   *     with {@code $<i>n</i>}.
-   */
-  public RawFindReplace(String find, String replace) {
-    this.pat = RegExp.compile(find);
-    this.replace = replace;
-  }
-
-  @Override
-  public RegExp pattern() {
-    return pat;
-  }
-
-  @Override
-  public String replace(String input) {
-    return pat.replace(input, replace);
-  }
-
-  @Override
-  public String toString() {
-    return "find = " + pat.getSource() + ", replace = " + replace;
-  }
-}
diff --git a/java/com/google/gwtexpui/safehtml/client/SafeHtml.java b/java/com/google/gwtexpui/safehtml/client/SafeHtml.java
deleted file mode 100644
index 2a1ddc0..0000000
--- a/java/com/google/gwtexpui/safehtml/client/SafeHtml.java
+++ /dev/null
@@ -1,334 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.regexp.shared.MatchResult;
-import com.google.gwt.regexp.shared.RegExp;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.HTMLTable;
-import com.google.gwt.user.client.ui.HasHTML;
-import com.google.gwt.user.client.ui.InlineHTML;
-import com.google.gwt.user.client.ui.Widget;
-import java.util.Iterator;
-import java.util.List;
-
-/** Immutable string safely placed as HTML without further escaping. */
-@SuppressWarnings("serial")
-public abstract class SafeHtml implements com.google.gwt.safehtml.shared.SafeHtml {
-  public static final SafeHtmlResources RESOURCES;
-
-  static {
-    if (GWT.isClient()) {
-      RESOURCES = GWT.create(SafeHtmlResources.class);
-      RESOURCES.css().ensureInjected();
-
-    } else {
-      RESOURCES =
-          new SafeHtmlResources() {
-            @Override
-            public SafeHtmlCss css() {
-              return new SafeHtmlCss() {
-                @Override
-                public String wikiList() {
-                  return "wikiList";
-                }
-
-                @Override
-                public String wikiPreFormat() {
-                  return "wikiPreFormat";
-                }
-
-                @Override
-                public String wikiQuote() {
-                  return "wikiQuote";
-                }
-
-                @Override
-                public boolean ensureInjected() {
-                  return false;
-                }
-
-                @Override
-                public String getName() {
-                  return null;
-                }
-
-                @Override
-                public String getText() {
-                  return null;
-                }
-              };
-            }
-          };
-    }
-  }
-
-  /** @return the existing HTML property of a widget. */
-  public static SafeHtml get(HasHTML t) {
-    return new SafeHtmlString(t.getHTML());
-  }
-
-  /** @return the existing HTML text, wrapped in a safe buffer. */
-  public static SafeHtml asis(String htmlText) {
-    return new SafeHtmlString(htmlText);
-  }
-
-  /** Set the HTML property of a widget. */
-  public static <T extends HasHTML> T set(T e, SafeHtml str) {
-    e.setHTML(str.asString());
-    return e;
-  }
-
-  /** @return the existing inner HTML of any element. */
-  public static SafeHtml get(Element e) {
-    return new SafeHtmlString(e.getInnerHTML());
-  }
-
-  /** Set the inner HTML of any element. */
-  public static Element setInnerHTML(Element e, SafeHtml str) {
-    e.setInnerHTML(str.asString());
-    return e;
-  }
-
-  /** @return the existing inner HTML of a table cell. */
-  public static SafeHtml get(HTMLTable t, int row, int col) {
-    return new SafeHtmlString(t.getHTML(row, col));
-  }
-
-  /** Set the inner HTML of a table cell. */
-  public static <T extends HTMLTable> T set(final T t, int row, int col, SafeHtml str) {
-    t.setHTML(row, col, str.asString());
-    return t;
-  }
-
-  /** Parse an HTML block and return the first (typically root) element. */
-  public static Element parse(SafeHtml html) {
-    Element e = DOM.createDiv();
-    setInnerHTML(e, html);
-    return DOM.getFirstChild(e);
-  }
-
-  /** Convert bare http:// and https:// URLs into &lt;a href&gt; tags. */
-  public SafeHtml linkify() {
-    final String part = "(?:[a-zA-Z0-9$_+!*'%;:@=?#/~-]|&(?!lt;|gt;)|[.,](?!(?:\\s|$)))";
-    return replaceAll(
-        "(https?://" + part + "{2,}(?:[(]" + part + "*[)])*" + part + "*)",
-        "<a href=\"$1\" target=\"_blank\" rel=\"nofollow\">$1</a>");
-  }
-
-  /**
-   * Apply {@link #linkify()}, and "\n\n" to &lt;p&gt;.
-   *
-   * <p>Lines that start with whitespace are assumed to be preformatted, and are formatted by the
-   * {@link SafeHtmlCss#wikiPreFormat()} CSS class.
-   */
-  public SafeHtml wikify() {
-    final SafeHtmlBuilder r = new SafeHtmlBuilder();
-    for (String p : linkify().asString().split("\n\n")) {
-      if (isQuote(p)) {
-        wikifyQuote(r, p);
-
-      } else if (isPreFormat(p)) {
-        r.openElement("p");
-        for (String line : p.split("\n")) {
-          r.openSpan();
-          r.setStyleName(RESOURCES.css().wikiPreFormat());
-          r.append(asis(line));
-          r.closeSpan();
-          r.br();
-        }
-        r.closeElement("p");
-
-      } else if (isList(p)) {
-        wikifyList(r, p);
-
-      } else {
-        r.openElement("p");
-        r.append(asis(p));
-        r.closeElement("p");
-      }
-    }
-    return r.toSafeHtml();
-  }
-
-  private void wikifyList(SafeHtmlBuilder r, String p) {
-    boolean in_ul = false;
-    boolean in_p = false;
-    for (String line : p.split("\n")) {
-      if (line.startsWith("-") || line.startsWith("*")) {
-        if (!in_ul) {
-          if (in_p) {
-            in_p = false;
-            r.closeElement("p");
-          }
-
-          in_ul = true;
-          r.openElement("ul");
-          r.setStyleName(RESOURCES.css().wikiList());
-        }
-        line = line.substring(1).trim();
-
-      } else if (!in_ul) {
-        if (!in_p) {
-          in_p = true;
-          r.openElement("p");
-        } else {
-          r.append(' ');
-        }
-        r.append(asis(line));
-        continue;
-      }
-
-      r.openElement("li");
-      r.append(asis(line));
-      r.closeElement("li");
-    }
-
-    if (in_ul) {
-      r.closeElement("ul");
-    } else if (in_p) {
-      r.closeElement("p");
-    }
-  }
-
-  private void wikifyQuote(SafeHtmlBuilder r, String p) {
-    r.openElement("blockquote");
-    r.setStyleName(RESOURCES.css().wikiQuote());
-    if (p.startsWith("&gt; ")) {
-      p = p.substring(5);
-    } else if (p.startsWith(" &gt; ")) {
-      p = p.substring(6);
-    }
-    p = p.replaceAll("\\n ?&gt; ", "\n");
-    for (String e : p.split("\n\n")) {
-      if (isQuote(e)) {
-        SafeHtmlBuilder b = new SafeHtmlBuilder();
-        wikifyQuote(b, e);
-        r.append(b);
-      } else {
-        r.append(asis(e));
-      }
-    }
-    r.closeElement("blockquote");
-  }
-
-  private static boolean isQuote(String p) {
-    return p.startsWith("&gt; ") || p.startsWith(" &gt; ");
-  }
-
-  private static boolean isPreFormat(String p) {
-    return p.contains("\n ") || p.contains("\n\t") || p.startsWith(" ") || p.startsWith("\t");
-  }
-
-  private static boolean isList(String p) {
-    return p.contains("\n- ") || p.contains("\n* ") || p.startsWith("- ") || p.startsWith("* ");
-  }
-
-  /**
-   * Replace first occurrence of {@code regex} with {@code repl} .
-   *
-   * <p><b>WARNING:</b> This replacement is being performed against an otherwise safe HTML string.
-   * The caller must ensure that the replacement does not introduce cross-site scripting attack
-   * entry points.
-   *
-   * @param regex regular expression pattern to match the substring with.
-   * @param repl replacement expression. Capture groups within {@code regex} can be referenced with
-   *     {@code $<i>n</i>}.
-   * @return a new string, after the replacement has been made.
-   */
-  public SafeHtml replaceFirst(String regex, String repl) {
-    return new SafeHtmlString(asString().replaceFirst(regex, repl));
-  }
-
-  /**
-   * Replace each occurrence of {@code regex} with {@code repl} .
-   *
-   * <p><b>WARNING:</b> This replacement is being performed against an otherwise safe HTML string.
-   * The caller must ensure that the replacement does not introduce cross-site scripting attack
-   * entry points.
-   *
-   * @param regex regular expression pattern to match substrings with.
-   * @param repl replacement expression. Capture groups within {@code regex} can be referenced with
-   *     {@code $<i>n</i>}.
-   * @return a new string, after the replacements have been made.
-   */
-  public SafeHtml replaceAll(String regex, String repl) {
-    return new SafeHtmlString(asString().replaceAll(regex, repl));
-  }
-
-  /**
-   * Replace all find/replace pairs in the list in a single pass.
-   *
-   * @param findReplaceList find/replace pairs to use.
-   * @return a new string, after the replacements have been made.
-   */
-  public <T> SafeHtml replaceAll(List<? extends FindReplace> findReplaceList) {
-    if (findReplaceList == null || findReplaceList.isEmpty()) {
-      return this;
-    }
-
-    StringBuilder pat = new StringBuilder();
-    Iterator<? extends FindReplace> it = findReplaceList.iterator();
-    while (it.hasNext()) {
-      FindReplace fr = it.next();
-      pat.append(fr.pattern().getSource());
-      if (it.hasNext()) {
-        pat.append('|');
-      }
-    }
-
-    StringBuilder result = new StringBuilder();
-    RegExp re = RegExp.compile(pat.toString(), "g");
-    String orig = asString();
-    int index = 0;
-    MatchResult mat;
-    while ((mat = re.exec(orig)) != null) {
-      String g = mat.getGroup(0);
-      // Re-run each candidate to find which one matched.
-      for (FindReplace fr : findReplaceList) {
-        if (fr.pattern().test(g)) {
-          try {
-            String repl = fr.replace(g);
-            result.append(orig.substring(index, mat.getIndex()));
-            result.append(repl);
-          } catch (IllegalArgumentException e) {
-            continue;
-          }
-          index = mat.getIndex() + g.length();
-          break;
-        }
-      }
-    }
-    result.append(orig.substring(index, orig.length()));
-    return asis(result.toString());
-  }
-
-  /** @return a GWT block display widget displaying this HTML. */
-  public Widget toBlockWidget() {
-    return new HTML(asString());
-  }
-
-  /** @return a GWT inline display widget displaying this HTML. */
-  public Widget toInlineWidget() {
-    return new InlineHTML(asString());
-  }
-
-  /** @return a clean HTML string safe for inclusion in any context. */
-  @Override
-  public abstract String asString();
-}
diff --git a/java/com/google/gwtexpui/safehtml/client/SafeHtmlBuilder.java b/java/com/google/gwtexpui/safehtml/client/SafeHtmlBuilder.java
deleted file mode 100644
index a926906..0000000
--- a/java/com/google/gwtexpui/safehtml/client/SafeHtmlBuilder.java
+++ /dev/null
@@ -1,424 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-import com.google.gwt.core.client.GWT;
-
-/** Safely constructs a {@link SafeHtml}, escaping user provided content. */
-@SuppressWarnings("serial")
-public class SafeHtmlBuilder extends SafeHtml {
-  private static final Impl impl;
-
-  static {
-    if (GWT.isClient()) {
-      impl = new ClientImpl();
-    } else {
-      impl = new ServerImpl();
-    }
-  }
-
-  private final BufferDirect dBuf;
-  private Buffer cb;
-
-  private BufferSealElement sBuf;
-  private AttMap att;
-
-  public SafeHtmlBuilder() {
-    cb = dBuf = new BufferDirect();
-  }
-
-  /** @return true if this builder has not had an append occur yet. */
-  public boolean isEmpty() {
-    return dBuf.isEmpty();
-  }
-
-  /** @return true if this builder has content appended into it. */
-  public boolean hasContent() {
-    return !isEmpty();
-  }
-
-  public SafeHtmlBuilder append(boolean in) {
-    cb.append(in);
-    return this;
-  }
-
-  public SafeHtmlBuilder append(char in) {
-    switch (in) {
-      case '&':
-        cb.append("&amp;");
-        break;
-
-      case '>':
-        cb.append("&gt;");
-        break;
-
-      case '<':
-        cb.append("&lt;");
-        break;
-
-      case '"':
-        cb.append("&quot;");
-        break;
-
-      case '\'':
-        cb.append("&#39;");
-        break;
-
-      default:
-        cb.append(in);
-        break;
-    }
-    return this;
-  }
-
-  public SafeHtmlBuilder append(int in) {
-    cb.append(in);
-    return this;
-  }
-
-  public SafeHtmlBuilder append(long in) {
-    cb.append(in);
-    return this;
-  }
-
-  public SafeHtmlBuilder append(float in) {
-    cb.append(in);
-    return this;
-  }
-
-  public SafeHtmlBuilder append(double in) {
-    cb.append(in);
-    return this;
-  }
-
-  /** Append already safe HTML as-is, avoiding double escaping. */
-  public SafeHtmlBuilder append(com.google.gwt.safehtml.shared.SafeHtml in) {
-    if (in != null) {
-      cb.append(in.asString());
-    }
-    return this;
-  }
-
-  /** Append already safe HTML as-is, avoiding double escaping. */
-  public SafeHtmlBuilder append(SafeHtml in) {
-    if (in != null) {
-      cb.append(in.asString());
-    }
-    return this;
-  }
-
-  /** Append the string, escaping unsafe characters. */
-  public SafeHtmlBuilder append(String in) {
-    if (in != null) {
-      impl.escapeStr(this, in);
-    }
-    return this;
-  }
-
-  /** Append the string, escaping unsafe characters. */
-  public SafeHtmlBuilder append(StringBuilder in) {
-    if (in != null) {
-      append(in.toString());
-    }
-    return this;
-  }
-
-  /** Append the string, escaping unsafe characters. */
-  public SafeHtmlBuilder append(StringBuffer in) {
-    if (in != null) {
-      append(in.toString());
-    }
-    return this;
-  }
-
-  /** Append the result of toString(), escaping unsafe characters. */
-  public SafeHtmlBuilder append(Object in) {
-    if (in != null) {
-      append(in.toString());
-    }
-    return this;
-  }
-
-  /** Append the string, escaping unsafe characters. */
-  public SafeHtmlBuilder append(CharSequence in) {
-    if (in != null) {
-      escapeCS(this, in);
-    }
-    return this;
-  }
-
-  /**
-   * Open an element, appending "{@code <tagName>}" to the buffer.
-   *
-   * <p>After the element is open the attributes may be manipulated until the next {@code append},
-   * {@code openElement}, {@code closeSelf} or {@code closeElement} call.
-   *
-   * @param tagName name of the HTML element to open.
-   */
-  public SafeHtmlBuilder openElement(String tagName) {
-    assert isElementName(tagName);
-    cb.append("<");
-    cb.append(tagName);
-    if (sBuf == null) {
-      att = new AttMap();
-      sBuf = new BufferSealElement(this);
-    }
-    att.reset(tagName);
-    cb = sBuf;
-    return this;
-  }
-
-  /**
-   * Get an attribute of the last opened element.
-   *
-   * @param name name of the attribute to read.
-   * @return the attribute value, as a string. The empty string if the attribute has not been
-   *     assigned a value. The returned string is the raw (unescaped) value.
-   */
-  public String getAttribute(String name) {
-    assert isAttributeName(name);
-    assert cb == sBuf;
-    return att.get(name);
-  }
-
-  /**
-   * Set an attribute of the last opened element.
-   *
-   * @param name name of the attribute to set.
-   * @param value value to assign; any existing value is replaced. The value is escaped (if
-   *     necessary) during the assignment.
-   */
-  public SafeHtmlBuilder setAttribute(String name, String value) {
-    assert isAttributeName(name);
-    assert cb == sBuf;
-    att.set(name, value != null ? value : "");
-    return this;
-  }
-
-  /**
-   * Set an attribute of the last opened element.
-   *
-   * @param name name of the attribute to set.
-   * @param value value to assign, any existing value is replaced.
-   */
-  public SafeHtmlBuilder setAttribute(String name, int value) {
-    return setAttribute(name, String.valueOf(value));
-  }
-
-  /**
-   * Append a new value into a whitespace delimited attribute.
-   *
-   * <p>If the attribute is not yet assigned, this method sets the attribute. If the attribute is
-   * already assigned, the new value is appended onto the end, after appending a single space to
-   * delimit the values.
-   *
-   * @param name name of the attribute to append onto.
-   * @param value additional value to append.
-   */
-  public SafeHtmlBuilder appendAttribute(String name, String value) {
-    if (value != null && value.length() > 0) {
-      final String e = getAttribute(name);
-      return setAttribute(name, e.length() > 0 ? e + " " + value : value);
-    }
-    return this;
-  }
-
-  /** Set the height attribute of the current element. */
-  public SafeHtmlBuilder setHeight(int height) {
-    return setAttribute("height", height);
-  }
-
-  /** Set the width attribute of the current element. */
-  public SafeHtmlBuilder setWidth(int width) {
-    return setAttribute("width", width);
-  }
-
-  /** Set the CSS class name for this element. */
-  public SafeHtmlBuilder setStyleName(String style) {
-    assert isCssName(style);
-    return setAttribute("class", style);
-  }
-
-  /**
-   * Add an additional CSS class name to this element.
-   *
-   * <p>If no CSS class name has been specified yet, this method initializes it to the single name.
-   */
-  public SafeHtmlBuilder addStyleName(String style) {
-    assert isCssName(style);
-    return appendAttribute("class", style);
-  }
-
-  private void sealElement0() {
-    assert cb == sBuf;
-    cb = dBuf;
-    att.onto(cb, this);
-  }
-
-  Buffer sealElement() {
-    sealElement0();
-    cb.append(">");
-    return cb;
-  }
-
-  /** Close the current element with a self closing suffix ("/ &gt;"). */
-  public SafeHtmlBuilder closeSelf() {
-    sealElement0();
-    cb.append(" />");
-    return this;
-  }
-
-  /** Append a closing tag for the named element. */
-  public SafeHtmlBuilder closeElement(String name) {
-    assert isElementName(name);
-    cb.append("</");
-    cb.append(name);
-    cb.append(">");
-    return this;
-  }
-
-  /** Append "&amp;nbsp;" - a non-breaking space, useful in empty table cells. */
-  public SafeHtmlBuilder nbsp() {
-    cb.append("&nbsp;");
-    return this;
-  }
-
-  /** Append "&lt;br /&gt;" - a line break with no attributes */
-  public SafeHtmlBuilder br() {
-    cb.append("<br />");
-    return this;
-  }
-
-  /** Append "&lt;tr&gt;"; attributes may be set if needed */
-  public SafeHtmlBuilder openTr() {
-    return openElement("tr");
-  }
-
-  /** Append "&lt;/tr&gt;" */
-  public SafeHtmlBuilder closeTr() {
-    return closeElement("tr");
-  }
-
-  /** Append "&lt;td&gt;"; attributes may be set if needed */
-  public SafeHtmlBuilder openTd() {
-    return openElement("td");
-  }
-
-  /** Append "&lt;/td&gt;" */
-  public SafeHtmlBuilder closeTd() {
-    return closeElement("td");
-  }
-
-  /** Append "&lt;th&gt;"; attributes may be set if needed */
-  public SafeHtmlBuilder openTh() {
-    return openElement("th");
-  }
-
-  /** Append "&lt;/th&gt;" */
-  public SafeHtmlBuilder closeTh() {
-    return closeElement("th");
-  }
-
-  /** Append "&lt;div&gt;"; attributes may be set if needed */
-  public SafeHtmlBuilder openDiv() {
-    return openElement("div");
-  }
-
-  /** Append "&lt;/div&gt;" */
-  public SafeHtmlBuilder closeDiv() {
-    return closeElement("div");
-  }
-
-  /** Append "&lt;span&gt;"; attributes may be set if needed */
-  public SafeHtmlBuilder openSpan() {
-    return openElement("span");
-  }
-
-  /** Append "&lt;/span&gt;" */
-  public SafeHtmlBuilder closeSpan() {
-    return closeElement("span");
-  }
-
-  /** Append "&lt;a&gt;"; attributes may be set if needed */
-  public SafeHtmlBuilder openAnchor() {
-    return openElement("a");
-  }
-
-  /** Append "&lt;/a&gt;" */
-  public SafeHtmlBuilder closeAnchor() {
-    return closeElement("a");
-  }
-
-  /** Append "&lt;param name=... value=... /&gt;". */
-  public SafeHtmlBuilder paramElement(String name, String value) {
-    openElement("param");
-    setAttribute("name", name);
-    setAttribute("value", value);
-    return closeSelf();
-  }
-
-  /** @return an immutable {@link SafeHtml} representation of the buffer. */
-  public SafeHtml toSafeHtml() {
-    return new SafeHtmlString(asString());
-  }
-
-  @Override
-  public String asString() {
-    return cb.toString();
-  }
-
-  private static void escapeCS(SafeHtmlBuilder b, CharSequence in) {
-    for (int i = 0; i < in.length(); i++) {
-      b.append(in.charAt(i));
-    }
-  }
-
-  private static boolean isElementName(String name) {
-    return name.matches("^[a-zA-Z][a-zA-Z0-9_-]*$");
-  }
-
-  private static boolean isAttributeName(String name) {
-    return isElementName(name);
-  }
-
-  private static boolean isCssName(String name) {
-    return isElementName(name);
-  }
-
-  private abstract static class Impl {
-    abstract void escapeStr(SafeHtmlBuilder b, String in);
-  }
-
-  private static class ServerImpl extends Impl {
-    @Override
-    void escapeStr(SafeHtmlBuilder b, String in) {
-      SafeHtmlBuilder.escapeCS(b, in);
-    }
-  }
-
-  private static class ClientImpl extends Impl {
-    @Override
-    void escapeStr(SafeHtmlBuilder b, String in) {
-      b.cb.append(escape(in));
-    }
-
-    private static native String escape(String src) /*-{ return src.replace(/&/g,'&amp;')
-                   .replace(/>/g,'&gt;')
-                   .replace(/</g,'&lt;')
-                   .replace(/"/g,'&quot;')
-                   .replace(/'/g,'&#39;');
-     }-*/;
-  }
-}
diff --git a/java/com/google/gwtexpui/safehtml/client/SafeHtmlCss.java b/java/com/google/gwtexpui/safehtml/client/SafeHtmlCss.java
deleted file mode 100644
index f4b1c77..0000000
--- a/java/com/google/gwtexpui/safehtml/client/SafeHtmlCss.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-import com.google.gwt.resources.client.CssResource;
-
-public interface SafeHtmlCss extends CssResource {
-  String wikiList();
-
-  String wikiPreFormat();
-
-  String wikiQuote();
-}
diff --git a/java/com/google/gwtexpui/safehtml/client/SafeHtmlResources.java b/java/com/google/gwtexpui/safehtml/client/SafeHtmlResources.java
deleted file mode 100644
index e3f5724..0000000
--- a/java/com/google/gwtexpui/safehtml/client/SafeHtmlResources.java
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-import com.google.gwt.resources.client.ClientBundle;
-
-public interface SafeHtmlResources extends ClientBundle {
-  @Source("safehtml.css")
-  SafeHtmlCss css();
-}
diff --git a/java/com/google/gwtexpui/safehtml/client/SafeHtmlString.java b/java/com/google/gwtexpui/safehtml/client/SafeHtmlString.java
deleted file mode 100644
index 889509a..0000000
--- a/java/com/google/gwtexpui/safehtml/client/SafeHtmlString.java
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-@SuppressWarnings("serial")
-class SafeHtmlString extends SafeHtml {
-  private final String html;
-
-  SafeHtmlString(String h) {
-    html = h;
-  }
-
-  @Override
-  public String asString() {
-    return html;
-  }
-}
diff --git a/java/com/google/gwtexpui/safehtml/client/safehtml.css b/java/com/google/gwtexpui/safehtml/client/safehtml.css
deleted file mode 100644
index 163c548..0000000
--- a/java/com/google/gwtexpui/safehtml/client/safehtml.css
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-.wikiList {
-}
-
-.wikiPreFormat {
-  white-space: pre;
-  font-family: 'Lucida Console', 'Lucida Sans Typewriter', Monaco, monospace;
-  font-size: small;
-}
-
-.wikiQuote {
-  margin-left: 0;
-  border-left: 1px solid #888;
-  padding-left: 5px;
-}
diff --git a/java/com/google/gwtexpui/user/BUILD b/java/com/google/gwtexpui/user/BUILD
deleted file mode 100644
index 813f433..0000000
--- a/java/com/google/gwtexpui/user/BUILD
+++ /dev/null
@@ -1,10 +0,0 @@
-load("//tools/bzl:gwt.bzl", "gwt_module")
-
-gwt_module(
-    name = "agent",
-    srcs = glob(["client/*.java"]),
-    gwt_xml = "User.gwt.xml",
-    resources = ["client/tooltip.css"],
-    visibility = ["//visibility:public"],
-    deps = ["//lib/gwt:user"],
-)
diff --git a/java/com/google/gwtexpui/user/User.gwt.xml b/java/com/google/gwtexpui/user/User.gwt.xml
deleted file mode 100644
index f4f8d51..0000000
--- a/java/com/google/gwtexpui/user/User.gwt.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<!--
- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<module>
-  <inherits name="com.google.gwt.user.User"/>
-</module>
diff --git a/java/com/google/gwtexpui/user/client/AutoCenterDialogBox.java b/java/com/google/gwtexpui/user/client/AutoCenterDialogBox.java
deleted file mode 100644
index fdaf861..0000000
--- a/java/com/google/gwtexpui/user/client/AutoCenterDialogBox.java
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (C) 2008 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.user.client;
-
-import com.google.gwt.event.logical.shared.ResizeEvent;
-import com.google.gwt.event.logical.shared.ResizeHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.DialogBox;
-
-/** A DialogBox that automatically re-centers itself if the window changes */
-public class AutoCenterDialogBox extends DialogBox {
-  private HandlerRegistration recenter;
-
-  public AutoCenterDialogBox() {
-    this(false);
-  }
-
-  public AutoCenterDialogBox(boolean autoHide) {
-    this(autoHide, true);
-  }
-
-  public AutoCenterDialogBox(boolean autoHide, boolean modal) {
-    super(autoHide, modal);
-  }
-
-  @Override
-  public void show() {
-    if (recenter == null) {
-      recenter =
-          Window.addResizeHandler(
-              new ResizeHandler() {
-                @Override
-                public void onResize(ResizeEvent event) {
-                  final int w = event.getWidth();
-                  final int h = event.getHeight();
-                  AutoCenterDialogBox.this.onResize(w, h);
-                }
-              });
-    }
-    super.show();
-  }
-
-  @Override
-  protected void onUnload() {
-    if (recenter != null) {
-      recenter.removeHandler();
-      recenter = null;
-    }
-    super.onUnload();
-  }
-
-  /**
-   * Invoked when the outer browser window resizes.
-   *
-   * <p>Subclasses may override (but should ensure they still call super.onResize) to implement
-   * custom logic when a window resize occurs.
-   *
-   * @param width new browser window width
-   * @param height new browser window height
-   */
-  protected void onResize(int width, int height) {
-    if (isAttached()) {
-      center();
-    }
-  }
-}
diff --git a/java/com/google/gwtexpui/user/client/Tooltip.java b/java/com/google/gwtexpui/user/client/Tooltip.java
deleted file mode 100644
index b5ce046..0000000
--- a/java/com/google/gwtexpui/user/client/Tooltip.java
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.user.client;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.resources.client.ClientBundle;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.user.client.ui.UIObject;
-
-/** Displays custom tooltip message below an element. */
-public class Tooltip {
-  interface Resources extends ClientBundle {
-    Resources I = GWT.create(Resources.class);
-
-    @Source("tooltip.css")
-    Css css();
-  }
-
-  interface Css extends CssResource {
-    String tooltip();
-  }
-
-  static {
-    Resources.I.css().ensureInjected();
-  }
-
-  /**
-   * Add required supporting style to enable custom tooltip rendering.
-   *
-   * @param o widget whose element should display a tooltip on hover.
-   */
-  public static void addStyle(UIObject o) {
-    addStyle(o.getElement());
-  }
-
-  /**
-   * Add required supporting style to enable custom tooltip rendering.
-   *
-   * @param e element that should display a tooltip on hover.
-   */
-  public static void addStyle(Element e) {
-    e.addClassName(Resources.I.css().tooltip());
-  }
-
-  /**
-   * Set the text displayed on hover.
-   *
-   * @param o widget whose hover text is being set.
-   * @param text message to display on hover.
-   */
-  public static void setLabel(UIObject o, String text) {
-    setLabel(o.getElement(), text);
-  }
-
-  /**
-   * Set the text displayed on hover.
-   *
-   * @param e element whose hover text is being set.
-   * @param text message to display on hover.
-   */
-  public static void setLabel(Element e, String text) {
-    e.setAttribute("aria-label", text != null ? text : "");
-  }
-
-  private Tooltip() {}
-}
diff --git a/java/com/google/gwtexpui/user/client/UserAgent.java b/java/com/google/gwtexpui/user/client/UserAgent.java
deleted file mode 100644
index 1660a62..0000000
--- a/java/com/google/gwtexpui/user/client/UserAgent.java
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.user.client;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.Window;
-
-/**
- * User agent feature tests we don't create permutations for.
- *
- * <p>Some features aren't worth creating full permutations in GWT for, as each new boolean
- * permutation (only two settings) doubles the compile time required. If the setting only affects a
- * couple of lines of JavaScript code, the slightly larger cache files for user agents that lack the
- * functionality requested is trivial compared to the time developers lose building their
- * application.
- */
-public class UserAgent {
-  private static boolean jsClip = guessJavaScriptClipboard();
-
-  public static boolean hasJavaScriptClipboard() {
-    return jsClip;
-  }
-
-  public static void disableJavaScriptClipboard() {
-    jsClip = false;
-  }
-
-  private static native boolean nativeHasCopy()
-      /*-{ return $doc['queryCommandSupported'] && $doc.queryCommandSupported('copy') }-*/ ;
-
-  private static boolean guessJavaScriptClipboard() {
-    String ua = Window.Navigator.getUserAgent();
-    int chrome = major(ua, "Chrome/");
-    if (chrome > 0) {
-      return 42 <= chrome;
-    }
-
-    int ff = major(ua, "Firefox/");
-    if (ff > 0) {
-      return 41 <= ff;
-    }
-
-    int opera = major(ua, "OPR/");
-    if (opera > 0) {
-      return 29 <= opera;
-    }
-
-    int msie = major(ua, "MSIE ");
-    if (msie > 0) {
-      return 9 <= msie;
-    }
-
-    if (nativeHasCopy()) {
-      // Firefox 39.0 lies and says it supports copy, then fails.
-      // So we try this after the browser specific test above.
-      return true;
-    }
-
-    // Safari is not planning to support document.execCommand('copy').
-    // Assume the browser does not have the feature.
-    return false;
-  }
-
-  private static int major(String ua, String product) {
-    int entry = ua.indexOf(product);
-    if (entry >= 0) {
-      String s = ua.substring(entry + product.length());
-      String p = s.split("[ /;,.)]", 2)[0];
-      try {
-        return Integer.parseInt(p);
-      } catch (NumberFormatException nan) {
-        // Ignored
-      }
-    }
-    return -1;
-  }
-
-  public static class Flash {
-    private static boolean checked;
-    private static boolean installed;
-
-    /**
-     * Does the browser have ShockwaveFlash plugin installed?
-     *
-     * <p>This method may still return true if the user has disabled Flash or set the plugin to
-     * "click to run".
-     */
-    public static boolean isInstalled() {
-      if (!checked) {
-        installed = hasFlash();
-        checked = true;
-      }
-      return installed;
-    }
-
-    private static native boolean hasFlash() /*-{
-      if (navigator.plugins && navigator.plugins.length) {
-        if (navigator.plugins['Shockwave Flash'])     return true;
-        if (navigator.plugins['Shockwave Flash 2.0']) return true;
-
-      } else if (navigator.mimeTypes && navigator.mimeTypes.length) {
-        var mimeType = navigator.mimeTypes['application/x-shockwave-flash'];
-        if (mimeType && mimeType.enabledPlugin) return true;
-
-      } else {
-        try { new ActiveXObject('ShockwaveFlash.ShockwaveFlash.7'); return true; } catch (e) {}
-        try { new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6'); return true; } catch (e) {}
-        try { new ActiveXObject('ShockwaveFlash.ShockwaveFlash');   return true; } catch (e) {}
-      }
-      return false;
-    }-*/;
-  }
-
-  /**
-   * Test for and disallow running this application in an &lt;iframe&gt;.
-   *
-   * <p>If the application is running within an iframe this method requests a browser generated
-   * redirect to pop the application out of the iframe into the top level window, and then aborts
-   * execution by throwing an exception. This is call should be placed early within the module's
-   * onLoad() method, before any real UI can be initialized that an attacking site could try to snip
-   * out and present in a confusing context.
-   *
-   * <p>If the break out works, execution will restart automatically in a proper top level window,
-   * where the script has full control over the display. If the break out fails, execution will
-   * abort and stop immediately, preventing UI widgets from being created, leaving the user with an
-   * empty frame.
-   */
-  public static void assertNotInIFrame() {
-    if (GWT.isScript() && amInsideIFrame()) {
-      bustOutOfIFrame(Window.Location.getHref());
-      throw new RuntimeException();
-    }
-  }
-
-  private static native boolean amInsideIFrame() /*-{ return top.location != $wnd.location; }-*/;
-
-  private static native void bustOutOfIFrame(String newloc) /*-{ top.location.href = newloc }-*/;
-
-  /**
-   * Test if Gerrit is running on a mobile browser. This check could be incomplete, but should cover
-   * most cases. Regexes shamelessly borrowed from CodeMirror.
-   */
-  public static native boolean isMobile() /*-{
-    var ua = $wnd.navigator.userAgent;
-    var ios = /AppleWebKit/.test(ua) && /Mobile\/\w+/.test(ua);
-    return ios
-        || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(ua);
-  }-*/;
-
-  /** Check if the height of the browser view is greater than its width. */
-  public static boolean isPortrait() {
-    return Window.getClientHeight() > Window.getClientWidth();
-  }
-
-  private UserAgent() {}
-}
diff --git a/java/com/google/gwtexpui/user/client/View.java b/java/com/google/gwtexpui/user/client/View.java
deleted file mode 100644
index b15d2fd..0000000
--- a/java/com/google/gwtexpui/user/client/View.java
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.user.client;
-
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.Widget;
-
-/**
- * Widget to display within a {@link ViewSite}.
- *
- * <p>Implementations must override {@code protected void onLoad()} and arrange for {@link
- * #display()} to be invoked once the DOM within the view is consistent for presentation to the
- * user. Typically this means that the subclass can start RPCs within {@code onLoad()} and then
- * invoke {@code display()} from within the AsyncCallback's {@code onSuccess(Object)} method.
- */
-public abstract class View extends Composite {
-  ViewSite<? extends View> site;
-
-  @Override
-  protected void onUnload() {
-    site = null;
-    super.onUnload();
-  }
-
-  /** true if this is the current view of its parent view site */
-  public final boolean isCurrentView() {
-    Widget p = getParent();
-    while (p != null) {
-      if (p instanceof ViewSite<?>) {
-        return ((ViewSite<?>) p).getView() == this;
-      }
-      p = p.getParent();
-    }
-    return false;
-  }
-
-  /** Replace the current view in the parent ViewSite with this view. */
-  public final void display() {
-    if (site != null) {
-      site.swap(this);
-    }
-  }
-}
diff --git a/java/com/google/gwtexpui/user/client/ViewSite.java b/java/com/google/gwtexpui/user/client/ViewSite.java
deleted file mode 100644
index 4614546..0000000
--- a/java/com/google/gwtexpui/user/client/ViewSite.java
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.user.client;
-
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.SimplePanel;
-
-/**
- * Hosts a single {@link View}.
- *
- * <p>View instances are attached inside of an invisible DOM node, permitting their {@code onLoad()}
- * method to be invoked and to update the DOM prior to the elements being made visible in the UI.
- *
- * <p>Complaint View instances must invoke {@link View#display()} once the DOM is ready for
- * presentation.
- */
-public class ViewSite<V extends View> extends Composite {
-  private final FlowPanel main;
-  private SimplePanel current;
-  private SimplePanel next;
-
-  public ViewSite() {
-    main = new FlowPanel();
-    initWidget(main);
-  }
-
-  /** Get the current view; null if there is no view being displayed. */
-  @SuppressWarnings("unchecked")
-  public V getView() {
-    return current != null ? (V) current.getWidget() : null;
-  }
-
-  /**
-   * Set the next view to display.
-   *
-   * <p>The view will be attached to the DOM tree within a hidden container, permitting its {@code
-   * onLoad()} method to execute and update the DOM without the user seeing the result.
-   *
-   * @param view the next view to display.
-   */
-  public void setView(V view) {
-    if (next != null) {
-      main.remove(next);
-    }
-    view.site = this;
-    next = new SimplePanel();
-    next.setVisible(false);
-    main.add(next);
-    next.add(view);
-  }
-
-  /**
-   * Invoked after the view becomes the current view and has been made visible.
-   *
-   * @param view the view being displayed.
-   */
-  protected void onShowView(V view) {}
-
-  @SuppressWarnings("unchecked")
-  final void swap(View v) {
-    if (next != null && next.getWidget() == v) {
-      if (current != null) {
-        main.remove(current);
-      }
-      current = next;
-      next = null;
-      current.setVisible(true);
-      onShowView((V) v);
-    }
-  }
-}
diff --git a/java/com/google/gwtexpui/user/client/tooltip.css b/java/com/google/gwtexpui/user/client/tooltip.css
deleted file mode 100644
index 1aeb015..0000000
--- a/java/com/google/gwtexpui/user/client/tooltip.css
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-.tooltip {
-  position: relative;
-}
-
-.tooltip:hover:before {
-  position: absolute;
-  z-index: 51;
-  border: solid;
-  border-color: #333 transparent;
-  border-width: 0 4px 4px 4px;
-  pointer-events: none;
-  content: "";
-
-  top: auto;
-  right: 50%;
-  bottom: -5px;
-  margin-right: -5px;
-}
-
-.tooltip:hover:after {
-  position: absolute;
-  z-index: 50;
-  font: normal normal 11px/1.5 Helvetica, arial, sans-serif;
-  text-align: center;
-  white-space: pre;
-  pointer-events: none;
-  background: rgba(0,0,0,.7);
-  color: #fff;
-  border-radius: 3px;
-  padding: 5px;
-  content: attr(aria-label);
-
-  top: 100%;
-  right: 50%;
-  margin-top: 5px;
-  -webkit-transform: translateX(50%);
-  -ms-transform: translateX(50%);
-  transform: translateX(50%)
-}
diff --git a/java/org/eclipse/jgit/BUILD b/java/org/eclipse/jgit/BUILD
index 95fef28..af8cde5 100644
--- a/java/org/eclipse/jgit/BUILD
+++ b/java/org/eclipse/jgit/BUILD
@@ -1,43 +1,6 @@
-load("//tools/bzl:genrule2.bzl", "genrule2")
-load("//tools/bzl:gwt.bzl", "gwt_module")
-
-gwt_module(
-    name = "client",
-    srcs = [
-        "diff/Edit_JsonSerializer.java",
-        "diff/ReplaceEdit.java",
-    ],
-    gwt_xml = "JGit.gwt.xml",
-    visibility = ["//visibility:public"],
-    deps = [
-        ":Edit",
-        "//lib:gwtjsonrpc",
-        "//lib/gwt:user",
-    ],
-)
-
-gwt_module(
-    name = "Edit",
-    srcs = [":jgit_edit_src"],
-    visibility = ["//visibility:public"],
-)
-
-genrule2(
-    name = "jgit_edit_src",
-    outs = ["edit.srcjar"],
-    cmd = " && ".join([
-        "unzip -qd $$TMP $(location //lib/jgit/org.eclipse.jgit:jgit-source) " +
-        "org/eclipse/jgit/diff/Edit.java",
-        "cd $$TMP",
-        "zip -Dq $$ROOT/$@ org/eclipse/jgit/diff/Edit.java",
-    ]),
-    tools = ["//lib/jgit/org.eclipse.jgit:jgit-source"],
-)
-
 java_library(
     name = "server",
     srcs = [
-        "diff/EditDeserializer.java",
         "diff/ReplaceEdit.java",
     ],
     visibility = ["//visibility:public"],
diff --git a/java/org/eclipse/jgit/JGit.gwt.xml b/java/org/eclipse/jgit/JGit.gwt.xml
deleted file mode 100644
index 5aeb936..0000000
--- a/java/org/eclipse/jgit/JGit.gwt.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<module>
-  <source path='diff' includes='
-      Edit.java
-      Edit_JsonSerializer.java
-      ReplaceEdit.java
-    '/>
-</module>
diff --git a/java/org/eclipse/jgit/diff/EditDeserializer.java b/java/org/eclipse/jgit/diff/EditDeserializer.java
deleted file mode 100644
index 9435979..0000000
--- a/java/org/eclipse/jgit/diff/EditDeserializer.java
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.eclipse.jgit.diff;
-
-import com.google.gson.JsonArray;
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonNull;
-import com.google.gson.JsonParseException;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.List;
-
-public class EditDeserializer implements JsonDeserializer<Edit>, JsonSerializer<Edit> {
-  @Override
-  public Edit deserialize(final JsonElement json, Type typeOfT, JsonDeserializationContext context)
-      throws JsonParseException {
-    if (json.isJsonNull()) {
-      return null;
-    }
-    if (!json.isJsonArray()) {
-      throw new JsonParseException("Expected array for Edit type");
-    }
-
-    final JsonArray o = (JsonArray) json;
-    final int cnt = o.size();
-    if (cnt < 4 || cnt % 4 != 0) {
-      throw new JsonParseException("Expected array of 4 for Edit type");
-    }
-
-    if (4 == cnt) {
-      return new Edit(get(o, 0), get(o, 1), get(o, 2), get(o, 3));
-    }
-
-    List<Edit> l = new ArrayList<>((cnt / 4) - 1);
-    for (int i = 4; i < cnt; ) {
-      int as = get(o, i++);
-      int ae = get(o, i++);
-      int bs = get(o, i++);
-      int be = get(o, i++);
-      l.add(new Edit(as, ae, bs, be));
-    }
-    return new ReplaceEdit(get(o, 0), get(o, 1), get(o, 2), get(o, 3), l);
-  }
-
-  private static int get(JsonArray a, int idx) throws JsonParseException {
-    final JsonElement v = a.get(idx);
-    if (!v.isJsonPrimitive()) {
-      throw new JsonParseException("Expected array of 4 for Edit type");
-    }
-    final JsonPrimitive p = (JsonPrimitive) v;
-    if (!p.isNumber()) {
-      throw new JsonParseException("Expected array of 4 for Edit type");
-    }
-    return p.getAsInt();
-  }
-
-  @Override
-  public JsonElement serialize(final Edit src, Type typeOfSrc, JsonSerializationContext context) {
-    if (src == null) {
-      return JsonNull.INSTANCE;
-    }
-    final JsonArray a = new JsonArray();
-    add(a, src);
-    if (src instanceof ReplaceEdit) {
-      for (Edit e : ((ReplaceEdit) src).getInternalEdits()) {
-        add(a, e);
-      }
-    }
-    return a;
-  }
-
-  private void add(JsonArray a, Edit src) {
-    a.add(new JsonPrimitive(src.getBeginA()));
-    a.add(new JsonPrimitive(src.getEndA()));
-    a.add(new JsonPrimitive(src.getBeginB()));
-    a.add(new JsonPrimitive(src.getEndB()));
-  }
-}
diff --git a/java/org/eclipse/jgit/diff/Edit_JsonSerializer.java b/java/org/eclipse/jgit/diff/Edit_JsonSerializer.java
deleted file mode 100644
index 184cb36..0000000
--- a/java/org/eclipse/jgit/diff/Edit_JsonSerializer.java
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.eclipse.jgit.diff;
-
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwtjsonrpc.client.impl.JsonSerializer;
-import java.util.ArrayList;
-import java.util.List;
-
-public class Edit_JsonSerializer extends JsonSerializer<Edit> {
-  public static final Edit_JsonSerializer INSTANCE = new Edit_JsonSerializer();
-
-  @Override
-  public Edit fromJson(Object jso) {
-    if (jso == null) {
-      return null;
-    }
-
-    final JavaScriptObject o = (JavaScriptObject) jso;
-    final int cnt = length(o);
-    if (4 == cnt) {
-      return new Edit(get(o, 0), get(o, 1), get(o, 2), get(o, 3));
-    }
-
-    List<Edit> l = new ArrayList<>((cnt / 4) - 1);
-    for (int i = 4; i < cnt; ) {
-      int as = get(o, i++);
-      int ae = get(o, i++);
-      int bs = get(o, i++);
-      int be = get(o, i++);
-      l.add(new Edit(as, ae, bs, be));
-    }
-    return new ReplaceEdit(get(o, 0), get(o, 1), get(o, 2), get(o, 3), l);
-  }
-
-  @Override
-  public void printJson(StringBuilder sb, Edit o) {
-    sb.append('[');
-    append(sb, o);
-    if (o instanceof ReplaceEdit) {
-      for (Edit e : ((ReplaceEdit) o).getInternalEdits()) {
-        sb.append(',');
-        append(sb, e);
-      }
-    }
-    sb.append(']');
-  }
-
-  private void append(StringBuilder sb, Edit o) {
-    sb.append(o.getBeginA());
-    sb.append(',');
-    sb.append(o.getEndA());
-    sb.append(',');
-    sb.append(o.getBeginB());
-    sb.append(',');
-    sb.append(o.getEndB());
-  }
-
-  private static native int length(JavaScriptObject jso) /*-{ return jso.length; }-*/;
-
-  private static native int get(JavaScriptObject jso, int idx) /*-{ return jso[idx]; }-*/;
-}
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
index 5e46a03..0f195b5 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
@@ -56,6 +56,7 @@
 import com.google.gerrit.acceptance.UseSsh;
 import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
 import com.google.gerrit.acceptance.testsuite.account.TestSshKeys;
+import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.common.data.AccessSection;
 import com.google.gerrit.common.data.GlobalCapability;
@@ -92,11 +93,13 @@
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
+import com.google.gerrit.git.LockFailureException;
 import com.google.gerrit.gpg.Fingerprint;
 import com.google.gerrit.gpg.PublicKeyStore;
 import com.google.gerrit.gpg.testing.TestKey;
 import com.google.gerrit.mail.Address;
 import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.reviewdb.client.Branch;
 import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.reviewdb.client.Project;
@@ -116,7 +119,6 @@
 import com.google.gerrit.server.account.externalids.ExternalIdNotes;
 import com.google.gerrit.server.account.externalids.ExternalIds;
 import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.LockFailureException;
 import com.google.gerrit.server.git.meta.MetaDataUpdate;
 import com.google.gerrit.server.index.account.AccountIndexer;
 import com.google.gerrit.server.index.account.StalenessChecker;
@@ -233,6 +235,8 @@
 
   @Inject private AccountManager accountManager;
 
+  @Inject protected GroupOperations groupOperations;
+
   private AccountIndexedCounter accountIndexedCounter;
   private RegistrationHandle accountIndexEventCounterHandle;
   private RefUpdateCounter refUpdateCounter;
@@ -2208,7 +2212,9 @@
   public void allGroupsForAUserAccountCanBeRetrieved() throws Exception {
     String username = name("user1");
     accountOperations.newAccount().username(username).create();
-    String group = createGroup("group");
+    AccountGroup.UUID groupID = groupOperations.newGroup().name("group").create();
+    String group = groupOperations.group(groupID).get().name();
+
     gApi.groups().id(group).addMembers(username);
 
     List<GroupInfo> allGroups = gApi.accounts().id(username).getGroups();
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AgreementsIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AgreementsIT.java
index 7a4a901..b4416302 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/AgreementsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/AgreementsIT.java
@@ -16,13 +16,22 @@
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.TruthJUnit.assume;
+import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.util.concurrent.TimeUnit.SECONDS;
 
+import com.google.common.collect.ImmutableList;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.GerritConfig;
+import com.google.gerrit.acceptance.PushOneCommit;
+import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
+import com.google.gerrit.common.RawInputUtil;
 import com.google.gerrit.common.data.ContributorAgreement;
+import com.google.gerrit.common.data.GroupReference;
+import com.google.gerrit.common.data.PermissionRule;
 import com.google.gerrit.extensions.api.changes.CherryPickInput;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
 import com.google.gerrit.extensions.api.changes.SubmitInput;
+import com.google.gerrit.extensions.api.groups.GroupApi;
 import com.google.gerrit.extensions.api.projects.BranchInfo;
 import com.google.gerrit.extensions.api.projects.BranchInput;
 import com.google.gerrit.extensions.client.InheritableBoolean;
@@ -34,8 +43,14 @@
 import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
 import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.BooleanProjectConfig;
+import com.google.gerrit.server.git.meta.MetaDataUpdate;
+import com.google.gerrit.server.group.InternalGroup;
+import com.google.gerrit.server.project.ProjectConfig;
 import com.google.gerrit.testing.ConfigSuite;
 import com.google.gerrit.testing.TestTimeUtil;
+import com.google.inject.Inject;
 import java.util.List;
 import org.eclipse.jgit.lib.Config;
 import org.junit.AfterClass;
@@ -46,6 +61,46 @@
 public class AgreementsIT extends AbstractDaemonTest {
   private ContributorAgreement caAutoVerify;
   private ContributorAgreement caNoAutoVerify;
+  @Inject private GroupOperations groupOperations;
+
+  protected void setUseContributorAgreements(InheritableBoolean value) throws Exception {
+    try (MetaDataUpdate md = metaDataUpdateFactory.create(project)) {
+      ProjectConfig config = projectConfigFactory.read(md);
+      config.getProject().setBooleanConfig(BooleanProjectConfig.USE_CONTRIBUTOR_AGREEMENTS, value);
+      config.commit(md);
+      projectCache.evict(config.getProject());
+    }
+  }
+
+  protected ContributorAgreement configureContributorAgreement(boolean autoVerify)
+      throws Exception {
+    ContributorAgreement ca;
+    String name = autoVerify ? "cla-test-group" : "cla-test-no-auto-verify-group";
+    AccountGroup.UUID g = groupOperations.newGroup().name(name).create();
+    GroupApi groupApi = gApi.groups().id(g.get());
+    groupApi.description("CLA test group");
+    InternalGroup caGroup = group(new AccountGroup.UUID(groupApi.detail().id));
+    GroupReference groupRef = new GroupReference(caGroup.getGroupUUID(), caGroup.getName());
+    PermissionRule rule = new PermissionRule(groupRef);
+    rule.setAction(PermissionRule.Action.ALLOW);
+    if (autoVerify) {
+      ca = new ContributorAgreement("cla-test");
+      ca.setAutoVerify(groupRef);
+      ca.setAccepted(ImmutableList.of(rule));
+    } else {
+      ca = new ContributorAgreement("cla-test-no-auto-verify");
+    }
+    ca.setDescription("description");
+    ca.setAgreementUrl("agreement-url");
+    ca.setAccepted(ImmutableList.of(rule));
+    ca.setExcludeProjectsRegexes(ImmutableList.of("ExcludedProject"));
+
+    try (ProjectConfigUpdate u = updateProject(allProjects)) {
+      u.getConfig().replace(ca);
+      u.save();
+      return ca;
+    }
+  }
 
   @ConfigSuite.Config
   public static Config enableAgreementsConfig() {
@@ -182,6 +237,28 @@
   }
 
   @Test
+  public void revertExcludedProjectChangeWithoutCLA() throws Exception {
+    // Contributor agreements configured with excludeProjects = ExcludedProject
+    // in AbstractDaemonTest.configureContributorAgreement(...)
+    assume().that(isContributorAgreementsEnabled()).isTrue();
+
+    // Create a change succeeds when agreement is not required
+    setUseContributorAgreements(InheritableBoolean.FALSE);
+    // Project name includes test method name which contains ExcludedProject
+    ChangeInfo change = gApi.changes().create(newChangeInput()).get();
+
+    // Approve and submit it
+    setApiUser(admin);
+    gApi.changes().id(change.changeId).current().review(ReviewInput.approve());
+    gApi.changes().id(change.changeId).current().submit(new SubmitInput());
+
+    // Revert in excluded project is allowed even when CLA is required but not signed
+    setApiUser(user);
+    setUseContributorAgreements(InheritableBoolean.TRUE);
+    gApi.changes().id(change.changeId).revert();
+  }
+
+  @Test
   public void cherrypickChangeWithoutCLA() throws Exception {
     assume().that(isContributorAgreementsEnabled()).isTrue();
 
@@ -240,6 +317,17 @@
     gApi.changes().create(newChangeInput());
   }
 
+  @Test
+  public void createExcludedProjectChangeIgnoresCLA() throws Exception {
+    // Contributor agreements configured with excludeProjects = ExcludedProject
+    // in AbstractDaemonTest.configureContributorAgreement(...)
+    assume().that(isContributorAgreementsEnabled()).isTrue();
+
+    // Create a change in excluded project is allowed even when CLA is required but not signed.
+    setUseContributorAgreements(InheritableBoolean.TRUE);
+    gApi.changes().create(newChangeInput());
+  }
+
   private void assertAgreement(AgreementInfo info, ContributorAgreement ca) {
     assertThat(info.name).isEqualTo(ca.getName());
     assertThat(info.description).isEqualTo(ca.getDescription());
@@ -258,4 +346,33 @@
     in.project = project.get();
     return in;
   }
+
+  @Test
+  @GerritConfig(name = "auth.contributorAgreements", value = "true")
+  public void anonymousAccessServerInfoEvenWithCLAs() throws Exception {
+    setApiUserAnonymous();
+    gApi.config().server().getInfo();
+  }
+
+  @Test
+  public void publishEditRestWithoutCLA() throws Exception {
+    String filename = "foo";
+    PushOneCommit push =
+        pushFactory.create(db, admin.getIdent(), testRepo, "subject1", filename, "contentold");
+    PushOneCommit.Result result = push.to("refs/for/master");
+    result.assertOkStatus();
+    String changeId = result.getChangeId();
+
+    gApi.changes().id(changeId).edit().create();
+    gApi.changes()
+        .id(changeId)
+        .edit()
+        .modifyFile(filename, RawInputUtil.create("newcontent".getBytes(UTF_8)));
+
+    String url = "/changes/" + changeId + "/edit:publish";
+    setUseContributorAgreements(InheritableBoolean.TRUE);
+    userRestSession.post(url).assertForbidden();
+    setUseContributorAgreements(InheritableBoolean.FALSE);
+    userRestSession.post(url).assertNoContent();
+  }
 }
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/BUILD b/javatests/com/google/gerrit/acceptance/api/accounts/BUILD
index 31f3f91..2167d27 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/BUILD
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/BUILD
@@ -9,6 +9,7 @@
         "no_windows",
     ],
     deps = [
+        "//java/com/google/gerrit/git",
         "//java/com/google/gerrit/mail",
         "//java/com/google/gerrit/server/util/time",
     ],
diff --git a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
index 7063b27..744d1e9 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
@@ -68,6 +68,7 @@
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.acceptance.TestProjectInput;
 import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
+import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
 import com.google.gerrit.common.FooterConstants;
 import com.google.gerrit.common.data.LabelFunction;
 import com.google.gerrit.common.data.LabelType;
@@ -80,6 +81,7 @@
 import com.google.gerrit.extensions.api.changes.NotifyInfo;
 import com.google.gerrit.extensions.api.changes.RebaseInput;
 import com.google.gerrit.extensions.api.changes.RecipientType;
+import com.google.gerrit.extensions.api.changes.RelatedChangeAndCommitInfo;
 import com.google.gerrit.extensions.api.changes.RevertInput;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
 import com.google.gerrit.extensions.api.changes.ReviewInput.DraftHandling;
@@ -124,6 +126,7 @@
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
+import com.google.gerrit.index.IndexConfig;
 import com.google.gerrit.mail.Address;
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.AccountGroup;
@@ -139,8 +142,12 @@
 import com.google.gerrit.server.change.ChangeResource;
 import com.google.gerrit.server.git.ChangeMessageModifier;
 import com.google.gerrit.server.group.SystemGroupBackend;
+import com.google.gerrit.server.index.change.ChangeIndex;
+import com.google.gerrit.server.index.change.ChangeIndexCollection;
+import com.google.gerrit.server.index.change.IndexedChangeQuery;
 import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
 import com.google.gerrit.server.project.testing.Util;
+import com.google.gerrit.server.query.change.ChangeData;
 import com.google.gerrit.server.restapi.change.PostReview;
 import com.google.gerrit.server.update.BatchUpdate;
 import com.google.gerrit.server.update.BatchUpdateOp;
@@ -185,6 +192,11 @@
 
   @Inject private AccountOperations accountOperations;
 
+  @Inject private ChangeIndexCollection changeIndexCollection;
+  @Inject private IndexConfig indexConfig;
+
+  @Inject protected GroupOperations groupOperations;
+
   private ChangeIndexedCounter changeIndexedCounter;
   private RegistrationHandle changeIndexedCounterHandle;
 
@@ -943,13 +955,77 @@
     RevisionInfo ri2 = ci2.revisions.get(ci2.currentRevision);
     assertThat(ri2.commit.parents.get(0).commit).isEqualTo(branchTip);
 
+    Change.Id id1 = r1.getChange().getId();
     RebaseInput in = new RebaseInput();
-    in.base = Integer.toString(r1.getChange().getId().get());
+    in.base = id1.toString();
     gApi.changes().id(r2.getChangeId()).rebase(in);
 
+    Change.Id id2 = r2.getChange().getId();
     ci2 = get(r2.getChangeId(), CURRENT_REVISION, CURRENT_COMMIT);
     ri2 = ci2.revisions.get(ci2.currentRevision);
     assertThat(ri2.commit.parents.get(0).commit).isEqualTo(r1.getCommit().name());
+
+    List<RelatedChangeAndCommitInfo> related = getRelated(id2, ri2._number);
+    assertThat(related).hasSize(2);
+    assertThat(related.get(0)._changeNumber).isEqualTo(id2.get());
+    assertThat(related.get(0)._revisionNumber).isEqualTo(2);
+    assertThat(related.get(1)._changeNumber).isEqualTo(id1.get());
+    assertThat(related.get(1)._revisionNumber).isEqualTo(1);
+  }
+
+  @Test
+  public void rebaseOnClosedChange() throws Exception {
+    String branchTip = testRepo.getRepository().exactRef("HEAD").getObjectId().name();
+    PushOneCommit.Result r1 = createChange();
+    testRepo.reset("HEAD~1");
+    PushOneCommit.Result r2 = createChange();
+
+    ChangeInfo ci2 = get(r2.getChangeId(), CURRENT_REVISION, CURRENT_COMMIT);
+    RevisionInfo ri2 = ci2.revisions.get(ci2.currentRevision);
+    assertThat(ri2.commit.parents.get(0).commit).isEqualTo(branchTip);
+
+    // Submit first change.
+    Change.Id id1 = r1.getChange().getId();
+    gApi.changes().id(id1.get()).current().review(ReviewInput.approve());
+    gApi.changes().id(id1.get()).current().submit();
+
+    // Rebase second change on first change.
+    RebaseInput in = new RebaseInput();
+    in.base = id1.toString();
+    gApi.changes().id(r2.getChangeId()).rebase(in);
+
+    Change.Id id2 = r2.getChange().getId();
+    ci2 = get(r2.getChangeId(), CURRENT_REVISION, CURRENT_COMMIT);
+    ri2 = ci2.revisions.get(ci2.currentRevision);
+    assertThat(ri2.commit.parents.get(0).commit).isEqualTo(r1.getCommit().name());
+
+    assertThat(getRelated(id2, ri2._number)).isEmpty();
+  }
+
+  @Test
+  public void rebaseFromRelationChainToClosedChange() throws Exception {
+    PushOneCommit.Result r1 = createChange();
+    testRepo.reset("HEAD~1");
+
+    createChange();
+    PushOneCommit.Result r3 = createChange();
+
+    // Submit first change.
+    Change.Id id1 = r1.getChange().getId();
+    gApi.changes().id(id1.get()).current().review(ReviewInput.approve());
+    gApi.changes().id(id1.get()).current().submit();
+
+    // Rebase third change on first change.
+    RebaseInput in = new RebaseInput();
+    in.base = id1.toString();
+    gApi.changes().id(r3.getChangeId()).rebase(in);
+
+    Change.Id id3 = r3.getChange().getId();
+    ChangeInfo ci3 = get(r3.getChangeId(), CURRENT_REVISION, CURRENT_COMMIT);
+    RevisionInfo ri3 = ci3.revisions.get(ci3.currentRevision);
+    assertThat(ri3.commit.parents.get(0).commit).isEqualTo(r1.getCommit().name());
+
+    assertThat(getRelated(id3, ri3._number)).isEmpty();
   }
 
   @Test
@@ -1244,6 +1320,23 @@
   }
 
   @Test
+  public void deleteChangeUpdatesIndex() throws Exception {
+    PushOneCommit.Result changeResult = createChange();
+    String changeId = changeResult.getChangeId();
+    Change.Id id = changeResult.getChange().getId();
+
+    ChangeIndex idx = changeIndexCollection.getSearchIndex();
+
+    Optional<ChangeData> result =
+        idx.get(id, IndexedChangeQuery.createOptions(indexConfig, 0, 1, ImmutableSet.of()));
+
+    assertThat(result.isPresent()).isTrue();
+    gApi.changes().id(changeId).delete();
+    result = idx.get(id, IndexedChangeQuery.createOptions(indexConfig, 0, 1, ImmutableSet.of()));
+    assertThat(result.isPresent()).isFalse();
+  }
+
+  @Test
   public void rebaseUpToDateChange() throws Exception {
     PushOneCommit.Result r = createChange();
     exception.expect(ResourceConflictException.class);
@@ -1602,7 +1695,7 @@
     PushOneCommit.Result result = createChange();
 
     String username = name("new-user");
-    gApi.accounts().create(username).setActive(false);
+    accountOperations.newAccount().username(username).inactive().create();
 
     AddReviewerInput in = new AddReviewerInput();
     in.reviewer = username;
@@ -1624,7 +1717,7 @@
     PushOneCommit.Result result = createChange();
 
     String username = "user@domain.com";
-    gApi.accounts().create(username).setActive(false);
+    accountOperations.newAccount().username(username).inactive().create();
 
     AddReviewerInput in = new AddReviewerInput();
     in.reviewer = username;
@@ -1733,7 +1826,7 @@
             .preferredEmail(email)
             .fullname(fullname)
             .create();
-    String testGroup = createGroupWithRealName("ab");
+    String testGroup = groupOperations.newGroup().name("ab").create().get();
     GroupApi groupApi = gApi.groups().id(testGroup);
     groupApi.description("test group");
     groupApi.addMembers(user.fullName);
@@ -1794,7 +1887,7 @@
             .fullname(myGroupUserFullname)
             .create();
 
-    String testGroup = createGroupWithRealName("kobe");
+    String testGroup = groupOperations.newGroup().name("kobe").create().get();
     GroupApi groupApi = gApi.groups().id(testGroup);
     groupApi.description("test group");
     groupApi.addMembers(myGroupUserFullname);
@@ -2006,7 +2099,7 @@
     ChangeResource rsrc = parseResource(r);
     String oldETag = rsrc.getETag();
 
-    gApi.accounts().id(admin.id.get()).setStatus("new status");
+    accountOperations.account(admin.id).forUpdate().status("new status").update();
     rsrc = parseResource(r);
     assertThat(rsrc.getETag()).isNotEqualTo(oldETag);
   }
diff --git a/javatests/com/google/gerrit/acceptance/api/group/GroupsConsistencyIT.java b/javatests/com/google/gerrit/acceptance/api/group/GroupsConsistencyIT.java
index 87a566e..491cb3a 100644
--- a/javatests/com/google/gerrit/acceptance/api/group/GroupsConsistencyIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/group/GroupsConsistencyIT.java
@@ -20,6 +20,7 @@
 import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.acceptance.Sandboxed;
+import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
 import com.google.gerrit.common.data.GlobalCapability;
 import com.google.gerrit.extensions.api.config.ConsistencyCheckInfo;
 import com.google.gerrit.extensions.api.config.ConsistencyCheckInfo.ConsistencyProblemInfo;
@@ -30,6 +31,7 @@
 import com.google.gerrit.server.group.db.GroupConfig;
 import com.google.gerrit.server.group.db.GroupNameNotes;
 import com.google.gerrit.server.group.db.testing.GroupTestUtil;
+import com.google.inject.Inject;
 import java.util.List;
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.RefRename;
@@ -47,6 +49,8 @@
 @Sandboxed
 @NoHttpd
 public class GroupsConsistencyIT extends AbstractDaemonTest {
+
+  @Inject protected GroupOperations groupOperations;
   private GroupInfo gAdmin;
   private GroupInfo g1;
   private GroupInfo g2;
@@ -57,8 +61,8 @@
   public void basicSetup() throws Exception {
     allowGlobalCapabilities(REGISTERED_USERS, GlobalCapability.ACCESS_DATABASE);
 
-    String name1 = createGroup("g1");
-    String name2 = createGroup("g2");
+    String name1 = groupOperations.newGroup().name("g1").create().get();
+    String name2 = groupOperations.newGroup().name("g2").create().get();
 
     gApi.groups().id(name1).addMembers(user.fullName);
     gApi.groups().id(name2).addMembers(admin.fullName);
@@ -218,7 +222,7 @@
   @Test
   public void cyclicSubgroup() throws Exception {
     updateGroupFile(RefNames.refsGroups(new AccountGroup.UUID(g1.id)), "subgroups", g1.id + "\n");
-    assertWarning("cyclic");
+    assertWarning("cycle");
   }
 
   private void assertError(String msg) throws Exception {
diff --git a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
index ade0f3c..ee22141 100644
--- a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
@@ -39,6 +39,7 @@
 import com.google.gerrit.acceptance.Sandboxed;
 import com.google.gerrit.acceptance.TestAccount;
 import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
+import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.common.data.GlobalCapability;
 import com.google.gerrit.common.data.GroupReference;
@@ -126,6 +127,7 @@
   @Inject private DynamicSet<GroupIndexedListener> groupIndexedListeners;
   @Inject private Sequences seq;
   @Inject private AccountOperations accountOperations;
+  @Inject private GroupOperations groupOperations;
 
   @Before
   public void setTimeForTesting() {
@@ -144,6 +146,23 @@
     }
   }
 
+  // Creates a group, but with uniquified name.
+  protected String createGroup(String name) throws Exception {
+    // TODO(hanwen): rewrite this test in terms of UUID. This requires redoing the assertion helpers
+    // too.
+    AccountGroup.UUID g = groupOperations.newGroup().ownerGroupUuid(adminGroupUuid()).create();
+    return groupRef(g).getName();
+  }
+
+  protected String createGroup(String name, String owner) throws Exception {
+    name = name(name);
+    GroupInput in = new GroupInput();
+    in.name = name;
+    in.ownerId = owner;
+    gApi.groups().create(in);
+    return name;
+  }
+
   @Override
   protected ProjectResetter.Config resetProjects() {
     // Don't reset All-Users since deleting users makes groups inconsistent (e.g. groups would
@@ -1493,9 +1512,9 @@
   }
 
   private static void assertIncludes(Iterable<GroupInfo> includes, String... expectedNames) {
-    assertThat(Iterables.transform(includes, i -> i.name))
-        .containsExactlyElementsIn(Arrays.asList(expectedNames))
-        .inOrder();
+    Iterable<String> names = Iterables.transform(includes, i -> i.name);
+    assertThat(names).containsExactlyElementsIn(Arrays.asList(expectedNames));
+    assertThat(names).isOrdered();
   }
 
   private void assertNoIncludes(String group) throws Exception {
diff --git a/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java b/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java
index 9fcbaa7..995f89b 100644
--- a/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java
@@ -33,6 +33,7 @@
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.extensions.api.projects.BranchInput;
+import com.google.gerrit.extensions.api.projects.CommentLinkInfo;
 import com.google.gerrit.extensions.api.projects.ConfigInfo;
 import com.google.gerrit.extensions.api.projects.ConfigInput;
 import com.google.gerrit.extensions.api.projects.DescriptionInput;
@@ -51,7 +52,10 @@
 import com.google.gerrit.reviewdb.client.RefNames;
 import com.google.gerrit.server.group.SystemGroupBackend;
 import com.google.gerrit.server.index.IndexExecutor;
+import com.google.gerrit.server.project.CommentLinkInfoImpl;
 import com.google.inject.Inject;
+import java.util.HashMap;
+import java.util.Map;
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.transport.PushResult;
 import org.eclipse.jgit.transport.RemoteRefUpdate.Status;
@@ -61,6 +65,13 @@
 
 @NoHttpd
 public class ProjectIT extends AbstractDaemonTest {
+  private static final String BUGZILLA = "bugzilla";
+  private static final String BUGZILLA_LINK = "http://bugzilla.example.com/?id=$2";
+  private static final String BUGZILLA_MATCH = "(bug\\\\s+#?)(\\\\d+)";
+  private static final String JIRA = "jira";
+  private static final String JIRA_LINK = "http://jira.example.com/?id=$2";
+  private static final String JIRA_MATCH = "(jira\\\\s+#?)(\\\\d+)";
+
   @Inject private DynamicSet<ProjectIndexedListener> projectIndexedListeners;
 
   @Inject
@@ -603,6 +614,31 @@
     setMaxObjectSize("100 foo");
   }
 
+  @Test
+  public void noCommentlinksByDefault() throws Exception {
+    assertThat(getConfig().commentlinks).isEmpty();
+  }
+
+  @Test
+  @GerritConfig(name = "commentlink.bugzilla.match", value = BUGZILLA_MATCH)
+  @GerritConfig(name = "commentlink.bugzilla.link", value = BUGZILLA_LINK)
+  @GerritConfig(name = "commentlink.jira.match", value = JIRA_MATCH)
+  @GerritConfig(name = "commentlink.jira.link", value = JIRA_LINK)
+  public void projectConfigUsesCommentlinksFromGlobalConfig() throws Exception {
+    Map<String, CommentLinkInfo> expected = new HashMap<>();
+    expected.put(BUGZILLA, commentLinkInfo(BUGZILLA, BUGZILLA_MATCH, BUGZILLA_LINK));
+    expected.put(JIRA, commentLinkInfo(JIRA, JIRA_MATCH, JIRA_LINK));
+    assertCommentLinks(getConfig(), expected);
+  }
+
+  private CommentLinkInfo commentLinkInfo(String name, String match, String link) {
+    return new CommentLinkInfoImpl(name, match, link, null /*html*/, null /*enabled*/);
+  }
+
+  private void assertCommentLinks(ConfigInfo actual, Map<String, CommentLinkInfo> expected) {
+    assertThat(actual.commentlinks).containsExactlyEntriesIn(expected);
+  }
+
   private ConfigInfo setConfig(Project.NameKey name, ConfigInput input) throws Exception {
     return gApi.projects().name(name.get()).config(input);
   }
diff --git a/javatests/com/google/gerrit/acceptance/api/revision/RobotCommentsIT.java b/javatests/com/google/gerrit/acceptance/api/revision/RobotCommentsIT.java
index cd20765..d713db6 100644
--- a/javatests/com/google/gerrit/acceptance/api/revision/RobotCommentsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/revision/RobotCommentsIT.java
@@ -1024,7 +1024,7 @@
   }
 
   @Test
-  public void queryChangesWithUnresolvedCommentCount() throws Exception {
+  public void queryChangesWithCommentCounts() throws Exception {
     assume().that(notesMigration.readChanges()).isTrue();
 
     PushOneCommit.Result r1 = createChange();
@@ -1043,6 +1043,7 @@
       // if we allow users to resolve a robot comment, then this test should
       // be modified.
       assertThat(result.unresolvedCommentCount).isEqualTo(0);
+      assertThat(result.totalCommentCount).isEqualTo(1);
     } finally {
       enableDb(ctx);
     }
diff --git a/javatests/com/google/gerrit/acceptance/edit/ChangeEditIT.java b/javatests/com/google/gerrit/acceptance/edit/ChangeEditIT.java
index 91a1278..96566f6 100644
--- a/javatests/com/google/gerrit/acceptance/edit/ChangeEditIT.java
+++ b/javatests/com/google/gerrit/acceptance/edit/ChangeEditIT.java
@@ -41,7 +41,6 @@
 import com.google.gerrit.extensions.api.changes.NotifyHandling;
 import com.google.gerrit.extensions.api.changes.PublishChangeEditInput;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
-import com.google.gerrit.extensions.client.InheritableBoolean;
 import com.google.gerrit.extensions.client.ListChangesOption;
 import com.google.gerrit.extensions.common.ApprovalInfo;
 import com.google.gerrit.extensions.common.ChangeInfo;
@@ -238,15 +237,6 @@
   }
 
   @Test
-  public void publishEditRestWithoutCLA() throws Exception {
-    createArbitraryEditFor(changeId);
-    setUseContributorAgreements(InheritableBoolean.TRUE);
-    adminRestSession.post(urlPublish(changeId)).assertForbidden();
-    setUseContributorAgreements(InheritableBoolean.FALSE);
-    adminRestSession.post(urlPublish(changeId)).assertNoContent();
-  }
-
-  @Test
   public void rebaseEdit() throws Exception {
     PatchSet previousPatchSet = getCurrentPatchSet(changeId2);
     createEmptyEditFor(changeId2);
diff --git a/javatests/com/google/gerrit/acceptance/git/AbstractSubmoduleSubscription.java b/javatests/com/google/gerrit/acceptance/git/AbstractSubmoduleSubscription.java
index 943b052..f306932 100644
--- a/javatests/com/google/gerrit/acceptance/git/AbstractSubmoduleSubscription.java
+++ b/javatests/com/google/gerrit/acceptance/git/AbstractSubmoduleSubscription.java
@@ -53,6 +53,7 @@
 import org.eclipse.jgit.transport.RefSpec;
 import org.eclipse.jgit.transport.RemoteRefUpdate;
 import org.eclipse.jgit.transport.RemoteRefUpdate.Status;
+import org.junit.Before;
 
 public abstract class AbstractSubmoduleSubscription extends AbstractDaemonTest {
 
@@ -95,7 +96,7 @@
     return cfg;
   }
 
-  protected TestRepository<?> createProjectWithPush(
+  protected Project.NameKey createProjectForPush(
       String name,
       @Nullable Project.NameKey parent,
       boolean createEmptyCommit,
@@ -104,24 +105,40 @@
     Project.NameKey project = createProject(name, parent, createEmptyCommit, submitType);
     grant(project, "refs/heads/*", Permission.PUSH);
     grant(project, "refs/for/refs/heads/*", Permission.SUBMIT);
-    return cloneProject(project);
-  }
-
-  protected TestRepository<?> createProjectWithPush(String name, @Nullable Project.NameKey parent)
-      throws Exception {
-    return createProjectWithPush(name, parent, true, getSubmitType());
-  }
-
-  protected TestRepository<?> createProjectWithPush(String name, boolean createEmptyCommit)
-      throws Exception {
-    return createProjectWithPush(name, null, createEmptyCommit, getSubmitType());
+    return project;
   }
 
   protected TestRepository<?> createProjectWithPush(String name) throws Exception {
     return createProjectWithPush(name, null, true, getSubmitType());
   }
 
+  protected TestRepository<?> createProjectWithPush(
+      String name,
+      @Nullable Project.NameKey parent,
+      boolean createEmptyCommit,
+      SubmitType submitType)
+      throws Exception {
+    return cloneProject(createProjectForPush(name, parent, createEmptyCommit, submitType));
+  }
+
+  protected TestRepository<?> createProjectWithPush(String name, boolean createEmptyCommit)
+      throws Exception {
+    return cloneProject(createProjectForPush(name, null, createEmptyCommit, getSubmitType()));
+  }
+
   private static AtomicInteger contentCounter = new AtomicInteger(0);
+  protected TestRepository<?> superRepo;
+  protected Project.NameKey superKey;
+  protected TestRepository<?> subRepo;
+  protected Project.NameKey subKey;
+
+  @Before
+  public void setUp() throws Exception {
+    superKey = createProjectForPush("super", null, true, getSubmitType());
+    subKey = createProjectForPush("sub", null, true, getSubmitType());
+    superRepo = cloneProject(superKey);
+    subRepo = cloneProject(subKey);
+  }
 
   protected ObjectId pushChangeTo(
       TestRepository<?> repo, String ref, String file, String content, String message, String topic)
@@ -184,16 +201,31 @@
   protected void allowSubmoduleSubscription(
       String submodule, String subBranch, String superproject, String superBranch, boolean match)
       throws Exception {
-    Project.NameKey sub = new Project.NameKey(name(submodule));
-    Project.NameKey superName = new Project.NameKey(name(superproject));
-    try (MetaDataUpdate md = metaDataUpdateFactory.create(sub)) {
+    allowSubmoduleSubscription(
+        nameKey(submodule), subBranch, nameKey(superproject), superBranch, match);
+  }
+
+  protected void allowMatchingSubmoduleSubscription(
+      Project.NameKey submodule, String subBranch, Project.NameKey superproject, String superBranch)
+      throws Exception {
+    allowSubmoduleSubscription(submodule, subBranch, superproject, superBranch, true);
+  }
+
+  protected void allowSubmoduleSubscription(
+      Project.NameKey submodule,
+      String subBranch,
+      Project.NameKey superproject,
+      String superBranch,
+      boolean match)
+      throws Exception {
+    try (MetaDataUpdate md = metaDataUpdateFactory.create(submodule)) {
       md.setMessage("Added superproject subscription");
       SubscribeSection s;
-      ProjectConfig pc = ProjectConfig.read(md);
-      if (pc.getSubscribeSections().containsKey(superName)) {
-        s = pc.getSubscribeSections().get(superName);
+      ProjectConfig pc = projectConfigFactory.read(md);
+      if (pc.getSubscribeSections().containsKey(superproject)) {
+        s = pc.getSubscribeSections().get(superproject);
       } else {
-        s = new SubscribeSection(superName);
+        s = new SubscribeSection(superproject);
       }
       String refspec;
       if (superBranch == null) {
@@ -223,6 +255,15 @@
   protected void createSubmoduleSubscription(
       TestRepository<?> repo, String branch, String subscribeToRepo, String subscribeToBranch)
       throws Exception {
+    createSubmoduleSubscription(repo, branch, nameKey(subscribeToRepo), subscribeToBranch);
+  }
+
+  protected void createSubmoduleSubscription(
+      TestRepository<?> repo,
+      String branch,
+      Project.NameKey subscribeToRepo,
+      String subscribeToBranch)
+      throws Exception {
     Config config = new Config();
     prepareSubmoduleConfigEntry(config, subscribeToRepo, subscribeToBranch);
     pushSubmoduleConfig(repo, branch, config);
@@ -246,12 +287,20 @@
       String subscribeToRepoPrefix,
       String subscribeToRepo,
       String subscribeToBranch) {
-    subscribeToRepo = name(subscribeToRepo);
-    String url = subscribeToRepoPrefix + subscribeToRepo;
-    config.setString("submodule", subscribeToRepo, "path", subscribeToRepo);
-    config.setString("submodule", subscribeToRepo, "url", url);
+    prepareRelativeSubmoduleConfigEntry(
+        config, subscribeToRepoPrefix, nameKey(subscribeToRepo), subscribeToBranch);
+  }
+
+  protected void prepareRelativeSubmoduleConfigEntry(
+      Config config,
+      String subscribeToRepoPrefix,
+      Project.NameKey subscribeToRepo,
+      String subscribeToBranch) {
+    String url = subscribeToRepoPrefix + subscribeToRepo.get();
+    config.setString("submodule", subscribeToRepo.get(), "path", subscribeToRepo.get());
+    config.setString("submodule", subscribeToRepo.get(), "url", url);
     if (subscribeToBranch != null) {
-      config.setString("submodule", subscribeToRepo, "branch", subscribeToBranch);
+      config.setString("submodule", subscribeToRepo.get(), "branch", subscribeToBranch);
     }
   }
 
@@ -260,21 +309,41 @@
     // The submodule subscription module checks for gerrit.canonicalWebUrl to
     // detect if it's configured for automatic updates. It doesn't matter if
     // it serves from that URL.
+    prepareSubmoduleConfigEntry(
+        config, nameKey(subscribeToRepo), nameKey(subscribeToRepo), subscribeToBranch);
+  }
+
+  protected void prepareSubmoduleConfigEntry(
+      Config config, Project.NameKey subscribeToRepo, String subscribeToBranch) {
+    // The submodule subscription module checks for gerrit.canonicalWebUrl to
+    // detect if it's configured for automatic updates. It doesn't matter if
+    // it serves from that URL.
     prepareSubmoduleConfigEntry(config, subscribeToRepo, subscribeToRepo, subscribeToBranch);
   }
 
+  protected Project.NameKey nameKey(String s) {
+    return new Project.NameKey(name(s));
+  }
+
   protected void prepareSubmoduleConfigEntry(
       Config config, String subscribeToRepo, String subscribeToRepoPath, String subscribeToBranch) {
-    subscribeToRepo = name(subscribeToRepo);
-    subscribeToRepoPath = name(subscribeToRepoPath);
+    prepareSubmoduleConfigEntry(
+        config, nameKey(subscribeToRepo), nameKey(subscribeToRepoPath), subscribeToBranch);
+  }
+
+  protected void prepareSubmoduleConfigEntry(
+      Config config,
+      Project.NameKey subscribeToRepo,
+      Project.NameKey subscribeToRepoPath,
+      String subscribeToBranch) {
     // The submodule subscription module checks for gerrit.canonicalWebUrl to
     // detect if it's configured for automatic updates. It doesn't matter if
     // it serves from that URL.
     String url = cfg.getString("gerrit", null, "canonicalWebUrl") + "/" + subscribeToRepo;
-    config.setString("submodule", subscribeToRepoPath, "path", subscribeToRepoPath);
-    config.setString("submodule", subscribeToRepoPath, "url", url);
+    config.setString("submodule", subscribeToRepoPath.get(), "path", subscribeToRepoPath.get());
+    config.setString("submodule", subscribeToRepoPath.get(), "url", url);
     if (subscribeToBranch != null) {
-      config.setString("submodule", subscribeToRepoPath, "branch", subscribeToBranch);
+      config.setString("submodule", subscribeToRepoPath.get(), "branch", subscribeToBranch);
     }
   }
 
@@ -302,8 +371,17 @@
       TestRepository<?> subRepo,
       String subBranch)
       throws Exception {
+    expectToHaveSubmoduleState(repo, branch, nameKey(submodule), subRepo, subBranch);
+  }
 
-    submodule = name(submodule);
+  protected void expectToHaveSubmoduleState(
+      TestRepository<?> repo,
+      String branch,
+      Project.NameKey submodule,
+      TestRepository<?> subRepo,
+      String subBranch)
+      throws Exception {
+
     ObjectId commitId =
         repo.git()
             .fetch()
@@ -326,7 +404,7 @@
     rw.parseBody(c.getTree());
 
     RevTree tree = c.getTree();
-    RevObject actualId = repo.get(tree, submodule);
+    RevObject actualId = repo.get(tree, submodule.get());
 
     assertThat(actualId).isEqualTo(subHead);
   }
@@ -334,8 +412,12 @@
   protected void expectToHaveSubmoduleState(
       TestRepository<?> repo, String branch, String submodule, ObjectId expectedId)
       throws Exception {
+    expectToHaveSubmoduleState(repo, branch, nameKey(submodule), expectedId);
+  }
 
-    submodule = name(submodule);
+  protected void expectToHaveSubmoduleState(
+      TestRepository<?> repo, String branch, Project.NameKey submodule, ObjectId expectedId)
+      throws Exception {
     ObjectId commitId =
         repo.git()
             .fetch()
@@ -349,7 +431,7 @@
     rw.parseBody(c.getTree());
 
     RevTree tree = c.getTree();
-    RevObject actualId = repo.get(tree, submodule);
+    RevObject actualId = repo.get(tree, submodule.get());
 
     assertThat(actualId).isEqualTo(expectedId);
   }
@@ -410,8 +492,11 @@
 
   protected boolean hasSubmodule(TestRepository<?> repo, String branch, String submodule)
       throws Exception {
+    return hasSubmodule(repo, branch, new Project.NameKey(name(submodule)));
+  }
 
-    submodule = name(submodule);
+  protected boolean hasSubmodule(TestRepository<?> repo, String branch, Project.NameKey submodule)
+      throws Exception {
     Ref branchTip =
         repo.git().fetch().setRemote("origin").call().getAdvertisedRef("refs/heads/" + branch);
     if (branchTip == null) {
@@ -426,7 +511,7 @@
 
     RevTree tree = c.getTree();
     try {
-      repo.get(tree, submodule);
+      repo.get(tree, submodule.get());
       return true;
     } catch (AssertionError e) {
       return false;
@@ -446,7 +531,8 @@
 
     RevWalk rw = repo.getRevWalk();
     RevCommit c = rw.parseCommit(commitId);
-    assertThat(c.getFullMessage()).isEqualTo(expectedMessage);
+    String msg = c.getFullMessage();
+    assertThat(msg).isEqualTo(expectedMessage);
   }
 
   protected PersonIdent getAuthor(TestRepository<?> repo, String branch) throws Exception {
@@ -465,8 +551,13 @@
 
   protected void directUpdateSubmodule(String project, String refName, String path, AnyObjectId id)
       throws Exception {
-    path = name(path);
-    try (Repository serverRepo = repoManager.openRepository(new Project.NameKey(name(project)));
+    directUpdateSubmodule(nameKey(project), refName, nameKey(path), id);
+  }
+
+  protected void directUpdateSubmodule(
+      Project.NameKey project, String refName, Project.NameKey path, AnyObjectId id)
+      throws Exception {
+    try (Repository serverRepo = repoManager.openRepository(project);
         ObjectInserter ins = serverRepo.newObjectInserter();
         RevWalk rw = new RevWalk(serverRepo)) {
       Ref ref = serverRepo.exactRef(refName);
@@ -480,7 +571,7 @@
       b.finish();
       DirCacheEditor e = dc.editor();
       e.add(
-          new PathEdit(path) {
+          new PathEdit(path.get()) {
             @Override
             public void apply(DirCacheEntry ent) {
               ent.setFileMode(FileMode.GITLINK);
diff --git a/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsIT.java b/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsIT.java
index 03b1165..d76b310 100644
--- a/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsIT.java
@@ -25,6 +25,7 @@
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.testing.ConfigSuite;
 import com.google.gerrit.testing.TestTimeUtil;
+import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
 import org.eclipse.jgit.junit.TestRepository;
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.ObjectId;
@@ -47,198 +48,169 @@
   @Test
   @GerritConfig(name = "submodule.enableSuperProjectSubscriptions", value = "false")
   public void testSubscriptionWithoutGlobalServerSetting() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/master", "super-project", "refs/heads/master");
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
 
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
     pushChangeTo(subRepo, "master");
-    assertThat(hasSubmodule(superRepo, "master", "subscribed-to-project")).isFalse();
+    assertThat(hasSubmodule(superRepo, "master", subKey)).isFalse();
   }
 
   @Test
   public void subscriptionWithoutSpecificSubscription() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
-
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
     pushChangeTo(subRepo, "master");
-    assertThat(hasSubmodule(superRepo, "master", "subscribed-to-project")).isFalse();
+    assertThat(hasSubmodule(superRepo, "master", subKey)).isFalse();
   }
 
   @Test
   public void subscriptionToEmptyRepo() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/master", "super-project", "refs/heads/master");
 
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
+
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
     pushChangeTo(subRepo, "master");
     ObjectId subHEAD = pushChangeTo(subRepo, "master");
-    assertThat(hasSubmodule(superRepo, "master", "subscribed-to-project")).isTrue();
-    expectToHaveSubmoduleState(superRepo, "master", "subscribed-to-project", subHEAD);
+    assertThat(hasSubmodule(superRepo, "master", subKey)).isTrue();
+    expectToHaveSubmoduleState(superRepo, "master", subKey, subHEAD);
   }
 
   @Test
   public void subscriptionToExistingRepo() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/master", "super-project", "refs/heads/master");
+
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
 
     pushChangeTo(subRepo, "master");
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
     ObjectId subHEAD = pushChangeTo(subRepo, "master");
-    assertThat(hasSubmodule(superRepo, "master", "subscribed-to-project")).isTrue();
-    expectToHaveSubmoduleState(superRepo, "master", "subscribed-to-project", subHEAD);
+    assertThat(hasSubmodule(superRepo, "master", subKey)).isTrue();
+    expectToHaveSubmoduleState(superRepo, "master", subKey, subHEAD);
   }
 
   @Test
   public void subscriptionWildcardACLForSingleBranch() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
+
     // master is allowed to be subscribed to master branch only:
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/master", "super-project", null);
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, null);
     // create 'branch':
     pushChangeTo(superRepo, "branch");
 
     pushChangeTo(subRepo, "master");
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
-    createSubmoduleSubscription(superRepo, "branch", "subscribed-to-project", "master");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
+    createSubmoduleSubscription(superRepo, "branch", subKey, "master");
 
     ObjectId subHEAD = pushChangeTo(subRepo, "master");
 
-    expectToHaveSubmoduleState(superRepo, "master", "subscribed-to-project", subHEAD);
-    assertThat(hasSubmodule(superRepo, "branch", "subscribed-to-project")).isFalse();
+    expectToHaveSubmoduleState(superRepo, "master", subKey, subHEAD);
+    assertThat(hasSubmodule(superRepo, "branch", subKey)).isFalse();
   }
 
   @Test
   public void subscriptionWildcardACLForMissingProject() throws Exception {
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
+
     allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/*", "not-existing-super-project", "refs/heads/*");
+        subKey, "refs/heads/*", new Project.NameKey("not-existing-super-project"), "refs/heads/*");
     pushChangeTo(subRepo, "master");
   }
 
   @Test
   public void subscriptionWildcardACLForMissingBranch() throws Exception {
-    createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/*", "super-project", "refs/heads/*");
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/*", superKey, "refs/heads/*");
     pushChangeTo(subRepo, "foo");
   }
 
   @Test
   public void subscriptionWildcardACLForMissingGitmodules() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/*", "super-project", "refs/heads/*");
+
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/*", superKey, "refs/heads/*");
     pushChangeTo(superRepo, "master");
     pushChangeTo(subRepo, "master");
   }
 
   @Test
   public void subscriptionWildcardACLOneOnOneMapping() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
+
     // any branch is allowed to be subscribed to the same superprojects branch:
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/*", "super-project", "refs/heads/*");
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/*", superKey, "refs/heads/*");
 
     // create 'branch' in both repos:
     pushChangeTo(superRepo, "branch");
     pushChangeTo(subRepo, "branch");
 
     pushChangeTo(subRepo, "master");
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
-    createSubmoduleSubscription(superRepo, "branch", "subscribed-to-project", "branch");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
+    createSubmoduleSubscription(superRepo, "branch", subKey, "branch");
 
     ObjectId subHEAD1 = pushChangeTo(subRepo, "master");
     ObjectId subHEAD2 = pushChangeTo(subRepo, "branch");
 
-    expectToHaveSubmoduleState(superRepo, "master", "subscribed-to-project", subHEAD1);
-    expectToHaveSubmoduleState(superRepo, "branch", "subscribed-to-project", subHEAD2);
+    expectToHaveSubmoduleState(superRepo, "master", subKey, subHEAD1);
+    expectToHaveSubmoduleState(superRepo, "branch", subKey, subHEAD2);
 
     // Now test that cross subscriptions do not work:
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "branch");
+    createSubmoduleSubscription(superRepo, "master", subKey, "branch");
     ObjectId subHEAD3 = pushChangeTo(subRepo, "branch");
 
-    expectToHaveSubmoduleState(superRepo, "master", "subscribed-to-project", subHEAD1);
-    expectToHaveSubmoduleState(superRepo, "branch", "subscribed-to-project", subHEAD3);
+    expectToHaveSubmoduleState(superRepo, "master", subKey, subHEAD1);
+    expectToHaveSubmoduleState(superRepo, "branch", subKey, subHEAD3);
   }
 
   @Test
   public void subscriptionWildcardACLForManyBranches() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
 
     // Any branch is allowed to be subscribed to any superproject branch:
-    allowSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/*", "super-project", null, false);
+    allowSubmoduleSubscription(subKey, "refs/heads/*", superKey, null, false);
     pushChangeTo(superRepo, "branch");
     pushChangeTo(subRepo, "another-branch");
-    createSubmoduleSubscription(superRepo, "branch", "subscribed-to-project", "another-branch");
+    createSubmoduleSubscription(superRepo, "branch", subKey, "another-branch");
     ObjectId subHEAD = pushChangeTo(subRepo, "another-branch");
-    expectToHaveSubmoduleState(superRepo, "branch", "subscribed-to-project", subHEAD);
+    expectToHaveSubmoduleState(superRepo, "branch", subKey, subHEAD);
   }
 
   @Test
   public void subscriptionWildcardACLOneToManyBranches() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
 
     // Any branch is allowed to be subscribed to any superproject branch:
-    allowSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/master", "super-project", "refs/heads/*", false);
+    allowSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/*", false);
     pushChangeTo(superRepo, "branch");
-    createSubmoduleSubscription(superRepo, "branch", "subscribed-to-project", "master");
+    createSubmoduleSubscription(superRepo, "branch", subKey, "master");
     ObjectId subHEAD = pushChangeTo(subRepo, "master");
-    expectToHaveSubmoduleState(superRepo, "branch", "subscribed-to-project", subHEAD);
+    expectToHaveSubmoduleState(superRepo, "branch", subKey, subHEAD);
 
-    createSubmoduleSubscription(superRepo, "branch", "subscribed-to-project", "branch");
+    createSubmoduleSubscription(superRepo, "branch", subKey, "branch");
     pushChangeTo(subRepo, "branch");
 
     // no change expected, as only master is subscribed:
-    expectToHaveSubmoduleState(superRepo, "branch", "subscribed-to-project", subHEAD);
+    expectToHaveSubmoduleState(superRepo, "branch", subKey, subHEAD);
   }
 
   @Test
   @GerritConfig(name = "submodule.verboseSuperprojectUpdate", value = "false")
   public void testSubmoduleShortCommitMessage() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/master", "super-project", "refs/heads/master");
+
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
 
     pushChangeTo(subRepo, "master");
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
 
     // The first update doesn't include any commit messages
     ObjectId subRepoId = pushChangeTo(subRepo, "master");
-    expectToHaveSubmoduleState(superRepo, "master", "subscribed-to-project", subRepoId);
+    expectToHaveSubmoduleState(superRepo, "master", subKey, subRepoId);
     expectToHaveCommitMessage(superRepo, "master", "Update git submodules\n\n");
 
     // Any following update also has a short message
     subRepoId = pushChangeTo(subRepo, "master");
-    expectToHaveSubmoduleState(superRepo, "master", "subscribed-to-project", subRepoId);
+    expectToHaveSubmoduleState(superRepo, "master", subKey, subRepoId);
     expectToHaveCommitMessage(superRepo, "master", "Update git submodules\n\n");
   }
 
   @Test
   @GerritConfig(name = "submodule.verboseSuperprojectUpdate", value = "SUBJECT_ONLY")
   public void testSubmoduleSubjectCommitMessage() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/master", "super-project", "refs/heads/master");
+
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
 
     pushChangeTo(subRepo, "master");
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
     ObjectId subHEAD = pushChangeTo(subRepo, "master");
 
     // The first update doesn't include the rev log
@@ -248,7 +220,7 @@
         "master",
         "Update git submodules\n\n"
             + "* Update "
-            + name("subscribed-to-project")
+            + subKey.get()
             + " from branch 'master'\n  to "
             + subHEAD.getName());
 
@@ -261,7 +233,7 @@
         "master",
         "Update git submodules\n\n"
             + "* Update "
-            + name("subscribed-to-project")
+            + subKey.get()
             + " from branch 'master'\n  to "
             + subHEAD.getName()
             + "\n  - "
@@ -270,13 +242,11 @@
 
   @Test
   public void submoduleCommitMessage() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/master", "super-project", "refs/heads/master");
+
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
 
     pushChangeTo(subRepo, "master");
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
     ObjectId subHEAD = pushChangeTo(subRepo, "master");
 
     // The first update doesn't include the rev log
@@ -286,7 +256,7 @@
         "master",
         "Update git submodules\n\n"
             + "* Update "
-            + name("subscribed-to-project")
+            + subKey.get()
             + " from branch 'master'\n  to "
             + subHEAD.getName());
 
@@ -299,7 +269,7 @@
         "master",
         "Update git submodules\n\n"
             + "* Update "
-            + name("subscribed-to-project")
+            + subKey.get()
             + " from branch 'master'\n  to "
             + subHEAD.getName()
             + "\n  - "
@@ -308,171 +278,151 @@
 
   @Test
   public void subscriptionUnsubscribe() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/master", "super-project", "refs/heads/master");
+
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
 
     pushChangeTo(subRepo, "master");
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
 
     pushChangeTo(subRepo, "master");
     ObjectId subHEADbeforeUnsubscribing = pushChangeTo(subRepo, "master");
 
     deleteAllSubscriptions(superRepo, "master");
-    expectToHaveSubmoduleState(
-        superRepo, "master", "subscribed-to-project", subHEADbeforeUnsubscribing);
+    expectToHaveSubmoduleState(superRepo, "master", subKey, subHEADbeforeUnsubscribing);
 
     pushChangeTo(superRepo, "refs/heads/master", "commit after unsubscribe", "");
     pushChangeTo(subRepo, "refs/heads/master", "commit after unsubscribe", "");
-    expectToHaveSubmoduleState(
-        superRepo, "master", "subscribed-to-project", subHEADbeforeUnsubscribing);
+    expectToHaveSubmoduleState(superRepo, "master", subKey, subHEADbeforeUnsubscribing);
   }
 
   @Test
   public void subscriptionUnsubscribeByDeletingGitModules() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/master", "super-project", "refs/heads/master");
+
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
 
     pushChangeTo(subRepo, "master");
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
 
     pushChangeTo(subRepo, "master");
     ObjectId subHEADbeforeUnsubscribing = pushChangeTo(subRepo, "master");
 
     deleteGitModulesFile(superRepo, "master");
-    expectToHaveSubmoduleState(
-        superRepo, "master", "subscribed-to-project", subHEADbeforeUnsubscribing);
+    expectToHaveSubmoduleState(superRepo, "master", subKey, subHEADbeforeUnsubscribing);
 
     pushChangeTo(superRepo, "refs/heads/master", "commit after unsubscribe", "");
     pushChangeTo(subRepo, "refs/heads/master", "commit after unsubscribe", "");
-    expectToHaveSubmoduleState(
-        superRepo, "master", "subscribed-to-project", subHEADbeforeUnsubscribing);
+    expectToHaveSubmoduleState(superRepo, "master", subKey, subHEADbeforeUnsubscribing);
   }
 
   @Test
   public void subscriptionToDifferentBranches() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/foo", "super-project", "refs/heads/master");
 
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "foo");
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/foo", superKey, "refs/heads/master");
+
+    createSubmoduleSubscription(superRepo, "master", subKey, "foo");
     ObjectId subFoo = pushChangeTo(subRepo, "foo");
     pushChangeTo(subRepo, "master");
 
-    expectToHaveSubmoduleState(superRepo, "master", "subscribed-to-project", subFoo);
+    expectToHaveSubmoduleState(superRepo, "master", subKey, subFoo);
   }
 
   @Test
   public void branchCircularSubscription() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/master", "super-project", "refs/heads/master");
-    allowMatchingSubmoduleSubscription(
-        "super-project", "refs/heads/master", "subscribed-to-project", "refs/heads/master");
+
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
+    allowMatchingSubmoduleSubscription(superKey, "refs/heads/master", subKey, "refs/heads/master");
 
     pushChangeTo(subRepo, "master");
     pushChangeTo(superRepo, "master");
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
-    createSubmoduleSubscription(subRepo, "master", "super-project", "master");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
+    createSubmoduleSubscription(subRepo, "master", superKey, "master");
 
     pushChangeTo(subRepo, "master");
     pushChangeTo(superRepo, "master");
 
-    assertThat(hasSubmodule(subRepo, "master", "super-project")).isFalse();
-    assertThat(hasSubmodule(superRepo, "master", "subscribed-to-project")).isFalse();
+    assertThat(hasSubmodule(subRepo, "master", superKey)).isFalse();
+    assertThat(hasSubmodule(superRepo, "master", subKey)).isFalse();
   }
 
   @Test
   public void projectCircularSubscription() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
 
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/master", "super-project", "refs/heads/master");
-    allowMatchingSubmoduleSubscription(
-        "super-project", "refs/heads/dev", "subscribed-to-project", "refs/heads/dev");
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
+    allowMatchingSubmoduleSubscription(superKey, "refs/heads/dev", subKey, "refs/heads/dev");
 
     pushChangeTo(subRepo, "master");
     pushChangeTo(superRepo, "master");
     pushChangeTo(subRepo, "dev");
     pushChangeTo(superRepo, "dev");
 
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
-    createSubmoduleSubscription(subRepo, "dev", "super-project", "dev");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
+    createSubmoduleSubscription(subRepo, "dev", superKey, "dev");
 
     ObjectId subMasterHead = pushChangeTo(subRepo, "master");
     ObjectId superDevHead = pushChangeTo(superRepo, "dev");
 
-    assertThat(hasSubmodule(superRepo, "master", "subscribed-to-project")).isTrue();
-    assertThat(hasSubmodule(subRepo, "dev", "super-project")).isTrue();
-    expectToHaveSubmoduleState(superRepo, "master", "subscribed-to-project", subMasterHead);
-    expectToHaveSubmoduleState(subRepo, "dev", "super-project", superDevHead);
+    assertThat(hasSubmodule(superRepo, "master", subKey)).isTrue();
+    assertThat(hasSubmodule(subRepo, "dev", superKey)).isTrue();
+    expectToHaveSubmoduleState(superRepo, "master", subKey, subMasterHead);
+    expectToHaveSubmoduleState(subRepo, "dev", superKey, superDevHead);
   }
 
   @Test
   public void subscriptionFailOnMissingACL() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
 
     pushChangeTo(subRepo, "master");
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
     pushChangeTo(subRepo, "master");
-    assertThat(hasSubmodule(superRepo, "master", "subscribed-to-project")).isFalse();
+    assertThat(hasSubmodule(superRepo, "master", subKey)).isFalse();
   }
 
   @Test
   public void subscriptionFailOnWrongProjectACL() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
     allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/master", "wrong-super-project", "refs/heads/master");
+        subKey,
+        "refs/heads/master",
+        new Project.NameKey("wrong-super-project"),
+        "refs/heads/master");
 
     pushChangeTo(subRepo, "master");
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
     pushChangeTo(subRepo, "master");
-    assertThat(hasSubmodule(superRepo, "master", "subscribed-to-project")).isFalse();
+    assertThat(hasSubmodule(superRepo, "master", subKey)).isFalse();
   }
 
   @Test
   public void subscriptionFailOnWrongBranchACL() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
     allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/master", "super-project", "refs/heads/wrong-branch");
+        subKey, "refs/heads/master", superKey, "refs/heads/wrong-branch");
 
     pushChangeTo(subRepo, "master");
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
     pushChangeTo(subRepo, "master");
-    assertThat(hasSubmodule(superRepo, "master", "subscribed-to-project")).isFalse();
+    assertThat(hasSubmodule(superRepo, "master", subKey)).isFalse();
   }
 
   @Test
   public void subscriptionInheritACL() throws Exception {
-    createProjectWithPush("config-repo");
-    createProjectWithPush("config-repo2", new Project.NameKey(name("config-repo")));
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo =
-        createProjectWithPush("subscribed-to-project", new Project.NameKey(name("config-repo2")));
-    allowMatchingSubmoduleSubscription(
-        "config-repo", "refs/heads/*", "super-project", "refs/heads/*");
+    Project.NameKey configKey = createProjectForPush("config-repo", null, true, getSubmitType());
+    Project.NameKey config2Key =
+        createProjectForPush("config-repo2", configKey, true, getSubmitType());
+    cloneProject(config2Key);
+
+    subKey = createProjectForPush("subrepo", config2Key, true, getSubmitType());
+    subRepo = cloneProject(subKey);
+
+    allowMatchingSubmoduleSubscription(configKey, "refs/heads/*", superKey, "refs/heads/*");
 
     pushChangeTo(subRepo, "master");
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
     ObjectId subHEAD = pushChangeTo(subRepo, "master");
-    expectToHaveSubmoduleState(superRepo, "master", "subscribed-to-project", subHEAD);
+    expectToHaveSubmoduleState(superRepo, "master", subKey, subHEAD);
   }
 
   @Test
   public void allowedButNotSubscribed() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/master", "super-project", "refs/heads/master");
+
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
 
     pushChangeTo(subRepo, "master");
     subRepo
@@ -490,16 +440,16 @@
     assertThat(r.getRemoteUpdate("refs/heads/master").getStatus())
         .isEqualTo(RemoteRefUpdate.Status.OK);
 
-    assertThat(hasSubmodule(superRepo, "master", "subscribed-to-project")).isFalse();
+    assertThat(hasSubmodule(superRepo, "master", subKey)).isFalse();
   }
 
   @Test
   public void subscriptionDeepRelative() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("nested/subscribed-to-project");
+    Project.NameKey nest =
+        createProjectForPush("nested/subscribed-to-project", null, true, getSubmitType());
+    TestRepository<?> subRepo = cloneProject(nest);
     // master is allowed to be subscribed to any superprojects branch:
-    allowMatchingSubmoduleSubscription(
-        "nested/subscribed-to-project", "refs/heads/master", "super-project", null);
+    allowMatchingSubmoduleSubscription(nest, "refs/heads/master", superKey, null);
 
     pushChangeTo(subRepo, "master");
     createRelativeSubmoduleSubscription(
@@ -519,7 +469,9 @@
 
   @Test
   @GerritConfig(name = "submodule.verboseSuperprojectUpdate", value = "SUBJECT_ONLY")
-  @GerritConfig(name = "submodule.maxCombinedCommitMessageSize", value = "220")
+  // The value 195 must tuned to the test environment, and is sensitive to the
+  // length of the uniquified repository name.
+  @GerritConfig(name = "submodule.maxCombinedCommitMessageSize", value = "200")
   public void submoduleSubjectCommitMessageSizeLimit() throws Exception {
     assume().that(isSubmitWholeTopicEnabled()).isFalse();
     testSubmoduleSubjectCommitMessageAndExpectTruncation();
@@ -530,11 +482,10 @@
     // Make sure that the commit is created at an earlier timestamp than the submit timestamp.
     TestTimeUtil.resetWithClockStep(1, SECONDS);
     try {
-      TestRepository<?> superRepo = createProjectWithPush("super-project");
-      TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
+
       allowMatchingSubmoduleSubscription(
-          "subscribed-to-project", "refs/heads/master", "super-project", "refs/heads/master");
-      createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
+          subKey, "refs/heads/master", superKey, "refs/heads/master");
+      createSubmoduleSubscription(superRepo, "master", subKey, "master");
 
       PushOneCommit.Result pushResult =
           createChange(subRepo, "refs/heads/master", "Change", "a.txt", "some content", null);
@@ -561,18 +512,18 @@
     // is afterwards.
     TestTimeUtil.resetWithClockStep(1, SECONDS);
     try {
-      TestRepository<?> superRepo = createProjectWithPush("super-project");
-      TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
-      TestRepository<?> subRepo2 = createProjectWithPush("subscribed-to-project-2");
 
+      Project.NameKey proj2 =
+          createProjectForPush("subscribed-to-project-2", null, true, getSubmitType());
+
+      TestRepository<?> subRepo2 = cloneProject(proj2);
       allowMatchingSubmoduleSubscription(
-          "subscribed-to-project", "refs/heads/master", "super-project", "refs/heads/master");
-      allowMatchingSubmoduleSubscription(
-          "subscribed-to-project-2", "refs/heads/master", "super-project", "refs/heads/master");
+          subKey, "refs/heads/master", superKey, "refs/heads/master");
+      allowMatchingSubmoduleSubscription(proj2, "refs/heads/master", superKey, "refs/heads/master");
 
       Config config = new Config();
-      prepareSubmoduleConfigEntry(config, "subscribed-to-project", "master");
-      prepareSubmoduleConfigEntry(config, "subscribed-to-project-2", "master");
+      prepareSubmoduleConfigEntry(config, subKey, subKey, "master");
+      prepareSubmoduleConfigEntry(config, proj2, proj2, "master");
       pushSubmoduleConfig(superRepo, "master", config);
 
       String topic = "foo";
@@ -610,21 +561,17 @@
     // is afterwards.
     TestTimeUtil.resetWithClockStep(1, SECONDS);
     try {
-      TestRepository<?> superRepo = createProjectWithPush("super-project");
-      TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
-
-      createProjectWithPush("subscribed-to-project-2");
-      TestRepository<?> subRepo2 =
-          cloneProject(new Project.NameKey(name("subscribed-to-project-2")), user);
+      Project.NameKey proj2 =
+          createProjectForPush("subscribed-to-project-2", null, true, getSubmitType());
+      TestRepository<InMemoryRepository> repo2 = cloneProject(proj2, user);
 
       allowMatchingSubmoduleSubscription(
-          "subscribed-to-project", "refs/heads/master", "super-project", "refs/heads/master");
-      allowMatchingSubmoduleSubscription(
-          "subscribed-to-project-2", "refs/heads/master", "super-project", "refs/heads/master");
+          subKey, "refs/heads/master", superKey, "refs/heads/master");
+      allowMatchingSubmoduleSubscription(proj2, "refs/heads/master", superKey, "refs/heads/master");
 
       Config config = new Config();
-      prepareSubmoduleConfigEntry(config, "subscribed-to-project", "master");
-      prepareSubmoduleConfigEntry(config, "subscribed-to-project-2", "master");
+      prepareSubmoduleConfigEntry(config, subKey, subKey, "master");
+      prepareSubmoduleConfigEntry(config, proj2, proj2, "master");
       pushSubmoduleConfig(superRepo, "master", config);
 
       String topic = "foo";
@@ -636,7 +583,7 @@
 
       // Create change as user.
       PushOneCommit push =
-          pushFactory.create(db, user.getIdent(), subRepo2, "Change 2", "b.txt", "other content");
+          pushFactory.create(db, user.getIdent(), repo2, "Change 2", "b.txt", "other content");
       PushOneCommit.Result pushResult2 = push.to("refs/for/master/" + name(topic));
       approve(pushResult2.getChangeId());
 
@@ -659,14 +606,15 @@
 
   @Test
   public void updateOnlyRelevantSubmodules() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo1 = createProjectWithPush("subscribed-to-project-1");
-    TestRepository<?> subRepo2 = createProjectWithPush("subscribed-to-project-2");
+    Project.NameKey subkey1 =
+        createProjectForPush("subscribed-to-project-1", null, true, getSubmitType());
+    Project.NameKey subkey2 =
+        createProjectForPush("subscribed-to-project-2", null, true, getSubmitType());
+    TestRepository<?> subRepo1 = cloneProject(subkey1);
+    TestRepository<?> subRepo2 = cloneProject(subkey2);
 
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project-1", "refs/heads/master", "super-project", "refs/heads/master");
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project-2", "refs/heads/master", "super-project", "refs/heads/master");
+    allowMatchingSubmoduleSubscription(subkey1, "refs/heads/master", superKey, "refs/heads/master");
+    allowMatchingSubmoduleSubscription(subkey2, "refs/heads/master", superKey, "refs/heads/master");
 
     Config config = new Config();
     prepareSubmoduleConfigEntry(config, "subscribed-to-project-1", "master");
@@ -689,41 +637,35 @@
 
   @Test
   public void skipUpdatingBrokenGitlinkPointer() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
 
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/master", "super-project", "refs/heads/master");
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
 
     // Push once to initialize submodule.
     ObjectId subTip = pushChangeTo(subRepo, "master");
-    expectToHaveSubmoduleState(superRepo, "master", "subscribed-to-project", subTip);
+    expectToHaveSubmoduleState(superRepo, "master", subKey, subTip);
 
     // Write an invalid SHA-1 directly to the gitlink.
     ObjectId badId = ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
-    directUpdateSubmodule("super-project", "refs/heads/master", "subscribed-to-project", badId);
-    expectToHaveSubmoduleState(superRepo, "master", "subscribed-to-project", badId);
+    directUpdateSubmodule(superKey, "refs/heads/master", subKey, badId);
+    expectToHaveSubmoduleState(superRepo, "master", subKey, badId);
 
     // Push succeeds, but gitlink update is skipped.
     pushChangeTo(subRepo, "master");
-    expectToHaveSubmoduleState(superRepo, "master", "subscribed-to-project", badId);
+    expectToHaveSubmoduleState(superRepo, "master", subKey, badId);
   }
 
   private ObjectId directUpdateRef(String project, String ref) throws Exception {
-    try (Repository serverRepo = repoManager.openRepository(new Project.NameKey(name(project)))) {
+    try (Repository serverRepo = repoManager.openRepository(nameKey(project))) {
       return new TestRepository<>(serverRepo).branch(ref).commit().create().copy();
     }
   }
 
   private void testSubmoduleSubjectCommitMessageAndExpectTruncation() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/master", "super-project", "refs/heads/master");
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
 
     pushChangeTo(subRepo, "master");
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
     // The first update doesn't include the rev log, so we ignore it
     pushChangeTo(subRepo, "master");
 
@@ -736,6 +678,6 @@
         "master",
         String.format(
             "Update git submodules\n\n* Update %s from branch 'master'\n  to %s\n  - %s\n\n[...]",
-            name("subscribed-to-project"), subHEAD.getName(), subCommitMsg.getShortMessage()));
+            subKey.get(), subHEAD.getName(), subCommitMsg.getShortMessage()));
   }
 }
diff --git a/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsWholeTopicMergeIT.java b/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsWholeTopicMergeIT.java
index eef3295..0b583bf 100644
--- a/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsWholeTopicMergeIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsWholeTopicMergeIT.java
@@ -68,12 +68,8 @@
 
   @Test
   public void subscriptionUpdateOfManyChanges() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/master", "super-project", "refs/heads/master");
-
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
 
     ObjectId subHEAD =
         subRepo
@@ -150,15 +146,13 @@
             .getAdvertisedRef("refs/heads/master")
             .getObjectId();
 
-    expectToHaveSubmoduleState(superRepo, "master", "subscribed-to-project", subRepoId);
+    expectToHaveSubmoduleState(superRepo, "master", subKey, subRepoId);
 
     // As the submodules have changed commits, the superproject tree will be
     // different, so we cannot directly compare the trees here, so make
     // assumptions only about the changed branches:
-    Project.NameKey p1 = new Project.NameKey(name("super-project"));
-    Project.NameKey p2 = new Project.NameKey(name("subscribed-to-project"));
-    assertThat(preview).containsKey(new Branch.NameKey(p1, "refs/heads/master"));
-    assertThat(preview).containsKey(new Branch.NameKey(p2, "refs/heads/master"));
+    assertThat(preview).containsKey(new Branch.NameKey(superKey, "refs/heads/master"));
+    assertThat(preview).containsKey(new Branch.NameKey(subKey, "refs/heads/master"));
 
     if ((getSubmitType() == SubmitType.CHERRY_PICK)
         || (getSubmitType() == SubmitType.REBASE_ALWAYS)) {
@@ -176,12 +170,9 @@
 
   @Test
   public void subscriptionUpdateIncludingChangeInSuperproject() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/master", "super-project", "refs/heads/master");
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
 
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
 
     ObjectId subHEAD =
         subRepo
@@ -274,27 +265,27 @@
             .getAdvertisedRef("refs/heads/master")
             .getObjectId();
 
-    expectToHaveSubmoduleState(superRepo, "master", "subscribed-to-project", subRepoId);
+    expectToHaveSubmoduleState(superRepo, "master", subKey, subRepoId);
   }
 
   @Test
   public void updateManySubmodules() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> sub1 = createProjectWithPush("sub1");
-    TestRepository<?> sub2 = createProjectWithPush("sub2");
-    TestRepository<?> sub3 = createProjectWithPush("sub3");
+    Project.NameKey subKey1 = createProjectForPush("sub1", null, true, getSubmitType());
+    Project.NameKey subKey2 = createProjectForPush("sub2", null, true, getSubmitType());
+    Project.NameKey subKey3 = createProjectForPush("sub3", null, true, getSubmitType());
 
-    allowMatchingSubmoduleSubscription(
-        "sub1", "refs/heads/master", "super-project", "refs/heads/master");
-    allowMatchingSubmoduleSubscription(
-        "sub2", "refs/heads/master", "super-project", "refs/heads/master");
-    allowMatchingSubmoduleSubscription(
-        "sub3", "refs/heads/master", "super-project", "refs/heads/master");
+    TestRepository<?> sub1 = cloneProject(subKey1);
+    TestRepository<?> sub2 = cloneProject(subKey2);
+    TestRepository<?> sub3 = cloneProject(subKey3);
+
+    allowMatchingSubmoduleSubscription(subKey1, "refs/heads/master", superKey, "refs/heads/master");
+    allowMatchingSubmoduleSubscription(subKey2, "refs/heads/master", superKey, "refs/heads/master");
+    allowMatchingSubmoduleSubscription(subKey3, "refs/heads/master", superKey, "refs/heads/master");
 
     Config config = new Config();
-    prepareSubmoduleConfigEntry(config, "sub1", "master");
-    prepareSubmoduleConfigEntry(config, "sub2", "master");
-    prepareSubmoduleConfigEntry(config, "sub3", "master");
+    prepareSubmoduleConfigEntry(config, subKey1, "master");
+    prepareSubmoduleConfigEntry(config, subKey2, "master");
+    prepareSubmoduleConfigEntry(config, subKey3, "master");
     pushSubmoduleConfig(superRepo, "master", config);
 
     ObjectId superPreviousId = pushChangeTo(superRepo, "master");
@@ -309,9 +300,9 @@
 
     gApi.changes().id(getChangeId(sub1, sub1Id).get()).current().submit();
 
-    expectToHaveSubmoduleState(superRepo, "master", "sub1", sub1, "master");
-    expectToHaveSubmoduleState(superRepo, "master", "sub2", sub2, "master");
-    expectToHaveSubmoduleState(superRepo, "master", "sub3", sub3, "master");
+    expectToHaveSubmoduleState(superRepo, "master", subKey1, sub1, "master");
+    expectToHaveSubmoduleState(superRepo, "master", subKey2, sub2, "master");
+    expectToHaveSubmoduleState(superRepo, "master", subKey3, sub3, "master");
 
     String sub1HEAD =
         sub1.git()
@@ -346,15 +337,15 @@
           "master",
           "Update git submodules\n\n"
               + "* Update "
-              + name("sub1")
+              + subKey1.get()
               + " from branch 'master'\n  to "
               + sub1HEAD
               + "\n\n* Update "
-              + name("sub2")
+              + subKey2.get()
               + " from branch 'master'\n  to "
               + sub2HEAD
               + "\n\n* Update "
-              + name("sub3")
+              + subKey3.get()
               + " from branch 'master'\n  to "
               + sub3HEAD);
     }
@@ -374,73 +365,74 @@
 
   @Test
   public void doNotUseFastForward() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project", false);
-    TestRepository<?> sub = createProjectWithPush("sub", false);
+    // like setup, but without empty commit
+    superKey = createProjectForPush("super-nc", null, false, getSubmitType());
+    subKey = createProjectForPush("sub-nc", null, false, getSubmitType());
+    superRepo = cloneProject(superKey);
+    subRepo = cloneProject(subKey);
 
-    allowMatchingSubmoduleSubscription(
-        "sub", "refs/heads/master", "super-project", "refs/heads/master");
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
 
-    createSubmoduleSubscription(superRepo, "master", "sub", "master");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
 
-    ObjectId subId = pushChangeTo(sub, "refs/for/master", "some message", "same-topic");
+    ObjectId subId = pushChangeTo(subRepo, "refs/for/master", "some message", "same-topic");
 
     ObjectId superId = pushChangeTo(superRepo, "refs/for/master", "some message", "same-topic");
 
-    String subChangeId = getChangeId(sub, subId).get();
+    String subChangeId = getChangeId(subRepo, subId).get();
     approve(subChangeId);
     approve(getChangeId(superRepo, superId).get());
 
     gApi.changes().id(subChangeId).current().submit();
 
-    expectToHaveSubmoduleState(superRepo, "master", "sub", sub, "master");
-    RevCommit superHead = getRemoteHead(name("super-project"), "master");
+    expectToHaveSubmoduleState(superRepo, "master", subKey, subRepo, "master");
+    RevCommit superHead = getRemoteHead(superKey, "master");
     assertThat(superHead.getShortMessage()).contains("some message");
     assertThat(superHead.getId()).isNotEqualTo(superId);
   }
 
   @Test
   public void useFastForwardWhenNoSubmodule() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project", false);
-    TestRepository<?> sub = createProjectWithPush("sub", false);
+    // like setup, but without empty commit
+    superKey = createProjectForPush("super-nc", null, false, getSubmitType());
+    subKey = createProjectForPush("sub-nc", null, false, getSubmitType());
+    superRepo = cloneProject(superKey);
+    subRepo = cloneProject(subKey);
 
-    ObjectId subId = pushChangeTo(sub, "refs/for/master", "some message", "same-topic");
-
+    ObjectId subId = pushChangeTo(subRepo, "refs/for/master", "some message", "same-topic");
     ObjectId superId = pushChangeTo(superRepo, "refs/for/master", "some message", "same-topic");
 
-    String subChangeId = getChangeId(sub, subId).get();
+    String subChangeId = getChangeId(subRepo, subId).get();
     approve(subChangeId);
     approve(getChangeId(superRepo, superId).get());
 
     gApi.changes().id(subChangeId).current().submit();
 
-    RevCommit superHead = getRemoteHead(name("super-project"), "master");
+    RevCommit superHead = getRemoteHead(superKey, "master");
     assertThat(superHead.getShortMessage()).isEqualTo("some message");
     assertThat(superHead.getId()).isEqualTo(superId);
   }
 
   @Test
   public void sameProjectSameBranchDifferentPaths() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> sub = createProjectWithPush("sub");
-
-    allowMatchingSubmoduleSubscription(
-        "sub", "refs/heads/master", "super-project", "refs/heads/master");
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
 
     Config config = new Config();
-    prepareSubmoduleConfigEntry(config, "sub", "master");
-    prepareSubmoduleConfigEntry(config, "sub", "sub-copy", "master");
+    prepareSubmoduleConfigEntry(config, subKey, "master");
+    Project.NameKey copyKey = nameKey("sub-copy");
+    prepareSubmoduleConfigEntry(config, subKey, copyKey, "master");
     pushSubmoduleConfig(superRepo, "master", config);
 
     ObjectId superPreviousId = pushChangeTo(superRepo, "master");
 
-    ObjectId subId = pushChangeTo(sub, "refs/for/master", "some message", "");
+    ObjectId subId = pushChangeTo(subRepo, "refs/for/master", "some message", "");
 
-    approve(getChangeId(sub, subId).get());
+    approve(getChangeId(subRepo, subId).get());
 
-    gApi.changes().id(getChangeId(sub, subId).get()).current().submit();
+    gApi.changes().id(getChangeId(subRepo, subId).get()).current().submit();
 
-    expectToHaveSubmoduleState(superRepo, "master", "sub", sub, "master");
-    expectToHaveSubmoduleState(superRepo, "master", "sub-copy", sub, "master");
+    expectToHaveSubmoduleState(superRepo, "master", subKey, subRepo, "master");
+    expectToHaveSubmoduleState(superRepo, "master", copyKey, subRepo, "master");
 
     superRepo
         .git()
@@ -457,37 +449,33 @@
 
   @Test
   public void sameProjectDifferentBranchDifferentPaths() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> sub = createProjectWithPush("sub");
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/dev", superKey, "refs/heads/master");
 
-    allowMatchingSubmoduleSubscription(
-        "sub", "refs/heads/master", "super-project", "refs/heads/master");
-    allowMatchingSubmoduleSubscription(
-        "sub", "refs/heads/dev", "super-project", "refs/heads/master");
-
-    ObjectId devHead = pushChangeTo(sub, "dev");
+    ObjectId devHead = pushChangeTo(subRepo, "dev");
     Config config = new Config();
-    prepareSubmoduleConfigEntry(config, "sub", "sub-master", "master");
-    prepareSubmoduleConfigEntry(config, "sub", "sub-dev", "dev");
+    prepareSubmoduleConfigEntry(config, subKey, nameKey("sub-master"), "master");
+    prepareSubmoduleConfigEntry(config, subKey, nameKey("sub-dev"), "dev");
     pushSubmoduleConfig(superRepo, "master", config);
 
     ObjectId subMasterId =
-        pushChangeTo(sub, "refs/for/master", "some message", "b.txt", "content b", "same-topic");
+        pushChangeTo(
+            subRepo, "refs/for/master", "some message", "b.txt", "content b", "same-topic");
 
-    sub.reset(devHead);
+    subRepo.reset(devHead);
     ObjectId subDevId =
         pushChangeTo(
-            sub, "refs/for/dev", "some message in dev", "b.txt", "content b", "same-topic");
+            subRepo, "refs/for/dev", "some message in dev", "b.txt", "content b", "same-topic");
 
-    approve(getChangeId(sub, subMasterId).get());
-    approve(getChangeId(sub, subDevId).get());
+    approve(getChangeId(subRepo, subMasterId).get());
+    approve(getChangeId(subRepo, subDevId).get());
 
     ObjectId superPreviousId = pushChangeTo(superRepo, "master");
 
-    gApi.changes().id(getChangeId(sub, subMasterId).get()).current().submit();
+    gApi.changes().id(getChangeId(subRepo, subMasterId).get()).current().submit();
 
-    expectToHaveSubmoduleState(superRepo, "master", "sub-master", sub, "master");
-    expectToHaveSubmoduleState(superRepo, "master", "sub-dev", sub, "dev");
+    expectToHaveSubmoduleState(superRepo, "master", nameKey("sub-master"), subRepo, "master");
+    expectToHaveSubmoduleState(superRepo, "master", nameKey("sub-dev"), subRepo, "dev");
 
     superRepo
         .git()
@@ -504,29 +492,27 @@
 
   @Test
   public void nonSubmoduleInSameTopic() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> sub = createProjectWithPush("sub");
-    TestRepository<?> standAlone = createProjectWithPush("standalone");
+    Project.NameKey standaloneKey = createProjectForPush("standalone", null, true, getSubmitType());
+    TestRepository<?> standAlone = cloneProject(standaloneKey);
 
-    allowMatchingSubmoduleSubscription(
-        "sub", "refs/heads/master", "super-project", "refs/heads/master");
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
 
-    createSubmoduleSubscription(superRepo, "master", "sub", "master");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
 
     ObjectId superPreviousId = pushChangeTo(superRepo, "master");
 
-    ObjectId subId = pushChangeTo(sub, "refs/for/master", "some message", "same-topic");
+    ObjectId subId = pushChangeTo(subRepo, "refs/for/master", "some message", "same-topic");
     ObjectId standAloneId =
         pushChangeTo(standAlone, "refs/for/master", "some message", "same-topic");
 
-    String subChangeId = getChangeId(sub, subId).get();
+    String subChangeId = getChangeId(subRepo, subId).get();
     String standAloneChangeId = getChangeId(standAlone, standAloneId).get();
     approve(subChangeId);
     approve(standAloneChangeId);
 
     gApi.changes().id(subChangeId).current().submit();
 
-    expectToHaveSubmoduleState(superRepo, "master", "sub", sub, "master");
+    expectToHaveSubmoduleState(superRepo, "master", subKey, subRepo, "master");
 
     ChangeStatus status = gApi.changes().id(standAloneChangeId).info().status;
     assertThat(status).isEqualTo(ChangeStatus.MERGED);
@@ -546,17 +532,18 @@
 
   @Test
   public void recursiveSubmodules() throws Exception {
-    TestRepository<?> topRepo = createProjectWithPush("top-project");
-    TestRepository<?> midRepo = createProjectWithPush("mid-project");
-    TestRepository<?> bottomRepo = createProjectWithPush("bottom-project");
+    Project.NameKey topKey = createProjectForPush("top-project", null, true, getSubmitType());
+    Project.NameKey midKey = createProjectForPush("mid-project", null, true, getSubmitType());
+    Project.NameKey botKey = createProjectForPush("bottom-project", null, true, getSubmitType());
+    TestRepository<?> topRepo = cloneProject(topKey);
+    TestRepository<?> midRepo = cloneProject(midKey);
+    TestRepository<?> bottomRepo = cloneProject(botKey);
 
-    allowMatchingSubmoduleSubscription(
-        "mid-project", "refs/heads/master", "top-project", "refs/heads/master");
-    allowMatchingSubmoduleSubscription(
-        "bottom-project", "refs/heads/master", "mid-project", "refs/heads/master");
+    allowMatchingSubmoduleSubscription(midKey, "refs/heads/master", topKey, "refs/heads/master");
+    allowMatchingSubmoduleSubscription(botKey, "refs/heads/master", midKey, "refs/heads/master");
 
-    createSubmoduleSubscription(topRepo, "master", "mid-project", "master");
-    createSubmoduleSubscription(midRepo, "master", "bottom-project", "master");
+    createSubmoduleSubscription(topRepo, "master", midKey, "master");
+    createSubmoduleSubscription(midRepo, "master", botKey, "master");
 
     ObjectId bottomHead = pushChangeTo(bottomRepo, "refs/for/master", "some message", "same-topic");
     ObjectId topHead = pushChangeTo(topRepo, "refs/for/master", "some message", "same-topic");
@@ -569,27 +556,27 @@
 
     gApi.changes().id(id1).current().submit();
 
-    expectToHaveSubmoduleState(midRepo, "master", "bottom-project", bottomRepo, "master");
-    expectToHaveSubmoduleState(topRepo, "master", "mid-project", midRepo, "master");
+    expectToHaveSubmoduleState(midRepo, "master", botKey, bottomRepo, "master");
+    expectToHaveSubmoduleState(topRepo, "master", midKey, midRepo, "master");
   }
 
   @Test
   public void triangleSubmodules() throws Exception {
-    TestRepository<?> topRepo = createProjectWithPush("top-project");
-    TestRepository<?> midRepo = createProjectWithPush("mid-project");
-    TestRepository<?> bottomRepo = createProjectWithPush("bottom-project");
+    Project.NameKey topKey = createProjectForPush("top-project", null, true, getSubmitType());
+    Project.NameKey midKey = createProjectForPush("mid-project", null, true, getSubmitType());
+    Project.NameKey botKey = createProjectForPush("bottom-project", null, true, getSubmitType());
+    TestRepository<?> topRepo = cloneProject(topKey);
+    TestRepository<?> midRepo = cloneProject(midKey);
+    TestRepository<?> bottomRepo = cloneProject(botKey);
 
-    allowMatchingSubmoduleSubscription(
-        "mid-project", "refs/heads/master", "top-project", "refs/heads/master");
-    allowMatchingSubmoduleSubscription(
-        "bottom-project", "refs/heads/master", "mid-project", "refs/heads/master");
-    allowMatchingSubmoduleSubscription(
-        "bottom-project", "refs/heads/master", "top-project", "refs/heads/master");
+    allowMatchingSubmoduleSubscription(midKey, "refs/heads/master", topKey, "refs/heads/master");
+    allowMatchingSubmoduleSubscription(botKey, "refs/heads/master", midKey, "refs/heads/master");
+    allowMatchingSubmoduleSubscription(botKey, "refs/heads/master", topKey, "refs/heads/master");
 
-    createSubmoduleSubscription(midRepo, "master", "bottom-project", "master");
+    createSubmoduleSubscription(midRepo, "master", botKey, "master");
     Config config = new Config();
-    prepareSubmoduleConfigEntry(config, "bottom-project", "master");
-    prepareSubmoduleConfigEntry(config, "mid-project", "master");
+    prepareSubmoduleConfigEntry(config, botKey, "master");
+    prepareSubmoduleConfigEntry(config, midKey, "master");
     pushSubmoduleConfig(topRepo, "master", config);
 
     ObjectId bottomHead = pushChangeTo(bottomRepo, "refs/for/master", "some message", "same-topic");
@@ -603,26 +590,26 @@
 
     gApi.changes().id(id1).current().submit();
 
-    expectToHaveSubmoduleState(midRepo, "master", "bottom-project", bottomRepo, "master");
-    expectToHaveSubmoduleState(topRepo, "master", "mid-project", midRepo, "master");
-    expectToHaveSubmoduleState(topRepo, "master", "bottom-project", bottomRepo, "master");
+    expectToHaveSubmoduleState(midRepo, "master", botKey, bottomRepo, "master");
+    expectToHaveSubmoduleState(topRepo, "master", midKey, midRepo, "master");
+    expectToHaveSubmoduleState(topRepo, "master", botKey, bottomRepo, "master");
   }
 
   private String prepareBranchCircularSubscription() throws Exception {
-    TestRepository<?> topRepo = createProjectWithPush("top-project");
-    TestRepository<?> midRepo = createProjectWithPush("mid-project");
-    TestRepository<?> bottomRepo = createProjectWithPush("bottom-project");
+    Project.NameKey topKey = createProjectForPush("top-project", null, true, getSubmitType());
+    Project.NameKey midKey = createProjectForPush("mid-project", null, true, getSubmitType());
+    Project.NameKey botKey = createProjectForPush("bottom-project", null, true, getSubmitType());
+    TestRepository<?> topRepo = cloneProject(topKey);
+    TestRepository<?> midRepo = cloneProject(midKey);
+    TestRepository<?> bottomRepo = cloneProject(botKey);
 
-    createSubmoduleSubscription(midRepo, "master", "bottom-project", "master");
-    createSubmoduleSubscription(topRepo, "master", "mid-project", "master");
-    createSubmoduleSubscription(bottomRepo, "master", "top-project", "master");
+    createSubmoduleSubscription(midRepo, "master", botKey, "master");
+    createSubmoduleSubscription(topRepo, "master", midKey, "master");
+    createSubmoduleSubscription(bottomRepo, "master", topKey, "master");
 
-    allowMatchingSubmoduleSubscription(
-        "bottom-project", "refs/heads/master", "mid-project", "refs/heads/master");
-    allowMatchingSubmoduleSubscription(
-        "mid-project", "refs/heads/master", "top-project", "refs/heads/master");
-    allowMatchingSubmoduleSubscription(
-        "top-project", "refs/heads/master", "bottom-project", "refs/heads/master");
+    allowMatchingSubmoduleSubscription(botKey, "refs/heads/master", midKey, "refs/heads/master");
+    allowMatchingSubmoduleSubscription(midKey, "refs/heads/master", topKey, "refs/heads/master");
+    allowMatchingSubmoduleSubscription(topKey, "refs/heads/master", botKey, "refs/heads/master");
 
     ObjectId bottomMasterHead = pushChangeTo(bottomRepo, "refs/for/master", "some message", "");
     String changeId = getChangeId(bottomRepo, bottomMasterHead).get();
@@ -649,19 +636,14 @@
 
   @Test
   public void projectCircularSubscriptionWholeTopic() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> subRepo = createProjectWithPush("subscribed-to-project");
-
-    allowMatchingSubmoduleSubscription(
-        "subscribed-to-project", "refs/heads/master", "super-project", "refs/heads/master");
-    allowMatchingSubmoduleSubscription(
-        "super-project", "refs/heads/dev", "subscribed-to-project", "refs/heads/dev");
+    allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
+    allowMatchingSubmoduleSubscription(superKey, "refs/heads/dev", subKey, "refs/heads/dev");
 
     pushChangeTo(subRepo, "dev");
     pushChangeTo(superRepo, "dev");
 
-    createSubmoduleSubscription(superRepo, "master", "subscribed-to-project", "master");
-    createSubmoduleSubscription(subRepo, "dev", "super-project", "dev");
+    createSubmoduleSubscription(superRepo, "master", subKey, "master");
+    createSubmoduleSubscription(subRepo, "dev", superKey, "dev");
 
     ObjectId subMasterHead =
         pushChangeTo(
@@ -672,15 +654,15 @@
     approve(getChangeId(superRepo, superDevHead).get());
 
     exception.expectMessage("Project level circular subscriptions detected");
-    exception.expectMessage("subscribed-to-project");
-    exception.expectMessage("super-project");
+    exception.expectMessage(subKey.get());
+    exception.expectMessage(superKey.get());
     gApi.changes().id(getChangeId(subRepo, subMasterHead).get()).current().submit();
   }
 
   @Test
   public void projectNoSubscriptionWholeTopic() throws Exception {
-    TestRepository<?> repoA = createProjectWithPush("project-a");
-    TestRepository<?> repoB = createProjectWithPush("project-b");
+    TestRepository<?> repoA = createProjectWithPush("project-a", null, true, getSubmitType());
+    TestRepository<?> repoB = createProjectWithPush("project-b", null, true, getSubmitType());
     // bootstrap the dev branch
     ObjectId a0 = pushChangeTo(repoA, "dev");
 
@@ -747,8 +729,8 @@
 
   @Test
   public void twoProjectsMultipleBranchesWholeTopic() throws Exception {
-    TestRepository<?> repoA = createProjectWithPush("project-a");
-    TestRepository<?> repoB = createProjectWithPush("project-b");
+    TestRepository<?> repoA = createProjectWithPush("project-a", null, true, getSubmitType());
+    TestRepository<?> repoB = createProjectWithPush("project-b", null, true, getSubmitType());
     // bootstrap the dev branch
     pushChangeTo(repoA, "dev");
 
@@ -796,18 +778,17 @@
   public void retrySubmitAfterTornTopicOnLockFailure() throws Exception {
     assume().that(notesMigration.disableChangeReviewDb()).isTrue();
 
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> sub1 = createProjectWithPush("sub1");
-    TestRepository<?> sub2 = createProjectWithPush("sub2");
+    Project.NameKey subKey1 = createProjectForPush("sub1", null, true, getSubmitType());
+    TestRepository<?> sub1 = cloneProject(subKey1);
+    Project.NameKey subKey2 = createProjectForPush("sub2", null, true, getSubmitType());
+    TestRepository<?> sub2 = cloneProject(subKey2);
 
-    allowMatchingSubmoduleSubscription(
-        "sub1", "refs/heads/master", "super-project", "refs/heads/master");
-    allowMatchingSubmoduleSubscription(
-        "sub2", "refs/heads/master", "super-project", "refs/heads/master");
+    allowMatchingSubmoduleSubscription(subKey1, "refs/heads/master", superKey, "refs/heads/master");
+    allowMatchingSubmoduleSubscription(subKey2, "refs/heads/master", superKey, "refs/heads/master");
 
     Config config = new Config();
-    prepareSubmoduleConfigEntry(config, "sub1", "master");
-    prepareSubmoduleConfigEntry(config, "sub2", "master");
+    prepareSubmoduleConfigEntry(config, subKey1, "master");
+    prepareSubmoduleConfigEntry(config, subKey2, "master");
     pushSubmoduleConfig(superRepo, "master", config);
 
     ObjectId superPreviousId = pushChangeTo(superRepo, "master");
@@ -837,20 +818,20 @@
 
     sub1.git().fetch().call();
     RevWalk rw1 = sub1.getRevWalk();
-    RevCommit master1 = rw1.parseCommit(getRemoteHead(name("sub1"), "master"));
+    RevCommit master1 = rw1.parseCommit(getRemoteHead(subKey1.get(), "master"));
     RevCommit change1Ps = parseCurrentRevision(rw1, changeId1);
     assertThat(rw1.isMergedInto(change1Ps, master1)).isTrue();
 
     sub2.git().fetch().call();
     RevWalk rw2 = sub2.getRevWalk();
-    RevCommit master2 = rw2.parseCommit(getRemoteHead(name("sub2"), "master"));
+    RevCommit master2 = rw2.parseCommit(getRemoteHead(subKey2.get(), "master"));
     RevCommit change2Ps = parseCurrentRevision(rw2, changeId2);
     assertThat(rw2.isMergedInto(change2Ps, master2)).isTrue();
 
     assertThat(input.generateLockFailures).containsExactly(false);
 
-    expectToHaveSubmoduleState(superRepo, "master", "sub1", sub1, "master");
-    expectToHaveSubmoduleState(superRepo, "master", "sub2", sub2, "master");
+    expectToHaveSubmoduleState(superRepo, "master", subKey1, sub1, "master");
+    expectToHaveSubmoduleState(superRepo, "master", subKey2, sub2, "master");
 
     assertWithMessage("submodule subscription update should have made one commit")
         .that(superRepo.getRepository().resolve("origin/master^"))
@@ -859,24 +840,23 @@
 
   @Test
   public void skipUpdatingBrokenGitlinkPointer() throws Exception {
-    TestRepository<?> superRepo = createProjectWithPush("super-project");
-    TestRepository<?> sub1 = createProjectWithPush("sub1");
-    TestRepository<?> sub2 = createProjectWithPush("sub2");
+    Project.NameKey subKey1 = createProjectForPush("sub1", null, true, getSubmitType());
+    TestRepository<?> sub1 = cloneProject(subKey1);
+    Project.NameKey subKey2 = createProjectForPush("sub2", null, true, getSubmitType());
+    TestRepository<?> sub2 = cloneProject(subKey2);
 
-    allowMatchingSubmoduleSubscription(
-        "sub1", "refs/heads/master", "super-project", "refs/heads/master");
-    allowMatchingSubmoduleSubscription(
-        "sub2", "refs/heads/master", "super-project", "refs/heads/master");
+    allowMatchingSubmoduleSubscription(subKey1, "refs/heads/master", superKey, "refs/heads/master");
+    allowMatchingSubmoduleSubscription(subKey2, "refs/heads/master", superKey, "refs/heads/master");
 
     Config config = new Config();
-    prepareSubmoduleConfigEntry(config, "sub1", "master");
-    prepareSubmoduleConfigEntry(config, "sub2", "master");
+    prepareSubmoduleConfigEntry(config, subKey1, "master");
+    prepareSubmoduleConfigEntry(config, subKey2, "master");
     pushSubmoduleConfig(superRepo, "master", config);
 
     // Write an invalid SHA-1 directly to one of the gitlinks.
     ObjectId badId = ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
-    directUpdateSubmodule("super-project", "refs/heads/master", "sub1", badId);
-    expectToHaveSubmoduleState(superRepo, "master", "sub1", badId);
+    directUpdateSubmodule(superKey, "refs/heads/master", subKey1, badId);
+    expectToHaveSubmoduleState(superRepo, "master", subKey1, badId);
 
     String topic = "same-topic";
     ObjectId sub1Id = pushChangeTo(sub1, "refs/for/master", "some message", topic);
@@ -893,7 +873,7 @@
     assertThat(info(changeId2).status).isEqualTo(ChangeStatus.MERGED);
 
     // sub1 was skipped but sub2 succeeded.
-    expectToHaveSubmoduleState(superRepo, "master", "sub1", badId);
-    expectToHaveSubmoduleState(superRepo, "master", "sub2", sub2, "master");
+    expectToHaveSubmoduleState(superRepo, "master", subKey1, badId);
+    expectToHaveSubmoduleState(superRepo, "master", subKey2, sub2, "master");
   }
 }
diff --git a/javatests/com/google/gerrit/acceptance/rest/ProjectsRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/ProjectsRestApiBindingsIT.java
index 6563de3..ca8d3ce 100644
--- a/javatests/com/google/gerrit/acceptance/rest/ProjectsRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/ProjectsRestApiBindingsIT.java
@@ -60,7 +60,6 @@
           RestCall.post("/projects/%s/access"),
           RestCall.put("/projects/%s/access:review"),
           RestCall.get("/projects/%s/check.access"),
-          RestCall.post("/projects/%s/check.access"),
           RestCall.put("/projects/%s/ban"),
           RestCall.get("/projects/%s/statistics.git"),
           RestCall.post("/projects/%s/index"),
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/ChangeIdIT.java b/javatests/com/google/gerrit/acceptance/rest/change/ChangeIdIT.java
index a2ad7fc..3f1608c 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/ChangeIdIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/ChangeIdIT.java
@@ -18,6 +18,7 @@
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.acceptance.RestResponse;
 import com.google.gerrit.extensions.api.changes.ChangeApi;
+import com.google.gerrit.reviewdb.client.Change;
 import org.junit.Test;
 
 public class ChangeIdIT extends AbstractDaemonTest {
@@ -92,6 +93,43 @@
     res.assertNotFound();
   }
 
+  @Test
+  public void changeNumberRedirects() throws Exception {
+    // This test tests a redirect that is primarily intended for the UI (though the backend doesn't
+    // really care who the caller is). The redirect rewrites a shorthand change number URL (/123) to
+    // it's canonical long form (/c/project/+/123).
+    int changeId = createChange().getChange().getId().id;
+    RestResponse res = anonymousRestSession.get("/" + changeId);
+    res.assertTemporaryRedirect("/c/" + project.get() + "/+/" + changeId + "/");
+  }
+
+  @Test
+  public void changeNumberRedirectsWithTrailingSlash() throws Exception {
+    int changeId = createChange().getChange().getId().id;
+    RestResponse res = anonymousRestSession.get("/" + changeId + "/");
+    res.assertTemporaryRedirect("/c/" + project.get() + "/+/" + changeId + "/");
+  }
+
+  @Test
+  public void changeNumberOverflowNotFound() throws Exception {
+    RestResponse res = anonymousRestSession.get("/9" + Long.MAX_VALUE);
+    res.assertNotFound();
+  }
+
+  @Test
+  public void unknownChangeNumberNotFound() throws Exception {
+    RestResponse res = anonymousRestSession.get("/10");
+    res.assertNotFound();
+  }
+
+  @Test
+  public void hiddenChangeNotFound() throws Exception {
+    Change.Id changeId = createChange().getChange().getId();
+    gApi.changes().id(changeId.id).setPrivate(true, null);
+    RestResponse res = anonymousRestSession.get("/" + changeId.id);
+    res.assertNotFound();
+  }
+
   private static String changeDetail(String changeId) {
     return "/changes/" + changeId + "/detail";
   }
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java b/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java
index d1f4d84..6a9a27c 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java
@@ -31,6 +31,7 @@
 import com.google.gerrit.acceptance.RestResponse;
 import com.google.gerrit.acceptance.Sandboxed;
 import com.google.gerrit.acceptance.TestAccount;
+import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.extensions.api.changes.AddReviewerInput;
 import com.google.gerrit.extensions.api.changes.AddReviewerResult;
@@ -52,6 +53,7 @@
 import com.google.gerrit.server.change.ReviewerAdder;
 import com.google.gerrit.testing.FakeEmailSender.Message;
 import com.google.gson.stream.JsonReader;
+import com.google.inject.Inject;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -62,12 +64,15 @@
 import org.junit.Test;
 
 public class ChangeReviewersIT extends AbstractDaemonTest {
+
+  @Inject protected GroupOperations groupOperations;
+
   @Test
   public void addGroupAsReviewer() throws Exception {
     // Set up two groups, one that is too large too add as reviewer, and one
     // that is too large to add without confirmation.
-    String largeGroup = createGroup("largeGroup");
-    String mediumGroup = createGroup("mediumGroup");
+    String largeGroup = groupOperations.newGroup().name("largeGroup").create().get();
+    String mediumGroup = groupOperations.newGroup().name("mediumGroup").create().get();
 
     int largeGroupSize = ReviewerAdder.DEFAULT_MAX_REVIEWERS + 1;
     int mediumGroupSize = ReviewerAdder.DEFAULT_MAX_REVIEWERS_WITHOUT_CHECK + 1;
@@ -170,7 +175,7 @@
     PushOneCommit.Result r = createChange();
     String changeId = r.getChangeId();
     AddReviewerInput in = new AddReviewerInput();
-    in.reviewer = createGroup("cc1");
+    in.reviewer = groupOperations.newGroup().name("cc1").create().get();
     in.state = CC;
     gApi.groups()
         .id(in.reviewer)
@@ -209,7 +214,7 @@
     result = addReviewer(changeId, reviewer.username);
     assertThat(result.error).isNull();
     sender.clear();
-    in.reviewer = createGroup("cc2");
+    in.reviewer = groupOperations.newGroup().name("cc2").create().get();
     gApi.groups().id(in.reviewer).addMembers(usernames.toArray(new String[usernames.size()]));
     gApi.groups().id(in.reviewer).addMembers(reviewer.username);
     result = addReviewer(changeId, in);
@@ -479,8 +484,8 @@
       usernames.add(u.username);
     }
 
-    String largeGroup = createGroup("largeGroup");
-    String mediumGroup = createGroup("mediumGroup");
+    String largeGroup = groupOperations.newGroup().name("largeGroup").create().get();
+    String mediumGroup = groupOperations.newGroup().name("mediumGroup").create().get();
     gApi.groups().id(largeGroup).addMembers(usernames.toArray(new String[largeGroupSize]));
     gApi.groups()
         .id(mediumGroup)
@@ -622,8 +627,8 @@
         accountCreator.create(name("user2"), emailPrefix + "user2@example.com", "User2");
     TestAccount user3 =
         accountCreator.create(name("user3"), emailPrefix + "user3@example.com", "User3");
-    String group1 = createGroup("group1");
-    String group2 = createGroup("group2");
+    String group1 = groupOperations.newGroup().name("group1").create().get();
+    String group2 = groupOperations.newGroup().name("group2").create().get();
     gApi.groups().id(group1).addMembers(user1.username, user2.username);
     gApi.groups().id(group2).addMembers(user2.username, user3.username);
 
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/CorsIT.java b/javatests/com/google/gerrit/acceptance/rest/change/CorsIT.java
index 0af9708..6fd3bab 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/CorsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/CorsIT.java
@@ -34,6 +34,7 @@
 import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.PushOneCommit.Result;
 import com.google.gerrit.acceptance.RestResponse;
+import com.google.gerrit.acceptance.RestSession;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.restapi.RestApiException;
@@ -44,6 +45,7 @@
 import java.util.stream.Stream;
 import org.apache.http.Header;
 import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
 import org.apache.http.client.fluent.Executor;
 import org.apache.http.client.fluent.Request;
 import org.apache.http.cookie.Cookie;
@@ -99,6 +101,30 @@
   }
 
   @Test
+  public void originsOnNotFoundException() throws Exception {
+    String url = "/changes/999/detail";
+    check(url, true, "http://example.com", adminRestSession, 404);
+    check(url, false, "http://friendsly", adminRestSession, 404);
+  }
+
+  @Test
+  public void originsOnBadRequestException() throws Exception {
+    String url = "/config/server/caches/?format=NONSENSE";
+    check(url, true, "http://example.com", adminRestSession, 400);
+    check(url, false, "http://friendsly", adminRestSession, 400);
+  }
+
+  @Test
+  public void originsOnForbidden() throws Exception {
+    Result change = createChange();
+    // Make change private to hide it
+    gApi.changes().id(change.getChangeId()).setPrivate(true, "now private");
+    String url = "/changes/" + change.getChangeId() + "/detail";
+    check(url, true, "http://example.com", anonymousRestSession, 404);
+    check(url, false, "http://friendsly", anonymousRestSession, 404);
+  }
+
+  @Test
   public void putWithServerOriginAcceptedWithNoCorsResponseHeaders() throws Exception {
     Result change = createChange();
     String origin = adminRestSession.url();
@@ -247,9 +273,15 @@
   }
 
   private void check(String url, boolean accept, String origin) throws Exception {
+    check(url, accept, origin, adminRestSession, HttpStatus.SC_OK);
+  }
+
+  private void check(
+      String url, boolean accept, String origin, RestSession restSession, int httpStatusCode)
+      throws Exception {
     Header hdr = new BasicHeader(ORIGIN, origin);
-    RestResponse r = adminRestSession.getWithHeader(url, hdr);
-    r.assertOK();
+    RestResponse r = restSession.getWithHeader(url, hdr);
+    r.assertStatus(httpStatusCode);
     checkCors(r, accept, origin);
   }
 
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/IndexChangeIT.java b/javatests/com/google/gerrit/acceptance/rest/change/IndexChangeIT.java
index 6555fe8..bb114e7 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/IndexChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/IndexChangeIT.java
@@ -20,17 +20,22 @@
 import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.acceptance.TestAccount;
+import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.project.testing.Util;
+import com.google.inject.Inject;
 import java.util.List;
 import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
 import org.eclipse.jgit.junit.TestRepository;
 import org.junit.Test;
 
 public class IndexChangeIT extends AbstractDaemonTest {
+
+  @Inject protected GroupOperations groupOperations;
+
   @Test
   public void indexChange() throws Exception {
     String changeId = createChange().getChangeId();
@@ -48,7 +53,8 @@
   public void indexChangeAfterOwnerLosesVisibility() throws Exception {
     // Create a test group with 2 users as members
     TestAccount user2 = accountCreator.user2();
-    String group = createGroup("test");
+    AccountGroup.UUID groupId = groupOperations.newGroup().name("test").create();
+    String group = groupOperations.group(groupId).get().name();
     gApi.groups().id(group).addMembers("admin", "user", user2.username);
 
     // Create a project and restrict its visibility to the group
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/MoveChangeIT.java b/javatests/com/google/gerrit/acceptance/rest/change/MoveChangeIT.java
index 206cc68..222973e 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/MoveChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/MoveChangeIT.java
@@ -19,6 +19,7 @@
 import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
 
 import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.GitUtil;
 import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.acceptance.PushOneCommit;
@@ -30,6 +31,7 @@
 import com.google.gerrit.extensions.api.projects.BranchInput;
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.BadRequestException;
+import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.reviewdb.client.AccountGroup;
@@ -332,6 +334,16 @@
     move(r.getChangeId(), null);
   }
 
+  @Test
+  @GerritConfig(name = "change.move", value = "false")
+  public void moveCanBeDisabledByConfig() throws Exception {
+    PushOneCommit.Result r = createChange();
+
+    exception.expect(MethodNotAllowedException.class);
+    exception.expectMessage("move changes endpoint is disabled");
+    move(r.getChangeId(), null);
+  }
+
   private void move(int changeNum, String destination) throws RestApiException {
     gApi.changes().id(changeNum).move(destination);
   }
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/SubmitByMergeIfNecessaryIT.java b/javatests/com/google/gerrit/acceptance/rest/change/SubmitByMergeIfNecessaryIT.java
index c1dda00..229122b 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/SubmitByMergeIfNecessaryIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/SubmitByMergeIfNecessaryIT.java
@@ -15,6 +15,7 @@
 package com.google.gerrit.acceptance.rest.change;
 
 import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.TruthJUnit.assume;
 import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
 import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
 
@@ -24,10 +25,9 @@
 import com.google.gerrit.extensions.api.changes.ChangeApi;
 import com.google.gerrit.extensions.api.changes.CherryPickInput;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
-import com.google.gerrit.extensions.api.changes.SubmitInput;
 import com.google.gerrit.extensions.api.projects.BranchInput;
-import com.google.gerrit.extensions.client.ChangeStatus;
 import com.google.gerrit.extensions.client.SubmitType;
+import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.BinaryResult;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.RestApiException;
@@ -657,7 +657,7 @@
   }
 
   @Test
-  public void dependencyOnHiddenChangeShouldPreventMergeButDoesnt() throws Exception {
+  public void dependencyOnHiddenChangePreventsMerge() throws Exception {
     grantLabel("Code-Review", -2, 2, project, "refs/heads/*", false, REGISTERED_USERS, false);
     grant(project, "refs/*", Permission.SUBMIT, false, REGISTERED_USERS);
 
@@ -686,18 +686,80 @@
       assertThat(e.getMessage()).isEqualTo("Not found: " + changeResult.getChangeId());
     }
 
-    // Submit the second change which has a dependency on the first change which is not visible to
-    // the user. We would expect the submit to fail, but instead the submit succeeds and the hidden
-    // change gets submitted too.
-    // TODO(ekempin): Make this submit fail.
-    gApi.changes().id(change2Result.getChangeId()).current().submit(new SubmitInput());
+    // Submit is expected to fail.
+    try {
+      gApi.changes().id(change2Result.getChangeId()).current().submit();
+      fail("expected failure");
+    } catch (AuthException e) {
+      assertThat(e.getMessage())
+          .isEqualTo(
+              "A change to be submitted with "
+                  + change2Result.getChange().getId().id
+                  + " is not visible");
+    }
+    assertRefUpdatedEvents();
+    assertChangeMergedEvents();
+  }
 
-    // Verify that both changes have been submitted.
-    setApiUser(admin);
-    assertThat(gApi.changes().id(changeResult.getChangeId()).get().status)
-        .isEqualTo(ChangeStatus.MERGED);
-    assertThat(gApi.changes().id(change2Result.getChangeId()).get().status)
-        .isEqualTo(ChangeStatus.MERGED);
+  @Test
+  public void dependencyOnHiddenChangeUsingTopicPreventsMerge() throws Exception {
+    // Construct a topic where a change included by topic depends on a private change that is not
+    // visible to the submitting user
+    // (c1) --- topic --- (c2b)
+    //                      |
+    //                    (c2a) <= private
+    assume().that(isSubmitWholeTopicEnabled()).isTrue();
+
+    Project.NameKey p1 = createProject("project-where-we-submit");
+    Project.NameKey p2 = createProject("project-impacted-via-topic");
+
+    grantLabel("Code-Review", -2, 2, p1, "refs/heads/*", false, REGISTERED_USERS, false);
+    grant(p1, "refs/*", Permission.SUBMIT, false, REGISTERED_USERS);
+    grantLabel("Code-Review", -2, 2, p2, "refs/heads/*", false, REGISTERED_USERS, false);
+    grant(p2, "refs/*", Permission.SUBMIT, false, REGISTERED_USERS);
+
+    TestRepository<?> repo1 = cloneProject(p1);
+    TestRepository<?> repo2 = cloneProject(p2);
+
+    PushOneCommit.Result change1 =
+        createChange(repo1, "master", "A fresh change in repo1", "a.txt", "1", "topic-to-submit");
+    approve(change1.getChangeId());
+    PushOneCommit push =
+        pushFactory.create(
+            db, admin.getIdent(), repo2, "An ancestor change in repo2", "a.txt", "2");
+    PushOneCommit.Result change2a = push.to("refs/for/master");
+    approve(change2a.getChangeId());
+    PushOneCommit.Result change2b =
+        createChange(
+            repo2, "master", "A topic-linked change in repo2", "a.txt", "2", "topic-to-submit");
+    approve(change2b.getChangeId());
+
+    // Mark change2a private so that it's not visible to user.
+    gApi.changes().id(change2a.getChangeId()).setPrivate(true, "nobody should see this");
+
+    setApiUser(user);
+
+    // Verify that user cannot see change2a
+    try {
+      gApi.changes().id(change2a.getChangeId()).get();
+      fail("expected failure");
+    } catch (ResourceNotFoundException e) {
+      assertThat(e.getMessage()).isEqualTo("Not found: " + change2a.getChangeId());
+    }
+
+    // Submit is expected to fail.
+    try {
+      gApi.changes().id(change1.getChangeId()).current().submit();
+      fail("expected failure");
+    } catch (AuthException e) {
+      assertThat(e.getMessage())
+          .isEqualTo(
+              "A change to be submitted with "
+                  + change1.getChange().getId().id
+                  + " is not visible");
+    }
+    assertRefUpdatedEvents();
+    assertChangeMergedEvents();
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/acceptance/rest/config/ServerInfoIT.java b/javatests/com/google/gerrit/acceptance/rest/config/ServerInfoIT.java
index 874e04e..6c0b707 100644
--- a/javatests/com/google/gerrit/acceptance/rest/config/ServerInfoIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/config/ServerInfoIT.java
@@ -70,7 +70,6 @@
   // gerrit
   @GerritConfig(name = "gerrit.allProjects", value = "Root")
   @GerritConfig(name = "gerrit.allUsers", value = "Users")
-  @GerritConfig(name = "gerrit.enableGwtUi", value = "true")
   @GerritConfig(name = "gerrit.reportBugText", value = "REPORT BUG")
   @GerritConfig(name = "gerrit.reportBugUrl", value = "https://example.com/report")
 
@@ -197,13 +196,4 @@
     // user
     assertThat(i.user.anonymousCowardName).isEqualTo(AnonymousCowardNameProvider.DEFAULT);
   }
-
-  @Test
-  @GerritConfig(name = "auth.contributorAgreements", value = "true")
-  public void anonymousAccess() throws Exception {
-    configureContributorAgreement(true);
-
-    setApiUserAnonymous();
-    gApi.config().server().getInfo();
-  }
 }
diff --git a/javatests/com/google/gerrit/acceptance/server/change/CommentsIT.java b/javatests/com/google/gerrit/acceptance/server/change/CommentsIT.java
index 8b1f4bc..0d40a1c 100644
--- a/javatests/com/google/gerrit/acceptance/server/change/CommentsIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/change/CommentsIT.java
@@ -716,7 +716,7 @@
   }
 
   @Test
-  public void queryChangesWithUnresolvedCommentCount() throws Exception {
+  public void queryChangesWithCommentCount() throws Exception {
     // PS1 has three comments in three different threads, PS2 has one comment in one thread.
     PushOneCommit.Result result = createChange("change 1", FILE_NAME, "content 1");
     String changeId1 = result.getChangeId();
@@ -751,8 +751,11 @@
       ChangeInfo changeInfo2 = Iterables.getOnlyElement(query(changeId2));
       ChangeInfo changeInfo3 = Iterables.getOnlyElement(query(changeId3));
       assertThat(changeInfo1.unresolvedCommentCount).isEqualTo(2);
+      assertThat(changeInfo1.totalCommentCount).isEqualTo(4);
       assertThat(changeInfo2.unresolvedCommentCount).isEqualTo(0);
+      assertThat(changeInfo2.totalCommentCount).isEqualTo(2);
       assertThat(changeInfo3.unresolvedCommentCount).isEqualTo(1);
+      assertThat(changeInfo3.totalCommentCount).isEqualTo(2);
     } finally {
       enableDb(ctx);
     }
diff --git a/javatests/com/google/gerrit/acceptance/server/change/GetRelatedIT.java b/javatests/com/google/gerrit/acceptance/server/change/GetRelatedIT.java
index 5d3b223..8e8aeac 100644
--- a/javatests/com/google/gerrit/acceptance/server/change/GetRelatedIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/change/GetRelatedIT.java
@@ -24,9 +24,10 @@
 import com.google.common.collect.Iterables;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.GerritConfig;
+import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.acceptance.PushOneCommit;
-import com.google.gerrit.acceptance.RestResponse;
 import com.google.gerrit.common.RawInputUtil;
+import com.google.gerrit.extensions.api.changes.RelatedChangeAndCommitInfo;
 import com.google.gerrit.extensions.common.CommitInfo;
 import com.google.gerrit.extensions.common.EditInfo;
 import com.google.gerrit.index.IndexConfig;
@@ -35,8 +36,6 @@
 import com.google.gerrit.server.query.change.ChangeData;
 import com.google.gerrit.server.restapi.change.ChangesCollection;
 import com.google.gerrit.server.restapi.change.GetRelated;
-import com.google.gerrit.server.restapi.change.GetRelated.ChangeAndCommit;
-import com.google.gerrit.server.restapi.change.GetRelated.RelatedInfo;
 import com.google.gerrit.server.update.BatchUpdate;
 import com.google.gerrit.server.update.BatchUpdateOp;
 import com.google.gerrit.server.update.ChangeContext;
@@ -56,6 +55,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
+@NoHttpd
 public class GetRelatedIT extends AbstractDaemonTest {
   private static final int MAX_TERMS = 10;
 
@@ -577,17 +577,6 @@
     assertRelated(cd.change().currentPatchSetId());
   }
 
-  private List<ChangeAndCommit> getRelated(PatchSet.Id ps) throws Exception {
-    return getRelated(ps.getParentKey(), ps.get());
-  }
-
-  private List<ChangeAndCommit> getRelated(Change.Id changeId, int ps) throws Exception {
-    String url = String.format("/changes/%d/revisions/%d/related", changeId.get(), ps);
-    RestResponse r = adminRestSession.get(url);
-    r.assertOK();
-    return newGson().fromJson(r.getReader(), RelatedInfo.class).changes;
-  }
-
   private RevCommit parseBody(RevCommit c) throws Exception {
     testRepo.getRevWalk().parseBody(c);
     return c;
@@ -601,9 +590,9 @@
     return Iterables.getOnlyElement(queryProvider.get().byCommit(c));
   }
 
-  private ChangeAndCommit changeAndCommit(
+  private RelatedChangeAndCommitInfo changeAndCommit(
       PatchSet.Id psId, ObjectId commitId, int currentRevisionNum) {
-    ChangeAndCommit result = new ChangeAndCommit();
+    RelatedChangeAndCommitInfo result = new RelatedChangeAndCommitInfo();
     result.project = project.get();
     result._changeNumber = psId.getParentKey().get();
     result.commit = new CommitInfo();
@@ -631,13 +620,14 @@
     }
   }
 
-  private void assertRelated(PatchSet.Id psId, ChangeAndCommit... expected) throws Exception {
-    List<ChangeAndCommit> actual = getRelated(psId);
+  private void assertRelated(PatchSet.Id psId, RelatedChangeAndCommitInfo... expected)
+      throws Exception {
+    List<RelatedChangeAndCommitInfo> actual = getRelated(psId);
     assertThat(actual).named("related to " + psId).hasSize(expected.length);
     for (int i = 0; i < actual.size(); i++) {
       String name = "index " + i + " related to " + psId;
-      ChangeAndCommit a = actual.get(i);
-      ChangeAndCommit e = expected[i];
+      RelatedChangeAndCommitInfo a = actual.get(i);
+      RelatedChangeAndCommitInfo e = expected[i];
       assertThat(a.project).named("project of " + name).isEqualTo(e.project);
       assertThat(a._changeNumber).named("change ID of " + name).isEqualTo(e._changeNumber);
       // Don't bother checking changeId; assume _changeNumber is sufficient.
diff --git a/javatests/com/google/gerrit/acceptance/server/mail/MailProcessorIT.java b/javatests/com/google/gerrit/acceptance/server/mail/MailProcessorIT.java
index 9ff2c05..b8380f5 100644
--- a/javatests/com/google/gerrit/acceptance/server/mail/MailProcessorIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/mail/MailProcessorIT.java
@@ -17,6 +17,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.common.collect.Iterables;
+import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.common.ChangeMessageInfo;
 import com.google.gerrit.extensions.common.CommentInfo;
@@ -33,6 +34,7 @@
 
 public class MailProcessorIT extends AbstractMailIT {
   @Inject private MailProcessor mailProcessor;
+  @Inject private AccountOperations accountOperations;
 
   @Test
   public void parseAndPersistChangeMessage() throws Exception {
@@ -163,16 +165,13 @@
     b.textContent(txt + textFooterForChange(changeInfo._number, ts));
 
     // Set account state to inactive
-    gApi.accounts().id("user").setActive(false);
+    accountOperations.account(user.id).forUpdate().inactive().update();
 
     mailProcessor.process(b.build());
     comments = gApi.changes().id(changeId).current().commentsAsList();
 
     // Check that comment size has not changed
     assertThat(comments).hasSize(2);
-
-    // Reset
-    gApi.accounts().id("user").setActive(true);
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/common/BUILD b/javatests/com/google/gerrit/common/BUILD
index c4f2c0a..9c5700e 100644
--- a/javatests/com/google/gerrit/common/BUILD
+++ b/javatests/com/google/gerrit/common/BUILD
@@ -1,8 +1,11 @@
 load("//tools/bzl:junit.bzl", "junit_tests")
 
 junit_tests(
-    name = "common_tests",
-    srcs = glob(["**/*.java"]),
+    name = "server_tests",
+    srcs = [
+        "AutoValueTest.java",
+        "VersionTest.java",
+    ],
     tags = ["no_windows"],
     deps = [
         "//java/com/google/gerrit/common:server",
diff --git a/javatests/com/google/gerrit/git/BUILD b/javatests/com/google/gerrit/git/BUILD
new file mode 100644
index 0000000..458bdf9
--- /dev/null
+++ b/javatests/com/google/gerrit/git/BUILD
@@ -0,0 +1,34 @@
+load("//tools/bzl:junit.bzl", "junit_tests")
+
+MEDIUM_TESTS = ["RefUpdateUtilRepoTest.java"]
+
+junit_tests(
+    name = "medium_tests",
+    size = "medium",
+    timeout = "short",
+    srcs = MEDIUM_TESTS,
+    tags = ["no_windows"],
+    deps = [
+        "//java/com/google/gerrit/git",
+        "//lib:guava",
+        "//lib:junit",
+        "//lib/jgit/org.eclipse.jgit:jgit",
+        "//lib/jgit/org.eclipse.jgit.junit:junit",
+        "//lib/truth",
+    ],
+)
+
+junit_tests(
+    name = "small_tests",
+    size = "small",
+    srcs = glob(
+        ["*.java"],
+        exclude = MEDIUM_TESTS,
+    ),
+    deps = [
+        "//java/com/google/gerrit/git",
+        "//lib:guava",
+        "//lib/jgit/org.eclipse.jgit:jgit",
+        "//lib/truth",
+    ],
+)
diff --git a/javatests/com/google/gerrit/git/RefUpdateUtilRepoTest.java b/javatests/com/google/gerrit/git/RefUpdateUtilRepoTest.java
new file mode 100644
index 0000000..99247b8
--- /dev/null
+++ b/javatests/com/google/gerrit/git/RefUpdateUtilRepoTest.java
@@ -0,0 +1,117 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.git;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.io.MoreFiles;
+import com.google.common.io.RecursiveDeleteOption;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
+import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
+import org.eclipse.jgit.internal.storage.file.FileRepository;
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.lib.Repository;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class RefUpdateUtilRepoTest {
+  public enum RepoSetup {
+    LOCAL_DISK {
+      @Override
+      Repository setUpRepo() throws Exception {
+        Path p = Files.createTempDirectory("gerrit_repo_");
+        try {
+          Repository repo = new FileRepository(p.toFile());
+          repo.create(true);
+          return repo;
+        } catch (Exception e) {
+          delete(p);
+          throw e;
+        }
+      }
+
+      @Override
+      void tearDownRepo(Repository repo) throws Exception {
+        delete(repo.getDirectory().toPath());
+      }
+
+      private void delete(Path p) throws Exception {
+        MoreFiles.deleteRecursively(p, RecursiveDeleteOption.ALLOW_INSECURE);
+      }
+    },
+
+    IN_MEMORY {
+      @Override
+      Repository setUpRepo() {
+        return new InMemoryRepository(new DfsRepositoryDescription("repo"));
+      }
+
+      @Override
+      void tearDownRepo(Repository repo) {}
+    };
+
+    abstract Repository setUpRepo() throws Exception;
+
+    abstract void tearDownRepo(Repository repo) throws Exception;
+  }
+
+  @Parameters(name = "{0}")
+  public static ImmutableList<RepoSetup[]> data() {
+    return ImmutableList.copyOf(new RepoSetup[][] {{RepoSetup.LOCAL_DISK}, {RepoSetup.IN_MEMORY}});
+  }
+
+  @Parameter public RepoSetup repoSetup;
+
+  private Repository repo;
+
+  @Before
+  public void setUp() throws Exception {
+    repo = repoSetup.setUpRepo();
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    if (repo != null) {
+      repoSetup.tearDownRepo(repo);
+      repo = null;
+    }
+  }
+
+  @Test
+  public void deleteRefNoOp() throws Exception {
+    String ref = "refs/heads/foo";
+    assertThat(repo.exactRef(ref)).isNull();
+    RefUpdateUtil.deleteChecked(repo, "refs/heads/foo");
+    assertThat(repo.exactRef(ref)).isNull();
+  }
+
+  @Test
+  public void deleteRef() throws Exception {
+    String ref = "refs/heads/foo";
+    new TestRepository<>(repo).branch(ref).commit().create();
+    assertThat(repo.exactRef(ref)).isNotNull();
+    RefUpdateUtil.deleteChecked(repo, "refs/heads/foo");
+    assertThat(repo.exactRef(ref)).isNull();
+  }
+}
diff --git a/javatests/com/google/gerrit/git/RefUpdateUtilTest.java b/javatests/com/google/gerrit/git/RefUpdateUtilTest.java
new file mode 100644
index 0000000..fe40fb4
--- /dev/null
+++ b/javatests/com/google/gerrit/git/RefUpdateUtilTest.java
@@ -0,0 +1,118 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.git;
+
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assert_;
+
+import com.google.common.collect.ImmutableList;
+import java.io.IOException;
+import java.util.function.Consumer;
+import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
+import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
+import org.eclipse.jgit.lib.BatchRefUpdate;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.transport.ReceiveCommand;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class RefUpdateUtilTest {
+  private static final Consumer<ReceiveCommand> OK = c -> c.setResult(ReceiveCommand.Result.OK);
+  private static final Consumer<ReceiveCommand> LOCK_FAILURE =
+      c -> c.setResult(ReceiveCommand.Result.LOCK_FAILURE);
+  private static final Consumer<ReceiveCommand> REJECTED =
+      c -> c.setResult(ReceiveCommand.Result.REJECTED_OTHER_REASON);
+  private static final Consumer<ReceiveCommand> ABORTED =
+      c -> {
+        c.setResult(ReceiveCommand.Result.NOT_ATTEMPTED);
+        ReceiveCommand.abort(ImmutableList.of(c));
+        checkState(
+            c.getResult() != ReceiveCommand.Result.NOT_ATTEMPTED
+                && c.getResult() != ReceiveCommand.Result.LOCK_FAILURE
+                && c.getResult() != ReceiveCommand.Result.OK,
+            "unexpected state after abort: %s",
+            c);
+      };
+
+  @Test
+  public void checkBatchRefUpdateResults() throws Exception {
+    checkResults();
+    checkResults(OK);
+    checkResults(OK, OK);
+
+    assertIoException(REJECTED);
+    assertIoException(OK, REJECTED);
+    assertIoException(LOCK_FAILURE, REJECTED);
+    assertIoException(LOCK_FAILURE, OK);
+    assertIoException(LOCK_FAILURE, REJECTED, OK);
+    assertIoException(LOCK_FAILURE, LOCK_FAILURE, REJECTED);
+    assertIoException(LOCK_FAILURE, ABORTED, REJECTED);
+    assertIoException(LOCK_FAILURE, ABORTED, OK);
+
+    assertLockFailureException(LOCK_FAILURE);
+    assertLockFailureException(LOCK_FAILURE, LOCK_FAILURE);
+    assertLockFailureException(LOCK_FAILURE, LOCK_FAILURE, ABORTED);
+    assertLockFailureException(LOCK_FAILURE, LOCK_FAILURE, ABORTED, ABORTED);
+    assertLockFailureException(ABORTED);
+    assertLockFailureException(ABORTED, ABORTED);
+  }
+
+  @SafeVarargs
+  private static void checkResults(Consumer<ReceiveCommand>... resultSetters) throws Exception {
+    RefUpdateUtil.checkResults(newBatchRefUpdate(resultSetters));
+  }
+
+  @SafeVarargs
+  private static void assertIoException(Consumer<ReceiveCommand>... resultSetters) {
+    try {
+      RefUpdateUtil.checkResults(newBatchRefUpdate(resultSetters));
+      assert_().fail("expected IOException");
+    } catch (IOException e) {
+      assertThat(e).isNotInstanceOf(LockFailureException.class);
+    }
+  }
+
+  @SafeVarargs
+  private static void assertLockFailureException(Consumer<ReceiveCommand>... resultSetters)
+      throws Exception {
+    try {
+      RefUpdateUtil.checkResults(newBatchRefUpdate(resultSetters));
+      assert_().fail("expected LockFailureException");
+    } catch (LockFailureException e) {
+      // Expected.
+    }
+  }
+
+  @SafeVarargs
+  private static BatchRefUpdate newBatchRefUpdate(Consumer<ReceiveCommand>... resultSetters) {
+    try (Repository repo = new InMemoryRepository(new DfsRepositoryDescription("repo"))) {
+      BatchRefUpdate bru = repo.getRefDatabase().newBatchUpdate();
+      for (int i = 0; i < resultSetters.length; i++) {
+        ReceiveCommand cmd =
+            new ReceiveCommand(
+                ObjectId.fromString(String.format("%039x1", i)),
+                ObjectId.fromString(String.format("%039x2", i)),
+                "refs/heads/branch" + i);
+        bru.addCommand(cmd);
+        resultSetters[i].accept(cmd);
+      }
+      return bru;
+    }
+  }
+}
diff --git a/javatests/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java b/javatests/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java
index 685f42d..689d786 100644
--- a/javatests/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java
+++ b/javatests/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java
@@ -41,7 +41,7 @@
 import com.google.gerrit.server.account.AccountsUpdate;
 import com.google.gerrit.server.account.AuthRequest;
 import com.google.gerrit.server.account.externalids.ExternalId;
-import com.google.gerrit.server.schema.SchemaCreator;
+import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
 import com.google.gerrit.server.util.RequestContext;
 import com.google.gerrit.server.util.ThreadLocalRequestContext;
 import com.google.gerrit.testing.InMemoryDatabase;
@@ -80,7 +80,7 @@
 
   @Inject private InMemoryDatabase schemaFactory;
 
-  @Inject private SchemaCreator schemaCreator;
+  @Inject private ReviewDbSchemaCreator schemaCreator;
 
   @Inject private ThreadLocalRequestContext requestContext;
 
diff --git a/javatests/com/google/gerrit/reviewdb/BUILD b/javatests/com/google/gerrit/reviewdb/BUILD
deleted file mode 100644
index 0fd140e..0000000
--- a/javatests/com/google/gerrit/reviewdb/BUILD
+++ /dev/null
@@ -1,14 +0,0 @@
-load("//tools/bzl:junit.bzl", "junit_tests")
-
-junit_tests(
-    name = "client_tests",
-    srcs = glob(["client/**/*.java"]),
-    deps = [
-        "//java/com/google/gerrit/reviewdb:client",
-        "//java/com/google/gerrit/server/project/testing:project-test-util",
-        "//java/com/google/gerrit/testing:gerrit-test-util",
-        "//lib:guava",
-        "//lib:gwtorm",
-        "//lib/truth",
-    ],
-)
diff --git a/javatests/com/google/gerrit/reviewdb/client/AccountGroupTest.java b/javatests/com/google/gerrit/reviewdb/client/AccountGroupTest.java
deleted file mode 100644
index 18a55bf..0000000
--- a/javatests/com/google/gerrit/reviewdb/client/AccountGroupTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (C) 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.reviewdb.client;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.gerrit.reviewdb.client.AccountGroup.UUID.fromRef;
-import static com.google.gerrit.reviewdb.client.AccountGroup.UUID.fromRefPart;
-
-import java.sql.Timestamp;
-import java.time.Instant;
-import java.time.LocalDateTime;
-import java.time.Month;
-import java.time.ZoneOffset;
-import org.junit.Test;
-
-public class AccountGroupTest {
-  private static final String TEST_UUID = "ccab3195282a8ce4f5014efa391e82d10f884c64";
-  private static final String TEST_SHARDED_UUID = TEST_UUID.substring(0, 2) + "/" + TEST_UUID;
-
-  @Test
-  public void auditCreationInstant() {
-    Instant instant = LocalDateTime.of(2009, Month.JUNE, 8, 19, 31).toInstant(ZoneOffset.UTC);
-    assertThat(AccountGroup.auditCreationInstantTs()).isEqualTo(Timestamp.from(instant));
-  }
-
-  @Test
-  public void parseRefName() {
-    assertThat(fromRef("refs/groups/" + TEST_SHARDED_UUID)).isEqualTo(uuid(TEST_UUID));
-    assertThat(fromRef("refs/groups/" + TEST_SHARDED_UUID + "-2"))
-        .isEqualTo(uuid(TEST_UUID + "-2"));
-    assertThat(fromRef("refs/groups/7e/7ec4775d")).isEqualTo(uuid("7ec4775d"));
-    assertThat(fromRef("refs/groups/fo/foo")).isEqualTo(uuid("foo"));
-
-    assertThat(fromRef(null)).isNull();
-    assertThat(fromRef("")).isNull();
-
-    // Missing prefix.
-    assertThat(fromRef(TEST_SHARDED_UUID)).isNull();
-
-    // Invalid shards.
-    assertThat(fromRef("refs/groups/c/" + TEST_UUID)).isNull();
-    assertThat(fromRef("refs/groups/cca/" + TEST_UUID)).isNull();
-
-    // Mismatched shard.
-    assertThat(fromRef("refs/groups/ca/" + TEST_UUID)).isNull();
-    assertThat(fromRef("refs/groups/64/" + TEST_UUID)).isNull();
-
-    // Wrong number of segments.
-    assertThat(fromRef("refs/groups/cc")).isNull();
-    assertThat(fromRef("refs/groups/" + TEST_SHARDED_UUID + "/1")).isNull();
-  }
-
-  @Test
-  public void parseRefNameParts() {
-    assertThat(fromRefPart(TEST_SHARDED_UUID)).isEqualTo(uuid(TEST_UUID));
-
-    // Mismatched shard.
-    assertThat(fromRefPart("ab/" + TEST_UUID)).isNull();
-  }
-
-  private AccountGroup.UUID uuid(String uuid) {
-    return new AccountGroup.UUID(uuid);
-  }
-}
diff --git a/javatests/com/google/gerrit/reviewdb/client/AccountTest.java b/javatests/com/google/gerrit/reviewdb/client/AccountTest.java
deleted file mode 100644
index 11a562f..0000000
--- a/javatests/com/google/gerrit/reviewdb/client/AccountTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.reviewdb.client;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.gerrit.reviewdb.client.Account.Id.fromRef;
-import static com.google.gerrit.reviewdb.client.Account.Id.fromRefPart;
-import static com.google.gerrit.reviewdb.client.Account.Id.fromRefSuffix;
-
-import org.junit.Test;
-
-public class AccountTest {
-  @Test
-  public void parseRefName() {
-    assertThat(fromRef("refs/users/01/1")).isEqualTo(id(1));
-    assertThat(fromRef("refs/users/01/1-drafts")).isEqualTo(id(1));
-    assertThat(fromRef("refs/users/01/1-drafts/2")).isEqualTo(id(1));
-    assertThat(fromRef("refs/users/01/1/edit/2")).isEqualTo(id(1));
-
-    assertThat(fromRef(null)).isNull();
-    assertThat(fromRef("")).isNull();
-
-    // Invalid characters.
-    assertThat(fromRef("refs/users/01a/1")).isNull();
-    assertThat(fromRef("refs/users/01/a1")).isNull();
-
-    // Mismatched shard.
-    assertThat(fromRef("refs/users/01/23")).isNull();
-
-    // Shard too short.
-    assertThat(fromRef("refs/users/1/1")).isNull();
-  }
-
-  @Test
-  public void parseDraftCommentsRefName() {
-    assertThat(fromRef("refs/draft-comments/35/135/1")).isEqualTo(id(1));
-    assertThat(fromRef("refs/draft-comments/35/135/1-foo/2")).isEqualTo(id(1));
-    assertThat(fromRef("refs/draft-comments/35/135/1/foo/2")).isEqualTo(id(1));
-
-    // Invalid characters.
-    assertThat(fromRef("refs/draft-comments/35a/135/1")).isNull();
-    assertThat(fromRef("refs/draft-comments/35/135a/1")).isNull();
-    assertThat(fromRef("refs/draft-comments/35/135/a1")).isNull();
-
-    // Mismatched shard.
-    assertThat(fromRef("refs/draft-comments/02/135/1")).isNull();
-
-    // Shard too short.
-    assertThat(fromRef("refs/draft-comments/2/2/1")).isNull();
-  }
-
-  @Test
-  public void parseStarredChangesRefName() {
-    assertThat(fromRef("refs/starred-changes/35/135/1")).isEqualTo(id(1));
-    assertThat(fromRef("refs/starred-changes/35/135/1-foo/2")).isEqualTo(id(1));
-    assertThat(fromRef("refs/starred-changes/35/135/1/foo/2")).isEqualTo(id(1));
-
-    // Invalid characters.
-    assertThat(fromRef("refs/starred-changes/35a/135/1")).isNull();
-    assertThat(fromRef("refs/starred-changes/35/135a/1")).isNull();
-    assertThat(fromRef("refs/starred-changes/35/135/a1")).isNull();
-
-    // Mismatched shard.
-    assertThat(fromRef("refs/starred-changes/02/135/1")).isNull();
-
-    // Shard too short.
-    assertThat(fromRef("refs/starred-changes/2/2/1")).isNull();
-  }
-
-  @Test
-  public void parseRefNameParts() {
-    assertThat(fromRefPart("01/1")).isEqualTo(id(1));
-    assertThat(fromRefPart("ab/cd")).isNull();
-  }
-
-  @Test
-  public void parseRefSuffix() {
-    assertThat(fromRefSuffix("12/34")).isEqualTo(id(34));
-    assertThat(fromRefSuffix("ab/cd")).isNull();
-  }
-
-  private Account.Id id(int n) {
-    return new Account.Id(n);
-  }
-}
diff --git a/javatests/com/google/gerrit/reviewdb/client/ChangeTest.java b/javatests/com/google/gerrit/reviewdb/client/ChangeTest.java
deleted file mode 100644
index 6d1d0a6..0000000
--- a/javatests/com/google/gerrit/reviewdb/client/ChangeTest.java
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.reviewdb.client;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
-import org.junit.Test;
-
-public class ChangeTest {
-  @Test
-  public void parseInvalidRefNames() {
-    assertNotRef(null);
-    assertNotRef("");
-    assertNotRef("01/1/1");
-    assertNotRef("HEAD");
-    assertNotRef("refs/tags/v1");
-  }
-
-  @Test
-  public void parsePatchSetRefNames() {
-    assertRef(1, "refs/changes/01/1/1");
-    assertRef(1234, "refs/changes/34/1234/56");
-
-    // Invalid characters.
-    assertNotRef("refs/changes/0x/1/1");
-    assertNotRef("refs/changes/01/x/1");
-    assertNotRef("refs/changes/01/1/x");
-
-    // Truncations.
-    assertNotRef("refs/changes/");
-    assertNotRef("refs/changes/1");
-    assertNotRef("refs/changes/01");
-    assertNotRef("refs/changes/01/");
-    assertNotRef("refs/changes/01/1/");
-    assertNotRef("refs/changes/01/1/1/");
-    assertNotRef("refs/changes/01//1/1");
-
-    // Leading zeroes.
-    assertNotRef("refs/changes/01/01/1");
-    assertNotRef("refs/changes/01/1/01");
-
-    // Mismatched last 2 digits.
-    assertNotRef("refs/changes/35/1234/56");
-
-    // Something other than patch set after change.
-    assertNotRef("refs/changes/34/1234/0");
-    assertNotRef("refs/changes/34/1234/foo");
-    assertNotRef("refs/changes/34/1234|56");
-    assertNotRef("refs/changes/34/1234foo");
-  }
-
-  @Test
-  public void parseEditRefNames() {
-    assertRef(5, "refs/users/34/1234/edit-5/1");
-    assertRef(5, "refs/users/34/1234/edit-5");
-    assertNotRef("refs/changes/34/1234/edit-5/1");
-    assertNotRef("refs/users/34/1234/EDIT-5/1");
-    assertNotRef("refs/users/34/1234");
-  }
-
-  @Test
-  public void parseChangeMetaRefNames() {
-    assertRef(1, "refs/changes/01/1/meta");
-    assertRef(1234, "refs/changes/34/1234/meta");
-
-    assertNotRef("refs/changes/01/1/met");
-    assertNotRef("refs/changes/01/1/META");
-    assertNotRef("refs/changes/01/1/1/meta");
-  }
-
-  @Test
-  public void parseRobotCommentRefNames() {
-    assertRef(1, "refs/changes/01/1/robot-comments");
-    assertRef(1234, "refs/changes/34/1234/robot-comments");
-
-    assertNotRef("refs/changes/01/1/robot-comment");
-    assertNotRef("refs/changes/01/1/ROBOT-COMMENTS");
-    assertNotRef("refs/changes/01/1/1/robot-comments");
-  }
-
-  @Test
-  public void parseStarredChangesRefNames() {
-    assertAllUsersRef(1, "refs/starred-changes/01/1/1001");
-    assertAllUsersRef(1234, "refs/starred-changes/34/1234/1001");
-
-    assertNotRef("refs/starred-changes/01/1/1001");
-    assertNotAllUsersRef(null);
-    assertNotAllUsersRef("refs/starred-changes/01/1/1xx1");
-    assertNotAllUsersRef("refs/starred-changes/01/1/");
-    assertNotAllUsersRef("refs/starred-changes/01/1");
-    assertNotAllUsersRef("refs/starred-changes/35/1234/1001");
-    assertNotAllUsersRef("refs/starred-changeS/01/1/1001");
-  }
-
-  @Test
-  public void parseDraftRefNames() {
-    assertAllUsersRef(1, "refs/draft-comments/01/1/1001");
-    assertAllUsersRef(1234, "refs/draft-comments/34/1234/1001");
-
-    assertNotRef("refs/draft-comments/01/1/1001");
-    assertNotAllUsersRef(null);
-    assertNotAllUsersRef("refs/draft-comments/01/1/1xx1");
-    assertNotAllUsersRef("refs/draft-comments/01/1/");
-    assertNotAllUsersRef("refs/draft-comments/01/1");
-    assertNotAllUsersRef("refs/draft-comments/35/1234/1001");
-    assertNotAllUsersRef("refs/draft-commentS/01/1/1001");
-  }
-
-  @Test
-  public void toRefPrefix() {
-    assertThat(new Change.Id(1).toRefPrefix()).isEqualTo("refs/changes/01/1/");
-    assertThat(new Change.Id(1234).toRefPrefix()).isEqualTo("refs/changes/34/1234/");
-  }
-
-  @Test
-  public void parseRefNameParts() {
-    assertRefPart(1, "01/1");
-
-    assertNotRefPart(null);
-    assertNotRefPart("");
-
-    // This method assumes that the common prefix "refs/changes/" was removed.
-    assertNotRefPart("refs/changes/01/1");
-
-    // Invalid characters.
-    assertNotRefPart("01a/1");
-    assertNotRefPart("01/a1");
-
-    // Mismatched shard.
-    assertNotRefPart("01/23");
-
-    // Shard too short.
-    assertNotRefPart("1/1");
-  }
-
-  private static void assertRef(int changeId, String refName) {
-    assertThat(Change.Id.fromRef(refName)).isEqualTo(new Change.Id(changeId));
-  }
-
-  private static void assertNotRef(String refName) {
-    assertThat(Change.Id.fromRef(refName)).isNull();
-  }
-
-  private static void assertAllUsersRef(int changeId, String refName) {
-    assertThat(Change.Id.fromAllUsersRef(refName)).isEqualTo(new Change.Id(changeId));
-  }
-
-  private static void assertNotAllUsersRef(String refName) {
-    assertThat(Change.Id.fromAllUsersRef(refName)).isNull();
-  }
-
-  private static void assertRefPart(int changeId, String refName) {
-    assertEquals(new Change.Id(changeId), Change.Id.fromRefPart(refName));
-  }
-
-  private static void assertNotRefPart(String refName) {
-    assertNull(Change.Id.fromRefPart(refName));
-  }
-}
diff --git a/javatests/com/google/gerrit/reviewdb/client/PatchSetApprovalTest.java b/javatests/com/google/gerrit/reviewdb/client/PatchSetApprovalTest.java
deleted file mode 100644
index 5e42ce0..0000000
--- a/javatests/com/google/gerrit/reviewdb/client/PatchSetApprovalTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.reviewdb.client;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.google.gerrit.testing.GerritBaseTests;
-import java.util.HashMap;
-import java.util.Map;
-import org.junit.Test;
-
-public class PatchSetApprovalTest extends GerritBaseTests {
-  @Test
-  public void keyEquality() {
-    PatchSetApproval.Key k1 =
-        new PatchSetApproval.Key(
-            new PatchSet.Id(new Change.Id(1), 2), new Account.Id(3), new LabelId("My-Label"));
-    PatchSetApproval.Key k2 =
-        new PatchSetApproval.Key(
-            new PatchSet.Id(new Change.Id(1), 2), new Account.Id(3), new LabelId("My-Label"));
-    PatchSetApproval.Key k3 =
-        new PatchSetApproval.Key(
-            new PatchSet.Id(new Change.Id(1), 2), new Account.Id(3), new LabelId("Other-Label"));
-
-    assertThat(k2).isEqualTo(k1);
-    assertThat(k3).isNotEqualTo(k1);
-    assertThat(k2.hashCode()).isEqualTo(k1.hashCode());
-    assertThat(k3.hashCode()).isNotEqualTo(k1.hashCode());
-
-    Map<PatchSetApproval.Key, String> map = new HashMap<>();
-    map.put(k1, "k1");
-    map.put(k2, "k2");
-    map.put(k3, "k3");
-    assertThat(map).containsKey(k1);
-    assertThat(map).containsKey(k2);
-    assertThat(map).containsKey(k3);
-    assertThat(map).containsEntry(k1, "k2");
-    assertThat(map).containsEntry(k2, "k2");
-    assertThat(map).containsEntry(k3, "k3");
-  }
-}
diff --git a/javatests/com/google/gerrit/reviewdb/client/PatchSetTest.java b/javatests/com/google/gerrit/reviewdb/client/PatchSetTest.java
deleted file mode 100644
index 51a405f..0000000
--- a/javatests/com/google/gerrit/reviewdb/client/PatchSetTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.reviewdb.client;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.gerrit.reviewdb.client.PatchSet.joinGroups;
-import static com.google.gerrit.reviewdb.client.PatchSet.splitGroups;
-
-import com.google.common.collect.ImmutableList;
-import org.junit.Test;
-
-public class PatchSetTest {
-  @Test
-  public void parseRefNames() {
-    assertRef(1, 1, "refs/changes/01/1/1");
-    assertRef(1234, 56, "refs/changes/34/1234/56");
-
-    // Not even close.
-    assertNotRef(null);
-    assertNotRef("");
-    assertNotRef("01/1/1");
-    assertNotRef("HEAD");
-    assertNotRef("refs/tags/v1");
-
-    // Invalid characters.
-    assertNotRef("refs/changes/0x/1/1");
-    assertNotRef("refs/changes/01/x/1");
-    assertNotRef("refs/changes/01/1/x");
-
-    // Truncations.
-    assertNotRef("refs/changes/");
-    assertNotRef("refs/changes/1");
-    assertNotRef("refs/changes/01");
-    assertNotRef("refs/changes/01/");
-    assertNotRef("refs/changes/01/1/");
-    assertNotRef("refs/changes/01/1/1/");
-    assertNotRef("refs/changes/01//1/1");
-
-    // Leading zeroes.
-    assertNotRef("refs/changes/01/01/1");
-    assertNotRef("refs/changes/01/1/01");
-
-    // Mismatched last 2 digits.
-    assertNotRef("refs/changes/35/1234/56");
-
-    // Something other than patch set after change.
-    assertNotRef("refs/changes/34/1234/0");
-    assertNotRef("refs/changes/34/1234/foo");
-    assertNotRef("refs/changes/34/1234|56");
-    assertNotRef("refs/changes/34/1234foo");
-  }
-
-  @Test
-  public void testSplitGroups() {
-    assertThat(splitGroups("")).containsExactly("");
-    assertThat(splitGroups("abcd")).containsExactly("abcd");
-    assertThat(splitGroups("ab,cd")).containsExactly("ab", "cd").inOrder();
-    assertThat(splitGroups("ab,")).containsExactly("ab", "").inOrder();
-    assertThat(splitGroups(",cd")).containsExactly("", "cd").inOrder();
-  }
-
-  @Test
-  public void testJoinGroups() {
-    assertThat(joinGroups(ImmutableList.of(""))).isEqualTo("");
-    assertThat(joinGroups(ImmutableList.of("abcd"))).isEqualTo("abcd");
-    assertThat(joinGroups(ImmutableList.of("ab", "cd"))).isEqualTo("ab,cd");
-    assertThat(joinGroups(ImmutableList.of("ab", ""))).isEqualTo("ab,");
-    assertThat(joinGroups(ImmutableList.of("", "cd"))).isEqualTo(",cd");
-  }
-
-  @Test
-  public void toRefName() {
-    assertThat(new PatchSet.Id(new Change.Id(1), 23).toRefName()).isEqualTo("refs/changes/01/1/23");
-    assertThat(new PatchSet.Id(new Change.Id(1234), 5).toRefName())
-        .isEqualTo("refs/changes/34/1234/5");
-  }
-
-  private static void assertRef(int changeId, int psId, String refName) {
-    assertThat(PatchSet.isChangeRef(refName)).isTrue();
-    assertThat(PatchSet.Id.fromRef(refName))
-        .isEqualTo(new PatchSet.Id(new Change.Id(changeId), psId));
-  }
-
-  private static void assertNotRef(String refName) {
-    assertThat(PatchSet.isChangeRef(refName)).isFalse();
-    assertThat(PatchSet.Id.fromRef(refName)).isNull();
-  }
-}
diff --git a/javatests/com/google/gerrit/reviewdb/client/RefNamesTest.java b/javatests/com/google/gerrit/reviewdb/client/RefNamesTest.java
deleted file mode 100644
index fa6a722..0000000
--- a/javatests/com/google/gerrit/reviewdb/client/RefNamesTest.java
+++ /dev/null
@@ -1,300 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.reviewdb.client;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.gerrit.reviewdb.client.RefNames.parseAfterShardedRefPart;
-import static com.google.gerrit.reviewdb.client.RefNames.parseRefSuffix;
-import static com.google.gerrit.reviewdb.client.RefNames.parseShardedRefPart;
-import static com.google.gerrit.reviewdb.client.RefNames.parseShardedUuidFromRefPart;
-import static com.google.gerrit.reviewdb.client.RefNames.skipShardedRefPart;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-public class RefNamesTest {
-  private static final String TEST_GROUP_UUID = "ccab3195282a8ce4f5014efa391e82d10f884c64";
-  private static final String TEST_SHARDED_GROUP_UUID =
-      TEST_GROUP_UUID.substring(0, 2) + "/" + TEST_GROUP_UUID;
-
-  @Rule public ExpectedException expectedException = ExpectedException.none();
-
-  private final Account.Id accountId = new Account.Id(1011123);
-  private final Change.Id changeId = new Change.Id(67473);
-  private final PatchSet.Id psId = new PatchSet.Id(changeId, 42);
-
-  @Test
-  public void fullName() throws Exception {
-    assertThat(RefNames.fullName(RefNames.REFS_CONFIG)).isEqualTo(RefNames.REFS_CONFIG);
-    assertThat(RefNames.fullName("refs/heads/master")).isEqualTo("refs/heads/master");
-    assertThat(RefNames.fullName("master")).isEqualTo("refs/heads/master");
-    assertThat(RefNames.fullName("refs/tags/v1.0")).isEqualTo("refs/tags/v1.0");
-    assertThat(RefNames.fullName("HEAD")).isEqualTo("HEAD");
-  }
-
-  @Test
-  public void changeRefs() throws Exception {
-    String changeMetaRef = RefNames.changeMetaRef(changeId);
-    assertThat(changeMetaRef).isEqualTo("refs/changes/73/67473/meta");
-    assertThat(RefNames.isNoteDbMetaRef(changeMetaRef)).isTrue();
-
-    String robotCommentsRef = RefNames.robotCommentsRef(changeId);
-    assertThat(robotCommentsRef).isEqualTo("refs/changes/73/67473/robot-comments");
-    assertThat(RefNames.isNoteDbMetaRef(robotCommentsRef)).isTrue();
-  }
-
-  @Test
-  public void refForGroupIsSharded() throws Exception {
-    AccountGroup.UUID groupUuid = new AccountGroup.UUID("ABCDEFG");
-    String groupRef = RefNames.refsGroups(groupUuid);
-    assertThat(groupRef).isEqualTo("refs/groups/AB/ABCDEFG");
-  }
-
-  @Test
-  public void refForGroupWithUuidLessThanTwoCharsIsRejected() throws Exception {
-    AccountGroup.UUID groupUuid = new AccountGroup.UUID("A");
-    expectedException.expect(IllegalArgumentException.class);
-    RefNames.refsGroups(groupUuid);
-  }
-
-  @Test
-  public void refForDeletedGroupIsSharded() throws Exception {
-    AccountGroup.UUID groupUuid = new AccountGroup.UUID("ABCDEFG");
-    String groupRef = RefNames.refsDeletedGroups(groupUuid);
-    assertThat(groupRef).isEqualTo("refs/deleted-groups/AB/ABCDEFG");
-  }
-
-  @Test
-  public void refForDeletedGroupWithUuidLessThanTwoCharsIsRejected() throws Exception {
-    AccountGroup.UUID groupUuid = new AccountGroup.UUID("A");
-    expectedException.expect(IllegalArgumentException.class);
-    RefNames.refsDeletedGroups(groupUuid);
-  }
-
-  @Test
-  public void refsUsers() throws Exception {
-    assertThat(RefNames.refsUsers(accountId)).isEqualTo("refs/users/23/1011123");
-  }
-
-  @Test
-  public void refsDraftComments() throws Exception {
-    assertThat(RefNames.refsDraftComments(changeId, accountId))
-        .isEqualTo("refs/draft-comments/73/67473/1011123");
-  }
-
-  @Test
-  public void refsDraftCommentsPrefix() throws Exception {
-    assertThat(RefNames.refsDraftCommentsPrefix(changeId))
-        .isEqualTo("refs/draft-comments/73/67473/");
-  }
-
-  @Test
-  public void refsStarredChanges() throws Exception {
-    assertThat(RefNames.refsStarredChanges(changeId, accountId))
-        .isEqualTo("refs/starred-changes/73/67473/1011123");
-  }
-
-  @Test
-  public void refsStarredChangesPrefix() throws Exception {
-    assertThat(RefNames.refsStarredChangesPrefix(changeId))
-        .isEqualTo("refs/starred-changes/73/67473/");
-  }
-
-  @Test
-  public void refsEdit() throws Exception {
-    assertThat(RefNames.refsEdit(accountId, changeId, psId))
-        .isEqualTo("refs/users/23/1011123/edit-67473/42");
-  }
-
-  @Test
-  public void isRefsEdit() throws Exception {
-    assertThat(RefNames.isRefsEdit("refs/users/23/1011123/edit-67473/42")).isTrue();
-
-    // user ref, but no edit ref
-    assertThat(RefNames.isRefsEdit("refs/users/23/1011123")).isFalse();
-
-    // other ref
-    assertThat(RefNames.isRefsEdit("refs/heads/master")).isFalse();
-  }
-
-  @Test
-  public void isRefsUsers() throws Exception {
-    assertThat(RefNames.isRefsUsers("refs/users/23/1011123")).isTrue();
-    assertThat(RefNames.isRefsUsers("refs/users/default")).isTrue();
-    assertThat(RefNames.isRefsUsers("refs/users/23/1011123/edit-67473/42")).isTrue();
-
-    assertThat(RefNames.isRefsUsers("refs/heads/master")).isFalse();
-    assertThat(RefNames.isRefsUsers("refs/groups/" + TEST_SHARDED_GROUP_UUID)).isFalse();
-  }
-
-  @Test
-  public void isRefsGroups() throws Exception {
-    assertThat(RefNames.isRefsGroups("refs/groups/" + TEST_SHARDED_GROUP_UUID)).isTrue();
-
-    assertThat(RefNames.isRefsGroups("refs/heads/master")).isFalse();
-    assertThat(RefNames.isRefsGroups("refs/users/23/1011123")).isFalse();
-    assertThat(RefNames.isRefsGroups(RefNames.REFS_GROUPNAMES)).isFalse();
-    assertThat(RefNames.isRefsGroups("refs/deleted-groups/" + TEST_SHARDED_GROUP_UUID)).isFalse();
-  }
-
-  @Test
-  public void isRefsDeletedGroups() throws Exception {
-    assertThat(RefNames.isRefsDeletedGroups("refs/deleted-groups/" + TEST_SHARDED_GROUP_UUID))
-        .isTrue();
-
-    assertThat(RefNames.isRefsDeletedGroups("refs/heads/master")).isFalse();
-    assertThat(RefNames.isRefsDeletedGroups("refs/users/23/1011123")).isFalse();
-    assertThat(RefNames.isRefsDeletedGroups(RefNames.REFS_GROUPNAMES)).isFalse();
-    assertThat(RefNames.isRefsDeletedGroups("refs/groups/" + TEST_SHARDED_GROUP_UUID)).isFalse();
-  }
-
-  @Test
-  public void isGroupRef() throws Exception {
-    assertThat(RefNames.isGroupRef("refs/groups/" + TEST_SHARDED_GROUP_UUID)).isTrue();
-    assertThat(RefNames.isGroupRef("refs/deleted-groups/" + TEST_SHARDED_GROUP_UUID)).isTrue();
-    assertThat(RefNames.isGroupRef(RefNames.REFS_GROUPNAMES)).isTrue();
-
-    assertThat(RefNames.isGroupRef("refs/heads/master")).isFalse();
-    assertThat(RefNames.isGroupRef("refs/users/23/1011123")).isFalse();
-  }
-
-  @Test
-  public void parseShardedRefsPart() throws Exception {
-    assertThat(parseShardedRefPart("01/1")).isEqualTo(1);
-    assertThat(parseShardedRefPart("01/1-drafts")).isEqualTo(1);
-    assertThat(parseShardedRefPart("01/1-drafts/2")).isEqualTo(1);
-
-    assertThat(parseShardedRefPart(null)).isNull();
-    assertThat(parseShardedRefPart("")).isNull();
-
-    // Prefix not stripped.
-    assertThat(parseShardedRefPart("refs/users/01/1")).isNull();
-
-    // Invalid characters.
-    assertThat(parseShardedRefPart("01a/1")).isNull();
-    assertThat(parseShardedRefPart("01/a1")).isNull();
-
-    // Mismatched shard.
-    assertThat(parseShardedRefPart("01/23")).isNull();
-
-    // Shard too short.
-    assertThat(parseShardedRefPart("1/1")).isNull();
-  }
-
-  @Test
-  public void parseShardedUuidFromRefsPart() throws Exception {
-    assertThat(parseShardedUuidFromRefPart(TEST_SHARDED_GROUP_UUID)).isEqualTo(TEST_GROUP_UUID);
-    assertThat(parseShardedUuidFromRefPart(TEST_SHARDED_GROUP_UUID + "-2"))
-        .isEqualTo(TEST_GROUP_UUID + "-2");
-    assertThat(parseShardedUuidFromRefPart("7e/7ec4775d")).isEqualTo("7ec4775d");
-    assertThat(parseShardedUuidFromRefPart("fo/foo")).isEqualTo("foo");
-
-    assertThat(parseShardedUuidFromRefPart(null)).isNull();
-    assertThat(parseShardedUuidFromRefPart("")).isNull();
-
-    // Prefix not stripped.
-    assertThat(parseShardedUuidFromRefPart("refs/groups/" + TEST_SHARDED_GROUP_UUID)).isNull();
-
-    // Invalid shards.
-    assertThat(parseShardedUuidFromRefPart("c/" + TEST_GROUP_UUID)).isNull();
-    assertThat(parseShardedUuidFromRefPart("cca/" + TEST_GROUP_UUID)).isNull();
-
-    // Mismatched shard.
-    assertThat(parseShardedUuidFromRefPart("ca/" + TEST_GROUP_UUID)).isNull();
-    assertThat(parseShardedUuidFromRefPart("64/" + TEST_GROUP_UUID)).isNull();
-
-    // Wrong number of segments.
-    assertThat(parseShardedUuidFromRefPart("cc")).isNull();
-    assertThat(parseShardedUuidFromRefPart(TEST_SHARDED_GROUP_UUID + "/1")).isNull();
-  }
-
-  @Test
-  public void skipShardedRefsPart() throws Exception {
-    assertThat(skipShardedRefPart("01/1")).isEqualTo("");
-    assertThat(skipShardedRefPart("01/1/")).isEqualTo("/");
-    assertThat(skipShardedRefPart("01/1/2")).isEqualTo("/2");
-    assertThat(skipShardedRefPart("01/1-edit")).isEqualTo("-edit");
-
-    assertThat(skipShardedRefPart(null)).isNull();
-    assertThat(skipShardedRefPart("")).isNull();
-
-    // Prefix not stripped.
-    assertThat(skipShardedRefPart("refs/draft-comments/01/1/2")).isNull();
-
-    // Invalid characters.
-    assertThat(skipShardedRefPart("01a/1/2")).isNull();
-    assertThat(skipShardedRefPart("01a/a1/2")).isNull();
-
-    // Mismatched shard.
-    assertThat(skipShardedRefPart("01/23/2")).isNull();
-
-    // Shard too short.
-    assertThat(skipShardedRefPart("1/1")).isNull();
-  }
-
-  @Test
-  public void parseAfterShardedRefsPart() throws Exception {
-    assertThat(parseAfterShardedRefPart("01/1/2")).isEqualTo(2);
-    assertThat(parseAfterShardedRefPart("01/1/2/4")).isEqualTo(2);
-    assertThat(parseAfterShardedRefPart("01/1/2-edit")).isEqualTo(2);
-
-    assertThat(parseAfterShardedRefPart(null)).isNull();
-    assertThat(parseAfterShardedRefPart("")).isNull();
-
-    // No ID after sharded ref part
-    assertThat(parseAfterShardedRefPart("01/1")).isNull();
-    assertThat(parseAfterShardedRefPart("01/1/")).isNull();
-    assertThat(parseAfterShardedRefPart("01/1/a")).isNull();
-
-    // Prefix not stripped.
-    assertThat(parseAfterShardedRefPart("refs/draft-comments/01/1/2")).isNull();
-
-    // Invalid characters.
-    assertThat(parseAfterShardedRefPart("01a/1/2")).isNull();
-    assertThat(parseAfterShardedRefPart("01a/a1/2")).isNull();
-
-    // Mismatched shard.
-    assertThat(parseAfterShardedRefPart("01/23/2")).isNull();
-
-    // Shard too short.
-    assertThat(parseAfterShardedRefPart("1/1")).isNull();
-  }
-
-  @Test
-  public void testParseRefSuffix() throws Exception {
-    assertThat(parseRefSuffix("1/2/34")).isEqualTo(34);
-    assertThat(parseRefSuffix("/34")).isEqualTo(34);
-
-    assertThat(parseRefSuffix(null)).isNull();
-    assertThat(parseRefSuffix("")).isNull();
-    assertThat(parseRefSuffix("34")).isNull();
-    assertThat(parseRefSuffix("12/ab")).isNull();
-    assertThat(parseRefSuffix("12/a4")).isNull();
-    assertThat(parseRefSuffix("12/4a")).isNull();
-    assertThat(parseRefSuffix("a4")).isNull();
-    assertThat(parseRefSuffix("4a")).isNull();
-  }
-
-  @Test
-  public void shard() throws Exception {
-    assertThat(RefNames.shard(1011123)).isEqualTo("23/1011123");
-    assertThat(RefNames.shard(537)).isEqualTo("37/537");
-    assertThat(RefNames.shard(12)).isEqualTo("12/12");
-    assertThat(RefNames.shard(0)).isEqualTo("00/0");
-    assertThat(RefNames.shard(1)).isEqualTo("01/1");
-    assertThat(RefNames.shard(-1)).isNull();
-  }
-}
diff --git a/javatests/com/google/gerrit/server/BUILD b/javatests/com/google/gerrit/server/BUILD
index 8749b7a..88edc2e 100644
--- a/javatests/com/google/gerrit/server/BUILD
+++ b/javatests/com/google/gerrit/server/BUILD
@@ -38,6 +38,7 @@
         "//java/com/google/gerrit/common:server",
         "//java/com/google/gerrit/extensions:api",
         "//java/com/google/gerrit/extensions/common/testing:common-test-util",
+        "//java/com/google/gerrit/git",
         "//java/com/google/gerrit/index",
         "//java/com/google/gerrit/index:query_exception",
         "//java/com/google/gerrit/lifecycle",
diff --git a/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java b/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java
index 5a067f1..982bd14 100644
--- a/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java
+++ b/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java
@@ -44,7 +44,7 @@
 import com.google.gerrit.server.notedb.ChangeNotes;
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.project.ProjectConfig;
-import com.google.gerrit.server.schema.SchemaCreator;
+import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
 import com.google.gerrit.server.util.RequestContext;
 import com.google.gerrit.server.util.ThreadLocalRequestContext;
 import com.google.gerrit.server.util.time.TimeUtil;
@@ -71,9 +71,10 @@
   @Inject private LabelNormalizer norm;
   @Inject private MetaDataUpdate.User metaDataUpdateFactory;
   @Inject private ProjectCache projectCache;
-  @Inject private SchemaCreator schemaCreator;
+  @Inject private ReviewDbSchemaCreator schemaCreator;
   @Inject protected ThreadLocalRequestContext requestContext;
   @Inject private ChangeNotes.Factory changeNotesFactory;
+  @Inject private ProjectConfig.Factory projectConfigFactory;
 
   private LifecycleManager lifecycle;
   private ReviewDb db;
@@ -198,7 +199,7 @@
 
   private ProjectConfig loadAllProjects() throws Exception {
     try (Repository repo = repoManager.openRepository(allProjects)) {
-      ProjectConfig pc = new ProjectConfig(allProjects);
+      ProjectConfig pc = projectConfigFactory.create(allProjects);
       pc.load(repo);
       return pc;
     }
diff --git a/javatests/com/google/gerrit/server/config/RepositoryConfigTest.java b/javatests/com/google/gerrit/server/config/RepositoryConfigTest.java
index 2edcf7c..3da35b2 100644
--- a/javatests/com/google/gerrit/server/config/RepositoryConfigTest.java
+++ b/javatests/com/google/gerrit/server/config/RepositoryConfigTest.java
@@ -19,7 +19,7 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.gerrit.extensions.client.SubmitType;
-import com.google.gerrit.reviewdb.client.Project.NameKey;
+import com.google.gerrit.reviewdb.client.Project;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.List;
@@ -41,35 +41,35 @@
   @Test
   public void defaultSubmitTypeWhenNotConfigured() {
     // Check expected value explicitly rather than depending on constant.
-    assertThat(repoCfg.getDefaultSubmitType(new NameKey("someProject")))
+    assertThat(repoCfg.getDefaultSubmitType(new Project.NameKey("someProject")))
         .isEqualTo(SubmitType.INHERIT);
   }
 
   @Test
   public void defaultSubmitTypeForStarFilter() {
     configureDefaultSubmitType("*", SubmitType.CHERRY_PICK);
-    assertThat(repoCfg.getDefaultSubmitType(new NameKey("someProject")))
+    assertThat(repoCfg.getDefaultSubmitType(new Project.NameKey("someProject")))
         .isEqualTo(SubmitType.CHERRY_PICK);
 
     configureDefaultSubmitType("*", SubmitType.FAST_FORWARD_ONLY);
-    assertThat(repoCfg.getDefaultSubmitType(new NameKey("someProject")))
+    assertThat(repoCfg.getDefaultSubmitType(new Project.NameKey("someProject")))
         .isEqualTo(SubmitType.FAST_FORWARD_ONLY);
 
     configureDefaultSubmitType("*", SubmitType.REBASE_IF_NECESSARY);
-    assertThat(repoCfg.getDefaultSubmitType(new NameKey("someProject")))
+    assertThat(repoCfg.getDefaultSubmitType(new Project.NameKey("someProject")))
         .isEqualTo(SubmitType.REBASE_IF_NECESSARY);
 
     configureDefaultSubmitType("*", SubmitType.REBASE_ALWAYS);
-    assertThat(repoCfg.getDefaultSubmitType(new NameKey("someProject")))
+    assertThat(repoCfg.getDefaultSubmitType(new Project.NameKey("someProject")))
         .isEqualTo(SubmitType.REBASE_ALWAYS);
   }
 
   @Test
   public void defaultSubmitTypeForSpecificFilter() {
     configureDefaultSubmitType("someProject", SubmitType.CHERRY_PICK);
-    assertThat(repoCfg.getDefaultSubmitType(new NameKey("someOtherProject")))
+    assertThat(repoCfg.getDefaultSubmitType(new Project.NameKey("someOtherProject")))
         .isEqualTo(RepositoryConfig.DEFAULT_SUBMIT_TYPE);
-    assertThat(repoCfg.getDefaultSubmitType(new NameKey("someProject")))
+    assertThat(repoCfg.getDefaultSubmitType(new Project.NameKey("someProject")))
         .isEqualTo(SubmitType.CHERRY_PICK);
   }
 
@@ -79,13 +79,13 @@
     configureDefaultSubmitType("somePath/*", SubmitType.CHERRY_PICK);
     configureDefaultSubmitType("*", SubmitType.MERGE_ALWAYS);
 
-    assertThat(repoCfg.getDefaultSubmitType(new NameKey("someProject")))
+    assertThat(repoCfg.getDefaultSubmitType(new Project.NameKey("someProject")))
         .isEqualTo(SubmitType.MERGE_ALWAYS);
 
-    assertThat(repoCfg.getDefaultSubmitType(new NameKey("somePath/someProject")))
+    assertThat(repoCfg.getDefaultSubmitType(new Project.NameKey("somePath/someProject")))
         .isEqualTo(SubmitType.CHERRY_PICK);
 
-    assertThat(repoCfg.getDefaultSubmitType(new NameKey("somePath/somePath/someProject")))
+    assertThat(repoCfg.getDefaultSubmitType(new Project.NameKey("somePath/somePath/someProject")))
         .isEqualTo(SubmitType.REBASE_IF_NECESSARY);
   }
 
@@ -99,14 +99,14 @@
 
   @Test
   public void ownerGroupsWhenNotConfigured() {
-    assertThat(repoCfg.getOwnerGroups(new NameKey("someProject"))).isEmpty();
+    assertThat(repoCfg.getOwnerGroups(new Project.NameKey("someProject"))).isEmpty();
   }
 
   @Test
   public void ownerGroupsForStarFilter() {
     ImmutableList<String> ownerGroups = ImmutableList.of("group1", "group2");
     configureOwnerGroups("*", ownerGroups);
-    assertThat(repoCfg.getOwnerGroups(new NameKey("someProject")))
+    assertThat(repoCfg.getOwnerGroups(new Project.NameKey("someProject")))
         .containsExactlyElementsIn(ownerGroups);
   }
 
@@ -114,8 +114,8 @@
   public void ownerGroupsForSpecificFilter() {
     ImmutableList<String> ownerGroups = ImmutableList.of("group1", "group2");
     configureOwnerGroups("someProject", ownerGroups);
-    assertThat(repoCfg.getOwnerGroups(new NameKey("someOtherProject"))).isEmpty();
-    assertThat(repoCfg.getOwnerGroups(new NameKey("someProject")))
+    assertThat(repoCfg.getOwnerGroups(new Project.NameKey("someOtherProject"))).isEmpty();
+    assertThat(repoCfg.getOwnerGroups(new Project.NameKey("someProject")))
         .containsExactlyElementsIn(ownerGroups);
   }
 
@@ -129,13 +129,13 @@
     configureOwnerGroups("somePath/*", ownerGroups2);
     configureOwnerGroups("somePath/somePath/*", ownerGroups3);
 
-    assertThat(repoCfg.getOwnerGroups(new NameKey("someProject")))
+    assertThat(repoCfg.getOwnerGroups(new Project.NameKey("someProject")))
         .containsExactlyElementsIn(ownerGroups1);
 
-    assertThat(repoCfg.getOwnerGroups(new NameKey("somePath/someProject")))
+    assertThat(repoCfg.getOwnerGroups(new Project.NameKey("somePath/someProject")))
         .containsExactlyElementsIn(ownerGroups2);
 
-    assertThat(repoCfg.getOwnerGroups(new NameKey("somePath/somePath/someProject")))
+    assertThat(repoCfg.getOwnerGroups(new Project.NameKey("somePath/somePath/someProject")))
         .containsExactlyElementsIn(ownerGroups3);
   }
 
@@ -149,22 +149,24 @@
 
   @Test
   public void basePathWhenNotConfigured() {
-    assertThat(repoCfg.getBasePath(new NameKey("someProject"))).isNull();
+    assertThat(repoCfg.getBasePath(new Project.NameKey("someProject"))).isNull();
   }
 
   @Test
   public void basePathForStarFilter() {
     String basePath = "/someAbsolutePath/someDirectory";
     configureBasePath("*", basePath);
-    assertThat(repoCfg.getBasePath(new NameKey("someProject")).toString()).isEqualTo(basePath);
+    assertThat(repoCfg.getBasePath(new Project.NameKey("someProject")).toString())
+        .isEqualTo(basePath);
   }
 
   @Test
   public void basePathForSpecificFilter() {
     String basePath = "/someAbsolutePath/someDirectory";
     configureBasePath("someProject", basePath);
-    assertThat(repoCfg.getBasePath(new NameKey("someOtherProject"))).isNull();
-    assertThat(repoCfg.getBasePath(new NameKey("someProject")).toString()).isEqualTo(basePath);
+    assertThat(repoCfg.getBasePath(new Project.NameKey("someOtherProject"))).isNull();
+    assertThat(repoCfg.getBasePath(new Project.NameKey("someProject")).toString())
+        .isEqualTo(basePath);
   }
 
   @Test
@@ -179,12 +181,14 @@
     configureBasePath("project/*", basePath3);
     configureBasePath("*", basePath4);
 
-    assertThat(repoCfg.getBasePath(new NameKey("project1")).toString()).isEqualTo(basePath1);
-    assertThat(repoCfg.getBasePath(new NameKey("project/project/someProject")).toString())
+    assertThat(repoCfg.getBasePath(new Project.NameKey("project1")).toString())
+        .isEqualTo(basePath1);
+    assertThat(repoCfg.getBasePath(new Project.NameKey("project/project/someProject")).toString())
         .isEqualTo(basePath2);
-    assertThat(repoCfg.getBasePath(new NameKey("project/someProject")).toString())
+    assertThat(repoCfg.getBasePath(new Project.NameKey("project/someProject")).toString())
         .isEqualTo(basePath3);
-    assertThat(repoCfg.getBasePath(new NameKey("someProject")).toString()).isEqualTo(basePath4);
+    assertThat(repoCfg.getBasePath(new Project.NameKey("someProject")).toString())
+        .isEqualTo(basePath4);
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/server/git/meta/VersionedMetaDataTest.java b/javatests/com/google/gerrit/server/git/meta/VersionedMetaDataTest.java
index 7e12439..7ed6c50 100644
--- a/javatests/com/google/gerrit/server/git/meta/VersionedMetaDataTest.java
+++ b/javatests/com/google/gerrit/server/git/meta/VersionedMetaDataTest.java
@@ -22,10 +22,10 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Streams;
 import com.google.gerrit.common.Nullable;
+import com.google.gerrit.git.RefUpdateUtil;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
 import com.google.gerrit.server.git.meta.VersionedMetaData.BatchMetaDataUpdate;
-import com.google.gerrit.server.update.RefUpdateUtil;
 import com.google.gerrit.server.util.time.TimeUtil;
 import com.google.gerrit.testing.TestTimeUtil;
 import java.io.IOException;
diff --git a/javatests/com/google/gerrit/server/group/db/BUILD b/javatests/com/google/gerrit/server/group/db/BUILD
index f3dd5d6..d02fa1b 100644
--- a/javatests/com/google/gerrit/server/group/db/BUILD
+++ b/javatests/com/google/gerrit/server/group/db/BUILD
@@ -10,6 +10,7 @@
         "//java/com/google/gerrit/common/data/testing:common-data-test-util",
         "//java/com/google/gerrit/extensions:api",
         "//java/com/google/gerrit/extensions/common/testing:common-test-util",
+        "//java/com/google/gerrit/git",
         "//java/com/google/gerrit/reviewdb:server",
         "//java/com/google/gerrit/server",
         "//java/com/google/gerrit/server/group/db/testing",
diff --git a/javatests/com/google/gerrit/server/group/db/GroupNameNotesTest.java b/javatests/com/google/gerrit/server/group/db/GroupNameNotesTest.java
index 42d01e2..7364c95 100644
--- a/javatests/com/google/gerrit/server/group/db/GroupNameNotesTest.java
+++ b/javatests/com/google/gerrit/server/group/db/GroupNameNotesTest.java
@@ -27,6 +27,7 @@
 import com.google.gerrit.common.data.testing.GroupReferenceSubject;
 import com.google.gerrit.extensions.common.CommitInfo;
 import com.google.gerrit.extensions.common.testing.CommitInfoSubject;
+import com.google.gerrit.git.RefUpdateUtil;
 import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.reviewdb.client.RefNames;
@@ -34,7 +35,6 @@
 import com.google.gerrit.server.config.AllUsersNameProvider;
 import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
 import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gerrit.server.update.RefUpdateUtil;
 import com.google.gerrit.server.util.time.TimeUtil;
 import com.google.gerrit.testing.GitTestUtil;
 import com.google.gerrit.testing.TestTimeUtil;
diff --git a/javatests/com/google/gerrit/server/notedb/RepoSequenceTest.java b/javatests/com/google/gerrit/server/notedb/RepoSequenceTest.java
index a21f5ba..64fd875 100644
--- a/javatests/com/google/gerrit/server/notedb/RepoSequenceTest.java
+++ b/javatests/com/google/gerrit/server/notedb/RepoSequenceTest.java
@@ -46,7 +46,7 @@
 
 public class RepoSequenceTest {
   // Don't sleep in tests.
-  private static final Retryer<RefUpdate.Result> RETRYER =
+  private static final Retryer<RefUpdate> RETRYER =
       RepoSequence.retryerBuilder().withBlockStrategy(t -> {}).build();
 
   @Rule public ExpectedException exception = ExpectedException.none();
@@ -200,11 +200,11 @@
             1,
             10,
             () -> writeBlob("id", Integer.toString(bgCounter.getAndAdd(1000))),
-            RetryerBuilder.<RefUpdate.Result>newBuilder()
+            RetryerBuilder.<RefUpdate>newBuilder()
                 .withStopStrategy(StopStrategies.stopAfterAttempt(3))
                 .build());
     exception.expect(OrmException.class);
-    exception.expectMessage("failed to update refs/sequences/id: LOCK_FAILURE");
+    exception.expectMessage("Failed to update refs/sequences/id: LOCK_FAILURE");
     s.next();
   }
 
@@ -335,11 +335,11 @@
             1,
             10,
             () -> writeBlob("id", Integer.toString(bgCounter.getAndAdd(1000))),
-            RetryerBuilder.<RefUpdate.Result>newBuilder()
+            RetryerBuilder.<RefUpdate>newBuilder()
                 .withStopStrategy(StopStrategies.stopAfterAttempt(3))
                 .build());
     exception.expect(OrmException.class);
-    exception.expectMessage("failed to update refs/sequences/id: LOCK_FAILURE");
+    exception.expectMessage("Failed to update refs/sequences/id: LOCK_FAILURE");
     s.increaseTo(2);
   }
 
@@ -352,7 +352,7 @@
       final int start,
       int batchSize,
       Runnable afterReadRef,
-      Retryer<RefUpdate.Result> retryer) {
+      Retryer<RefUpdate> retryer) {
     return new RepoSequence(
         repoManager,
         GitReferenceUpdated.DISABLED,
diff --git a/javatests/com/google/gerrit/server/permissions/RefControlTest.java b/javatests/com/google/gerrit/server/permissions/RefControlTest.java
index a3f9f93..38e9578 100644
--- a/javatests/com/google/gerrit/server/permissions/RefControlTest.java
+++ b/javatests/com/google/gerrit/server/permissions/RefControlTest.java
@@ -63,7 +63,7 @@
 import com.google.gerrit.server.project.ProjectState;
 import com.google.gerrit.server.project.RefPattern;
 import com.google.gerrit.server.project.testing.Util;
-import com.google.gerrit.server.schema.SchemaCreator;
+import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
 import com.google.gerrit.server.util.RequestContext;
 import com.google.gerrit.server.util.ThreadLocalRequestContext;
 import com.google.gerrit.testing.InMemoryDatabase;
@@ -199,13 +199,14 @@
 
   @Inject private PermissionBackend permissionBackend;
   @Inject private CapabilityCollection.Factory capabilityCollectionFactory;
-  @Inject private SchemaCreator schemaCreator;
+  @Inject private ReviewDbSchemaCreator schemaCreator;
   @Inject private SingleVersionListener singleVersionListener;
   @Inject private InMemoryDatabase schemaFactory;
   @Inject private ThreadLocalRequestContext requestContext;
   @Inject private DefaultRefFilter.Factory refFilterFactory;
   @Inject private TransferConfig transferConfig;
   @Inject private MetricMaker metricMaker;
+  @Inject private ProjectConfig.Factory projectConfigFactory;
 
   @Before
   public void setUp() throws Exception {
@@ -274,7 +275,8 @@
 
     try {
       Repository repo = repoManager.createRepository(allProjectsName);
-      ProjectConfig allProjects = new ProjectConfig(new Project.NameKey(allProjectsName.get()));
+      ProjectConfig allProjects =
+          projectConfigFactory.create(new Project.NameKey(allProjectsName.get()));
       allProjects.load(repo);
       LabelType cr = Util.codeReview();
       allProjects.getLabelSections().put(cr.getName(), cr);
@@ -295,11 +297,11 @@
         CacheBuilder.newBuilder().build();
     sectionSorter = new PermissionCollection.Factory(new SectionSortCache(c), metricMaker);
 
-    parent = new ProjectConfig(parentKey);
+    parent = projectConfigFactory.create(parentKey);
     parent.load(newRepository(parentKey));
     add(parent);
 
-    local = new ProjectConfig(localKey);
+    local = projectConfigFactory.create(localKey);
     local.load(newRepository(localKey));
     add(local);
     local.getProject().setParentName(parentKey);
@@ -455,7 +457,7 @@
     allow(local, READ, DEVS, "refs/heads/*");
     assertCanAccess(user(local, "a", ADMIN));
 
-    local = new ProjectConfig(localKey);
+    local = projectConfigFactory.create(localKey);
     local.load(newRepository(localKey));
     local.getProject().setParentName(parentKey);
     allow(local, READ, DEVS, "refs/*");
diff --git a/javatests/com/google/gerrit/server/project/CommitsCollectionTest.java b/javatests/com/google/gerrit/server/project/CommitsCollectionTest.java
index b39208a..2ae9e90 100644
--- a/javatests/com/google/gerrit/server/project/CommitsCollectionTest.java
+++ b/javatests/com/google/gerrit/server/project/CommitsCollectionTest.java
@@ -57,6 +57,7 @@
   @Inject protected MetaDataUpdate.Server metaDataUpdateFactory;
   @Inject protected AllProjectsName allProjects;
   @Inject private CommitsCollection commits;
+  @Inject private ProjectConfig.Factory projectConfigFactory;
 
   private TestRepository<InMemoryRepository> repo;
   private ProjectConfig project;
@@ -70,7 +71,7 @@
 
     Project.NameKey name = new Project.NameKey("project");
     InMemoryRepository inMemoryRepo = repoManager.createRepository(name);
-    project = new ProjectConfig(name);
+    project = projectConfigFactory.create(name);
     project.load(inMemoryRepo);
     repo = new TestRepository<>(inMemoryRepo);
   }
diff --git a/javatests/com/google/gerrit/server/project/ProjectConfigTest.java b/javatests/com/google/gerrit/server/project/ProjectConfigTest.java
index 0e4ba10..764d49a 100644
--- a/javatests/com/google/gerrit/server/project/ProjectConfigTest.java
+++ b/javatests/com/google/gerrit/server/project/ProjectConfigTest.java
@@ -78,11 +78,13 @@
       new GroupReference(new AccountGroup.UUID("X"), "Developers");
   private final GroupReference staff = new GroupReference(new AccountGroup.UUID("Y"), "Staff");
 
+  private ProjectConfig.Factory factory;
   private Repository db;
   private TestRepository<?> tr;
 
   @Before
   public void setUp() throws Exception {
+    factory = new ProjectConfig.Factory();
     db = new InMemoryRepository(new DfsRepositoryDescription("repo"));
     tr = new TestRepository<>(db);
   }
@@ -104,6 +106,13 @@
                     + "  sameGroupVisibility = block group Staff\n"
                     + "[contributor-agreement \"Individual\"]\n"
                     + "  description = A simple description\n"
+                    + "  matchProjects = ^/ourproject\n"
+                    + "  matchProjects = ^/ourotherproject\n"
+                    + "  matchProjects = ^/someotherroot/ourproject\n"
+                    + "  excludeProjects = ^/theirproject\n"
+                    + "  excludeProjects = ^/theirotherproject\n"
+                    + "  excludeProjects = ^/someotherroot/theirproject\n"
+                    + "  excludeProjects = ^/someotherroot/theirotherproject\n"
                     + "  accepted = group Developers\n"
                     + "  accepted = group Staff\n"
                     + "  autoVerify = group Developers\n"
@@ -115,6 +124,14 @@
     ContributorAgreement ca = cfg.getContributorAgreement("Individual");
     assertThat(ca.getName()).isEqualTo("Individual");
     assertThat(ca.getDescription()).isEqualTo("A simple description");
+    assertThat(ca.getMatchProjectsRegexes())
+        .containsExactly("^/ourproject", "^/ourotherproject", "^/someotherroot/ourproject");
+    assertThat(ca.getExcludeProjectsRegexes())
+        .containsExactly(
+            "^/theirproject",
+            "^/theirotherproject",
+            "^/someotherroot/theirproject",
+            "^/someotherroot/theirotherproject");
     assertThat(ca.getAgreementUrl()).isEqualTo("http://www.example.com/agree");
     assertThat(ca.getAccepted()).hasSize(2);
     assertThat(ca.getAccepted().get(0).getGroup()).isEqualTo(developers);
@@ -256,6 +273,7 @@
                     + "  sameGroupVisibility = block group Staff\n"
                     + "[contributor-agreement \"Individual\"]\n"
                     + "  description = A simple description\n"
+                    + "  matchProjects = ^/ourproject\n"
                     + "  accepted = group Developers\n"
                     + "  autoVerify = group Developers\n"
                     + "  agreementUrl = http://www.example.com/agree\n"
@@ -273,6 +291,8 @@
     ContributorAgreement ca = cfg.getContributorAgreement("Individual");
     ca.setAccepted(Collections.singletonList(new PermissionRule(cfg.resolve(staff))));
     ca.setAutoVerify(null);
+    ca.setMatchProjectsRegexes(null);
+    ca.setExcludeProjectsRegexes(Collections.singletonList("^/theirproject"));
     ca.setDescription("A new description");
     rev = commit(cfg);
     assertThat(text(rev, "project.config"))
@@ -289,6 +309,7 @@
                 + "  description = A new description\n"
                 + "  accepted = group Staff\n"
                 + "  agreementUrl = http://www.example.com/agree\n"
+                + "\texcludeProjects = ^/theirproject\n"
                 + "[label \"CustomLabel\"]\n"
                 + LABEL_SCORES_CONFIG
                 + "\tfunction = MaxWithBlock\n" // label gets this function when it is created
@@ -385,7 +406,7 @@
 
   @Test
   public void readUnexistingPluginConfig() throws Exception {
-    ProjectConfig cfg = new ProjectConfig(new Project.NameKey("test"));
+    ProjectConfig cfg = factory.create(new Project.NameKey("test"));
     cfg.load(db);
     PluginConfig pluginCfg = cfg.getPluginConfig("somePlugin");
     assertThat(pluginCfg.getNames()).isEmpty();
@@ -573,7 +594,7 @@
   }
 
   private ProjectConfig read(RevCommit rev) throws IOException, ConfigInvalidException {
-    ProjectConfig cfg = new ProjectConfig(new Project.NameKey("test"));
+    ProjectConfig cfg = factory.create(new Project.NameKey("test"));
     cfg.load(db, rev);
     return cfg;
   }
diff --git a/javatests/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java b/javatests/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java
index 9d01405..26cc3f8 100644
--- a/javatests/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java
+++ b/javatests/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java
@@ -74,7 +74,7 @@
 import com.google.gerrit.server.index.account.AccountIndex;
 import com.google.gerrit.server.index.account.AccountIndexCollection;
 import com.google.gerrit.server.index.account.AccountIndexer;
-import com.google.gerrit.server.schema.SchemaCreator;
+import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
 import com.google.gerrit.server.util.ManualRequestContext;
 import com.google.gerrit.server.util.OneOffRequestContext;
 import com.google.gerrit.server.util.RequestContext;
@@ -120,7 +120,7 @@
 
   @Inject protected InMemoryDatabase schemaFactory;
 
-  @Inject protected SchemaCreator schemaCreator;
+  @Inject protected ReviewDbSchemaCreator schemaCreator;
 
   @Inject protected ThreadLocalRequestContext requestContext;
 
diff --git a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
index b9973e9..de2234e 100644
--- a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -109,7 +109,7 @@
 import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.project.ProjectConfig;
-import com.google.gerrit.server.schema.SchemaCreator;
+import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
 import com.google.gerrit.server.update.BatchUpdate;
 import com.google.gerrit.server.util.ManualRequestContext;
 import com.google.gerrit.server.util.OneOffRequestContext;
@@ -177,7 +177,7 @@
   @Inject protected PatchSetUtil psUtil;
   @Inject protected ChangeNotes.Factory changeNotesFactory;
   @Inject protected Provider<ChangeQueryProcessor> queryProcessorProvider;
-  @Inject protected SchemaCreator schemaCreator;
+  @Inject protected ReviewDbSchemaCreator schemaCreator;
   @Inject protected SchemaFactory<ReviewDb> schemaFactory;
   @Inject protected Sequences seq;
   @Inject protected ThreadLocalRequestContext requestContext;
@@ -2378,6 +2378,12 @@
     cd.reviewers();
     cd.unresolvedCommentCount();
 
+    if (getSchemaVersion() < 51) {
+      assertMissingField(ChangeField.TOTAL_COMMENT_COUNT);
+    } else {
+      cd.totalCommentCount();
+    }
+
     // TODO(dborowitz): Swap out GitRepositoryManager somehow? Will probably be
     // necessary for NoteDb anyway.
     cd.isMergeable();
diff --git a/javatests/com/google/gerrit/server/query/group/AbstractQueryGroupsTest.java b/javatests/com/google/gerrit/server/query/group/AbstractQueryGroupsTest.java
index 750813a..7e4a0a4 100644
--- a/javatests/com/google/gerrit/server/query/group/AbstractQueryGroupsTest.java
+++ b/javatests/com/google/gerrit/server/query/group/AbstractQueryGroupsTest.java
@@ -52,7 +52,7 @@
 import com.google.gerrit.server.index.group.GroupField;
 import com.google.gerrit.server.index.group.GroupIndex;
 import com.google.gerrit.server.index.group.GroupIndexCollection;
-import com.google.gerrit.server.schema.SchemaCreator;
+import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
 import com.google.gerrit.server.util.ManualRequestContext;
 import com.google.gerrit.server.util.OneOffRequestContext;
 import com.google.gerrit.server.util.RequestContext;
@@ -91,7 +91,7 @@
 
   @Inject protected InMemoryDatabase schemaFactory;
 
-  @Inject protected SchemaCreator schemaCreator;
+  @Inject protected ReviewDbSchemaCreator schemaCreator;
 
   @Inject protected ThreadLocalRequestContext requestContext;
 
diff --git a/javatests/com/google/gerrit/server/query/project/AbstractQueryProjectsTest.java b/javatests/com/google/gerrit/server/query/project/AbstractQueryProjectsTest.java
index 420c323..3219dfd 100644
--- a/javatests/com/google/gerrit/server/query/project/AbstractQueryProjectsTest.java
+++ b/javatests/com/google/gerrit/server/query/project/AbstractQueryProjectsTest.java
@@ -50,7 +50,7 @@
 import com.google.gerrit.server.account.AuthRequest;
 import com.google.gerrit.server.config.AllProjectsName;
 import com.google.gerrit.server.group.SystemGroupBackend;
-import com.google.gerrit.server.schema.SchemaCreator;
+import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
 import com.google.gerrit.server.util.ManualRequestContext;
 import com.google.gerrit.server.util.OneOffRequestContext;
 import com.google.gerrit.server.util.RequestContext;
@@ -88,7 +88,7 @@
 
   @Inject protected InMemoryDatabase schemaFactory;
 
-  @Inject protected SchemaCreator schemaCreator;
+  @Inject protected ReviewDbSchemaCreator schemaCreator;
 
   @Inject protected ThreadLocalRequestContext requestContext;
 
diff --git a/javatests/com/google/gerrit/server/schema/GroupRebuilderTest.java b/javatests/com/google/gerrit/server/schema/GroupRebuilderTest.java
index bf6953a..6a8a55a 100644
--- a/javatests/com/google/gerrit/server/schema/GroupRebuilderTest.java
+++ b/javatests/com/google/gerrit/server/schema/GroupRebuilderTest.java
@@ -25,6 +25,7 @@
 import com.google.gerrit.common.data.GroupDescription;
 import com.google.gerrit.common.data.GroupReference;
 import com.google.gerrit.extensions.common.CommitInfo;
+import com.google.gerrit.git.RefUpdateUtil;
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.reviewdb.client.AccountGroupById;
@@ -37,7 +38,6 @@
 import com.google.gerrit.server.group.db.AuditLogFormatter;
 import com.google.gerrit.server.group.db.AuditLogReader;
 import com.google.gerrit.server.group.db.GroupNameNotes;
-import com.google.gerrit.server.update.RefUpdateUtil;
 import com.google.gerrit.server.util.time.TimeUtil;
 import com.google.gerrit.testing.GerritBaseTests;
 import com.google.gerrit.testing.GitTestUtil;
diff --git a/javatests/com/google/gerrit/server/schema/ReviewDbSchemaCreatorTest.java b/javatests/com/google/gerrit/server/schema/ReviewDbSchemaCreatorTest.java
new file mode 100644
index 0000000..bb358cc
--- /dev/null
+++ b/javatests/com/google/gerrit/server/schema/ReviewDbSchemaCreatorTest.java
@@ -0,0 +1,130 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.schema;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth8.assertThat;
+
+import com.google.common.collect.ImmutableList;
+import com.google.gerrit.common.data.LabelFunction;
+import com.google.gerrit.common.data.LabelType;
+import com.google.gerrit.common.data.LabelTypes;
+import com.google.gerrit.common.data.LabelValue;
+import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.project.ProjectConfig;
+import com.google.gerrit.testing.InMemoryDatabase;
+import com.google.gerrit.testing.InMemoryModule;
+import com.google.gwtorm.jdbc.JdbcSchema;
+import com.google.gwtorm.server.OrmException;
+import com.google.inject.Inject;
+import java.io.File;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.eclipse.jgit.lib.Repository;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ReviewDbSchemaCreatorTest {
+  @Inject private AllProjectsName allProjects;
+
+  @Inject private GitRepositoryManager repoManager;
+
+  @Inject private InMemoryDatabase db;
+
+  @Inject private ProjectConfig.Factory projectConfigFactory;
+
+  @Before
+  public void setUp() throws Exception {
+    new InMemoryModule().inject(this);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    InMemoryDatabase.drop(db);
+  }
+
+  @Test
+  public void getCauses_CreateSchema() throws OrmException, SQLException {
+    // Initially the schema should be empty.
+    String[] types = {"TABLE", "VIEW"};
+    try (JdbcSchema d = (JdbcSchema) db.open();
+        ResultSet rs = d.getConnection().getMetaData().getTables(null, null, null, types)) {
+      assertThat(rs.next()).isFalse();
+    }
+
+    // Create the schema using the current schema version.
+    //
+    db.create();
+    db.assertSchemaVersion();
+
+    // By default sitePath is set to the current working directory.
+    //
+    File sitePath = new File(".").getAbsoluteFile();
+    if (sitePath.getName().equals(".")) {
+      sitePath = sitePath.getParentFile();
+    }
+  }
+
+  private LabelTypes getLabelTypes() throws Exception {
+    db.create();
+    ProjectConfig c = projectConfigFactory.create(allProjects);
+    try (Repository repo = repoManager.openRepository(allProjects)) {
+      c.load(repo);
+      return new LabelTypes(ImmutableList.copyOf(c.getLabelSections().values()));
+    }
+  }
+
+  @Test
+  public void createSchema_LabelTypes() throws Exception {
+    List<String> labels = new ArrayList<>();
+    for (LabelType label : getLabelTypes().getLabelTypes()) {
+      labels.add(label.getName());
+    }
+    assertThat(labels).containsExactly("Code-Review");
+  }
+
+  @Test
+  public void createSchema_Label_CodeReview() throws Exception {
+    LabelType codeReview = getLabelTypes().byLabel("Code-Review");
+    assertThat(codeReview).isNotNull();
+    assertThat(codeReview.getName()).isEqualTo("Code-Review");
+    assertThat(codeReview.getDefaultValue()).isEqualTo(0);
+    assertThat(codeReview.getFunction()).isEqualTo(LabelFunction.MAX_WITH_BLOCK);
+    assertThat(codeReview.isCopyMinScore()).isTrue();
+    assertValueRange(codeReview, -2, -1, 0, 1, 2);
+  }
+
+  private void assertValueRange(LabelType label, Integer... range) {
+    List<Integer> rangeList = Arrays.asList(range);
+    assertThat(rangeList).isNotEmpty();
+    assertThat(rangeList).isStrictlyOrdered();
+
+    assertThat(label.getValues().stream().map(v -> (int) v.getValue()))
+        .containsExactlyElementsIn(rangeList)
+        .inOrder();
+    assertThat(label.getMax().getValue()).isEqualTo(Collections.max(rangeList));
+    assertThat(label.getMin().getValue()).isEqualTo(Collections.min(rangeList));
+    for (LabelValue v : label.getValues()) {
+      assertThat(v.getText()).isNotNull();
+      assertThat(v.getText()).isNotEmpty();
+    }
+  }
+}
diff --git a/javatests/com/google/gerrit/server/schema/ReviewDbSchemaUpdaterTest.java b/javatests/com/google/gerrit/server/schema/ReviewDbSchemaUpdaterTest.java
new file mode 100644
index 0000000..4133558
--- /dev/null
+++ b/javatests/com/google/gerrit/server/schema/ReviewDbSchemaUpdaterTest.java
@@ -0,0 +1,151 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.schema;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.gerrit.extensions.config.FactoryModule;
+import com.google.gerrit.lifecycle.LifecycleManager;
+import com.google.gerrit.metrics.DisabledMetricMaker;
+import com.google.gerrit.metrics.MetricMaker;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.GerritPersonIdent;
+import com.google.gerrit.server.GerritPersonIdentProvider;
+import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.config.AllUsersName;
+import com.google.gerrit.server.config.AnonymousCowardName;
+import com.google.gerrit.server.config.AnonymousCowardNameProvider;
+import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gerrit.server.config.GerritServerId;
+import com.google.gerrit.server.config.GerritServerIdProvider;
+import com.google.gerrit.server.config.SitePaths;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.group.SystemGroupBackend;
+import com.google.gerrit.server.notedb.NotesMigration;
+import com.google.gerrit.testing.InMemoryDatabase;
+import com.google.gerrit.testing.InMemoryH2Type;
+import com.google.gerrit.testing.InMemoryRepositoryManager;
+import com.google.gerrit.testing.TestUpdateUI;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
+import com.google.inject.Guice;
+import com.google.inject.Key;
+import com.google.inject.ProvisionException;
+import com.google.inject.TypeLiteral;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.UUID;
+import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ReviewDbSchemaUpdaterTest {
+  private LifecycleManager lifecycle;
+  private InMemoryDatabase db;
+
+  @Before
+  public void setUp() throws Exception {
+    lifecycle = new LifecycleManager();
+    db = InMemoryDatabase.newDatabase(lifecycle);
+    lifecycle.start();
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    if (lifecycle != null) {
+      lifecycle.stop();
+    }
+    InMemoryDatabase.drop(db);
+  }
+
+  @Test
+  public void update() throws OrmException, FileNotFoundException, IOException {
+    db.create();
+
+    final Path site = Paths.get(UUID.randomUUID().toString());
+    final SitePaths paths = new SitePaths(site);
+    ReviewDbSchemaUpdater u =
+        Guice.createInjector(
+                new FactoryModule() {
+                  @Override
+                  protected void configure() {
+                    TypeLiteral<SchemaFactory<ReviewDb>> schemaFactory =
+                        new TypeLiteral<SchemaFactory<ReviewDb>>() {};
+                    bind(schemaFactory).to(NotesMigrationSchemaFactory.class);
+                    bind(Key.get(schemaFactory, ReviewDbFactory.class)).toInstance(db);
+                    bind(SitePaths.class).toInstance(paths);
+
+                    Config cfg = new Config();
+                    cfg.setString("user", null, "name", "Gerrit Code Review");
+                    cfg.setString("user", null, "email", "gerrit@localhost");
+                    cfg.setString(
+                        GerritServerIdProvider.SECTION,
+                        null,
+                        GerritServerIdProvider.KEY,
+                        "1234567");
+                    bind(Config.class) //
+                        .annotatedWith(GerritServerConfig.class) //
+                        .toInstance(cfg);
+
+                    bind(PersonIdent.class) //
+                        .annotatedWith(GerritPersonIdent.class) //
+                        .toProvider(GerritPersonIdentProvider.class);
+
+                    bind(String.class).annotatedWith(GerritServerId.class).toInstance("gerrit");
+
+                    bind(AllProjectsName.class).toInstance(new AllProjectsName("All-Projects"));
+                    bind(AllUsersName.class).toInstance(new AllUsersName("All-Users"));
+
+                    bind(GitRepositoryManager.class).toInstance(new InMemoryRepositoryManager());
+
+                    bind(String.class) //
+                        .annotatedWith(AnonymousCowardName.class) //
+                        .toProvider(AnonymousCowardNameProvider.class);
+
+                    bind(DataSourceType.class).to(InMemoryH2Type.class);
+
+                    bind(SystemGroupBackend.class);
+                    install(new NotesMigration.Module());
+                    bind(MetricMaker.class).to(DisabledMetricMaker.class);
+                  }
+                })
+            .getInstance(ReviewDbSchemaUpdater.class);
+
+    for (ReviewDbSchemaVersion s = u.getLatestSchemaVersion();
+        s.getVersionNbr() > 1;
+        s = s.getPrior()) {
+      try {
+        assertThat(s.getPrior().getVersionNbr())
+            .named(
+                "schema %s has prior version %s. Not true that",
+                s.getVersionNbr(), s.getPrior().getVersionNbr())
+            .isEqualTo(s.getVersionNbr() - 1);
+      } catch (ProvisionException e) {
+        // Ignored
+        // The oldest supported schema version doesn't have a prior schema
+        // version.
+        break;
+      }
+    }
+
+    u.update(new TestUpdateUI());
+
+    db.assertSchemaVersion();
+  }
+}
diff --git a/javatests/com/google/gerrit/server/schema/SchemaCreatorTest.java b/javatests/com/google/gerrit/server/schema/SchemaCreatorTest.java
deleted file mode 100644
index 9569745..0000000
--- a/javatests/com/google/gerrit/server/schema/SchemaCreatorTest.java
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.schema;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth8.assertThat;
-
-import com.google.common.collect.ImmutableList;
-import com.google.gerrit.common.data.LabelFunction;
-import com.google.gerrit.common.data.LabelType;
-import com.google.gerrit.common.data.LabelTypes;
-import com.google.gerrit.common.data.LabelValue;
-import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.project.ProjectConfig;
-import com.google.gerrit.testing.InMemoryDatabase;
-import com.google.gerrit.testing.InMemoryModule;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import java.io.File;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import org.eclipse.jgit.lib.Repository;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class SchemaCreatorTest {
-  @Inject private AllProjectsName allProjects;
-
-  @Inject private GitRepositoryManager repoManager;
-
-  @Inject private InMemoryDatabase db;
-
-  @Before
-  public void setUp() throws Exception {
-    new InMemoryModule().inject(this);
-  }
-
-  @After
-  public void tearDown() throws Exception {
-    InMemoryDatabase.drop(db);
-  }
-
-  @Test
-  public void getCauses_CreateSchema() throws OrmException, SQLException {
-    // Initially the schema should be empty.
-    String[] types = {"TABLE", "VIEW"};
-    try (JdbcSchema d = (JdbcSchema) db.open();
-        ResultSet rs = d.getConnection().getMetaData().getTables(null, null, null, types)) {
-      assertThat(rs.next()).isFalse();
-    }
-
-    // Create the schema using the current schema version.
-    //
-    db.create();
-    db.assertSchemaVersion();
-
-    // By default sitePath is set to the current working directory.
-    //
-    File sitePath = new File(".").getAbsoluteFile();
-    if (sitePath.getName().equals(".")) {
-      sitePath = sitePath.getParentFile();
-    }
-  }
-
-  private LabelTypes getLabelTypes() throws Exception {
-    db.create();
-    ProjectConfig c = new ProjectConfig(allProjects);
-    try (Repository repo = repoManager.openRepository(allProjects)) {
-      c.load(repo);
-      return new LabelTypes(ImmutableList.copyOf(c.getLabelSections().values()));
-    }
-  }
-
-  @Test
-  public void createSchema_LabelTypes() throws Exception {
-    List<String> labels = new ArrayList<>();
-    for (LabelType label : getLabelTypes().getLabelTypes()) {
-      labels.add(label.getName());
-    }
-    assertThat(labels).containsExactly("Code-Review");
-  }
-
-  @Test
-  public void createSchema_Label_CodeReview() throws Exception {
-    LabelType codeReview = getLabelTypes().byLabel("Code-Review");
-    assertThat(codeReview).isNotNull();
-    assertThat(codeReview.getName()).isEqualTo("Code-Review");
-    assertThat(codeReview.getDefaultValue()).isEqualTo(0);
-    assertThat(codeReview.getFunction()).isEqualTo(LabelFunction.MAX_WITH_BLOCK);
-    assertThat(codeReview.isCopyMinScore()).isTrue();
-    assertValueRange(codeReview, -2, -1, 0, 1, 2);
-  }
-
-  private void assertValueRange(LabelType label, Integer... range) {
-    List<Integer> rangeList = Arrays.asList(range);
-    assertThat(rangeList).isNotEmpty();
-    assertThat(rangeList).isStrictlyOrdered();
-
-    assertThat(label.getValues().stream().map(v -> (int) v.getValue()))
-        .containsExactlyElementsIn(rangeList)
-        .inOrder();
-    assertThat(label.getMax().getValue()).isEqualTo(Collections.max(rangeList));
-    assertThat(label.getMin().getValue()).isEqualTo(Collections.min(rangeList));
-    for (LabelValue v : label.getValues()) {
-      assertThat(v.getText()).isNotNull();
-      assertThat(v.getText()).isNotEmpty();
-    }
-  }
-}
diff --git a/javatests/com/google/gerrit/server/schema/SchemaUpdaterTest.java b/javatests/com/google/gerrit/server/schema/SchemaUpdaterTest.java
deleted file mode 100644
index 7ea4d93..0000000
--- a/javatests/com/google/gerrit/server/schema/SchemaUpdaterTest.java
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.schema;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.google.gerrit.extensions.config.FactoryModule;
-import com.google.gerrit.lifecycle.LifecycleManager;
-import com.google.gerrit.metrics.DisabledMetricMaker;
-import com.google.gerrit.metrics.MetricMaker;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.GerritPersonIdentProvider;
-import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.config.AnonymousCowardName;
-import com.google.gerrit.server.config.AnonymousCowardNameProvider;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.config.GerritServerId;
-import com.google.gerrit.server.config.GerritServerIdProvider;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.group.SystemGroupBackend;
-import com.google.gerrit.server.notedb.NotesMigration;
-import com.google.gerrit.testing.InMemoryDatabase;
-import com.google.gerrit.testing.InMemoryH2Type;
-import com.google.gerrit.testing.InMemoryRepositoryManager;
-import com.google.gerrit.testing.TestUpdateUI;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.SchemaFactory;
-import com.google.inject.Guice;
-import com.google.inject.Key;
-import com.google.inject.ProvisionException;
-import com.google.inject.TypeLiteral;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.UUID;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class SchemaUpdaterTest {
-  private LifecycleManager lifecycle;
-  private InMemoryDatabase db;
-
-  @Before
-  public void setUp() throws Exception {
-    lifecycle = new LifecycleManager();
-    db = InMemoryDatabase.newDatabase(lifecycle);
-    lifecycle.start();
-  }
-
-  @After
-  public void tearDown() throws Exception {
-    if (lifecycle != null) {
-      lifecycle.stop();
-    }
-    InMemoryDatabase.drop(db);
-  }
-
-  @Test
-  public void update() throws OrmException, FileNotFoundException, IOException {
-    db.create();
-
-    final Path site = Paths.get(UUID.randomUUID().toString());
-    final SitePaths paths = new SitePaths(site);
-    SchemaUpdater u =
-        Guice.createInjector(
-                new FactoryModule() {
-                  @Override
-                  protected void configure() {
-                    TypeLiteral<SchemaFactory<ReviewDb>> schemaFactory =
-                        new TypeLiteral<SchemaFactory<ReviewDb>>() {};
-                    bind(schemaFactory).to(NotesMigrationSchemaFactory.class);
-                    bind(Key.get(schemaFactory, ReviewDbFactory.class)).toInstance(db);
-                    bind(SitePaths.class).toInstance(paths);
-
-                    Config cfg = new Config();
-                    cfg.setString("user", null, "name", "Gerrit Code Review");
-                    cfg.setString("user", null, "email", "gerrit@localhost");
-                    cfg.setString(
-                        GerritServerIdProvider.SECTION,
-                        null,
-                        GerritServerIdProvider.KEY,
-                        "1234567");
-                    bind(Config.class) //
-                        .annotatedWith(GerritServerConfig.class) //
-                        .toInstance(cfg);
-
-                    bind(PersonIdent.class) //
-                        .annotatedWith(GerritPersonIdent.class) //
-                        .toProvider(GerritPersonIdentProvider.class);
-
-                    bind(String.class).annotatedWith(GerritServerId.class).toInstance("gerrit");
-
-                    bind(AllProjectsName.class).toInstance(new AllProjectsName("All-Projects"));
-                    bind(AllUsersName.class).toInstance(new AllUsersName("All-Users"));
-
-                    bind(GitRepositoryManager.class).toInstance(new InMemoryRepositoryManager());
-
-                    bind(String.class) //
-                        .annotatedWith(AnonymousCowardName.class) //
-                        .toProvider(AnonymousCowardNameProvider.class);
-
-                    bind(DataSourceType.class).to(InMemoryH2Type.class);
-
-                    bind(SystemGroupBackend.class);
-                    install(new NotesMigration.Module());
-                    bind(MetricMaker.class).to(DisabledMetricMaker.class);
-                  }
-                })
-            .getInstance(SchemaUpdater.class);
-
-    for (SchemaVersion s = u.getLatestSchemaVersion(); s.getVersionNbr() > 1; s = s.getPrior()) {
-      try {
-        assertThat(s.getPrior().getVersionNbr())
-            .named(
-                "schema %s has prior version %s. Not true that",
-                s.getVersionNbr(), s.getPrior().getVersionNbr())
-            .isEqualTo(s.getVersionNbr() - 1);
-      } catch (ProvisionException e) {
-        // Ignored
-        // The oldest supported schema version doesn't have a prior schema
-        // version.
-        break;
-      }
-    }
-
-    u.update(new TestUpdateUI());
-
-    db.assertSchemaVersion();
-  }
-}
diff --git a/javatests/com/google/gerrit/server/schema/Schema_161_to_162_Test.java b/javatests/com/google/gerrit/server/schema/Schema_161_to_162_Test.java
index 67d071d..10aabe8 100644
--- a/javatests/com/google/gerrit/server/schema/Schema_161_to_162_Test.java
+++ b/javatests/com/google/gerrit/server/schema/Schema_161_to_162_Test.java
@@ -47,6 +47,7 @@
   @Inject private GitRepositoryManager repoManager;
   @Inject private Schema_162 schema162;
   @Inject private ReviewDb db;
+  @Inject private ProjectConfig.Factory projectConfigFactory;
   @Inject @GerritPersonIdent private PersonIdent serverUser;
 
   @Test
@@ -73,7 +74,7 @@
 
     try (Repository git = repoManager.openRepository(allUsersName);
         MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, git)) {
-      ProjectConfig cfg = ProjectConfig.read(md);
+      ProjectConfig cfg = projectConfigFactory.read(md);
       cfg.getProject().setParentName(testProject);
       md.getCommitBuilder().setCommitter(serverUser);
       md.getCommitBuilder().setAuthor(serverUser);
diff --git a/javatests/com/google/gerrit/server/schema/Schema_166_to_167_WithGroupsInNoteDbTest.java b/javatests/com/google/gerrit/server/schema/Schema_166_to_167_WithGroupsInNoteDbTest.java
index 57689b3..f17550e 100644
--- a/javatests/com/google/gerrit/server/schema/Schema_166_to_167_WithGroupsInNoteDbTest.java
+++ b/javatests/com/google/gerrit/server/schema/Schema_166_to_167_WithGroupsInNoteDbTest.java
@@ -206,7 +206,7 @@
     }
   }
 
-  private void executeSchemaMigration(SchemaVersion schema) throws Exception {
+  private void executeSchemaMigration(ReviewDbSchemaVersion schema) throws Exception {
     schema.migrateData(db, new TestUpdateUI());
   }
 
diff --git a/javatests/com/google/gerrit/server/schema/Schema_166_to_167_WithGroupsInReviewDbTest.java b/javatests/com/google/gerrit/server/schema/Schema_166_to_167_WithGroupsInReviewDbTest.java
index 78fef39..890ae32 100644
--- a/javatests/com/google/gerrit/server/schema/Schema_166_to_167_WithGroupsInReviewDbTest.java
+++ b/javatests/com/google/gerrit/server/schema/Schema_166_to_167_WithGroupsInReviewDbTest.java
@@ -920,7 +920,7 @@
     }
   }
 
-  private void executeSchemaMigration(SchemaVersion schema, AccountGroup... groupsToVerify)
+  private void executeSchemaMigration(ReviewDbSchemaVersion schema, AccountGroup... groupsToVerify)
       throws Exception {
     executeSchemaMigration(
         schema,
@@ -929,7 +929,7 @@
             .toArray(AccountGroup.UUID[]::new));
   }
 
-  private void executeSchemaMigration(SchemaVersion schema, GroupInfo... groupsToVerify)
+  private void executeSchemaMigration(ReviewDbSchemaVersion schema, GroupInfo... groupsToVerify)
       throws Exception {
     executeSchemaMigration(
         schema,
@@ -938,8 +938,8 @@
             .toArray(AccountGroup.UUID[]::new));
   }
 
-  private void executeSchemaMigration(SchemaVersion schema, AccountGroup.UUID... groupsToVerify)
-      throws Exception {
+  private void executeSchemaMigration(
+      ReviewDbSchemaVersion schema, AccountGroup.UUID... groupsToVerify) throws Exception {
     List<GroupBundle> reviewDbBundles = new ArrayList<>();
     for (AccountGroup.UUID groupUuid : groupsToVerify) {
       reviewDbBundles.add(GroupBundle.Factory.fromReviewDb(db, groupUuid));
diff --git a/javatests/com/google/gerrit/server/update/BUILD b/javatests/com/google/gerrit/server/update/BUILD
index cef3d63..9117e85 100644
--- a/javatests/com/google/gerrit/server/update/BUILD
+++ b/javatests/com/google/gerrit/server/update/BUILD
@@ -1,30 +1,9 @@
 load("//tools/bzl:junit.bzl", "junit_tests")
 
-MEDIUM_TESTS = ["RefUpdateUtilRepoTest.java"]
-
-junit_tests(
-    name = "medium_tests",
-    size = "medium",
-    timeout = "short",
-    srcs = MEDIUM_TESTS,
-    tags = ["no_windows"],
-    deps = [
-        "//java/com/google/gerrit/server",
-        "//lib:guava",
-        "//lib:junit",
-        "//lib/jgit/org.eclipse.jgit:jgit",
-        "//lib/jgit/org.eclipse.jgit.junit:junit",
-        "//lib/truth",
-    ],
-)
-
 junit_tests(
     name = "small_tests",
     size = "small",
-    srcs = glob(
-        ["*.java"],
-        exclude = MEDIUM_TESTS,
-    ),
+    srcs = glob(["*.java"]),
     deps = [
         "//java/com/google/gerrit/common:server",
         "//java/com/google/gerrit/lifecycle",
diff --git a/javatests/com/google/gerrit/server/update/RefUpdateUtilRepoTest.java b/javatests/com/google/gerrit/server/update/RefUpdateUtilRepoTest.java
deleted file mode 100644
index fe9d522..0000000
--- a/javatests/com/google/gerrit/server/update/RefUpdateUtilRepoTest.java
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright (C) 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.update;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.io.MoreFiles;
-import com.google.common.io.RecursiveDeleteOption;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
-import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
-import org.eclipse.jgit.internal.storage.file.FileRepository;
-import org.eclipse.jgit.junit.TestRepository;
-import org.eclipse.jgit.lib.Repository;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class RefUpdateUtilRepoTest {
-  public enum RepoSetup {
-    LOCAL_DISK {
-      @Override
-      Repository setUpRepo() throws Exception {
-        Path p = Files.createTempDirectory("gerrit_repo_");
-        try {
-          Repository repo = new FileRepository(p.toFile());
-          repo.create(true);
-          return repo;
-        } catch (Exception e) {
-          delete(p);
-          throw e;
-        }
-      }
-
-      @Override
-      void tearDownRepo(Repository repo) throws Exception {
-        delete(repo.getDirectory().toPath());
-      }
-
-      private void delete(Path p) throws Exception {
-        MoreFiles.deleteRecursively(p, RecursiveDeleteOption.ALLOW_INSECURE);
-      }
-    },
-
-    IN_MEMORY {
-      @Override
-      Repository setUpRepo() {
-        return new InMemoryRepository(new DfsRepositoryDescription("repo"));
-      }
-
-      @Override
-      void tearDownRepo(Repository repo) {}
-    };
-
-    abstract Repository setUpRepo() throws Exception;
-
-    abstract void tearDownRepo(Repository repo) throws Exception;
-  }
-
-  @Parameters(name = "{0}")
-  public static ImmutableList<RepoSetup[]> data() {
-    return ImmutableList.copyOf(new RepoSetup[][] {{RepoSetup.LOCAL_DISK}, {RepoSetup.IN_MEMORY}});
-  }
-
-  @Parameter public RepoSetup repoSetup;
-
-  private Repository repo;
-
-  @Before
-  public void setUp() throws Exception {
-    repo = repoSetup.setUpRepo();
-  }
-
-  @After
-  public void tearDown() throws Exception {
-    if (repo != null) {
-      repoSetup.tearDownRepo(repo);
-      repo = null;
-    }
-  }
-
-  @Test
-  public void deleteRefNoOp() throws Exception {
-    String ref = "refs/heads/foo";
-    assertThat(repo.exactRef(ref)).isNull();
-    RefUpdateUtil.deleteChecked(repo, "refs/heads/foo");
-    assertThat(repo.exactRef(ref)).isNull();
-  }
-
-  @Test
-  public void deleteRef() throws Exception {
-    String ref = "refs/heads/foo";
-    new TestRepository<>(repo).branch(ref).commit().create();
-    assertThat(repo.exactRef(ref)).isNotNull();
-    RefUpdateUtil.deleteChecked(repo, "refs/heads/foo");
-    assertThat(repo.exactRef(ref)).isNull();
-  }
-}
diff --git a/javatests/com/google/gerrit/server/update/RefUpdateUtilTest.java b/javatests/com/google/gerrit/server/update/RefUpdateUtilTest.java
deleted file mode 100644
index fc8696a..0000000
--- a/javatests/com/google/gerrit/server/update/RefUpdateUtilTest.java
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (C) 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.update;
-
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assert_;
-
-import com.google.common.collect.ImmutableList;
-import com.google.gerrit.server.git.LockFailureException;
-import java.io.IOException;
-import java.util.function.Consumer;
-import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
-import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
-import org.eclipse.jgit.lib.BatchRefUpdate;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.transport.ReceiveCommand;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public class RefUpdateUtilTest {
-  private static final Consumer<ReceiveCommand> OK = c -> c.setResult(ReceiveCommand.Result.OK);
-  private static final Consumer<ReceiveCommand> LOCK_FAILURE =
-      c -> c.setResult(ReceiveCommand.Result.LOCK_FAILURE);
-  private static final Consumer<ReceiveCommand> REJECTED =
-      c -> c.setResult(ReceiveCommand.Result.REJECTED_OTHER_REASON);
-  private static final Consumer<ReceiveCommand> ABORTED =
-      c -> {
-        c.setResult(ReceiveCommand.Result.NOT_ATTEMPTED);
-        ReceiveCommand.abort(ImmutableList.of(c));
-        checkState(
-            c.getResult() != ReceiveCommand.Result.NOT_ATTEMPTED
-                && c.getResult() != ReceiveCommand.Result.LOCK_FAILURE
-                && c.getResult() != ReceiveCommand.Result.OK,
-            "unexpected state after abort: %s",
-            c);
-      };
-
-  @Test
-  public void checkBatchRefUpdateResults() throws Exception {
-    checkResults();
-    checkResults(OK);
-    checkResults(OK, OK);
-
-    assertIoException(REJECTED);
-    assertIoException(OK, REJECTED);
-    assertIoException(LOCK_FAILURE, REJECTED);
-    assertIoException(LOCK_FAILURE, OK);
-    assertIoException(LOCK_FAILURE, REJECTED, OK);
-    assertIoException(LOCK_FAILURE, LOCK_FAILURE, REJECTED);
-    assertIoException(LOCK_FAILURE, ABORTED, REJECTED);
-    assertIoException(LOCK_FAILURE, ABORTED, OK);
-
-    assertLockFailureException(LOCK_FAILURE);
-    assertLockFailureException(LOCK_FAILURE, LOCK_FAILURE);
-    assertLockFailureException(LOCK_FAILURE, LOCK_FAILURE, ABORTED);
-    assertLockFailureException(LOCK_FAILURE, LOCK_FAILURE, ABORTED, ABORTED);
-    assertLockFailureException(ABORTED);
-    assertLockFailureException(ABORTED, ABORTED);
-  }
-
-  @SafeVarargs
-  private static void checkResults(Consumer<ReceiveCommand>... resultSetters) throws Exception {
-    RefUpdateUtil.checkResults(newBatchRefUpdate(resultSetters));
-  }
-
-  @SafeVarargs
-  private static void assertIoException(Consumer<ReceiveCommand>... resultSetters) {
-    try {
-      RefUpdateUtil.checkResults(newBatchRefUpdate(resultSetters));
-      assert_().fail("expected IOException");
-    } catch (IOException e) {
-      assertThat(e).isNotInstanceOf(LockFailureException.class);
-    }
-  }
-
-  @SafeVarargs
-  private static void assertLockFailureException(Consumer<ReceiveCommand>... resultSetters)
-      throws Exception {
-    try {
-      RefUpdateUtil.checkResults(newBatchRefUpdate(resultSetters));
-      assert_().fail("expected LockFailureException");
-    } catch (LockFailureException e) {
-      // Expected.
-    }
-  }
-
-  @SafeVarargs
-  private static BatchRefUpdate newBatchRefUpdate(Consumer<ReceiveCommand>... resultSetters) {
-    try (Repository repo = new InMemoryRepository(new DfsRepositoryDescription("repo"))) {
-      BatchRefUpdate bru = repo.getRefDatabase().newBatchUpdate();
-      for (int i = 0; i < resultSetters.length; i++) {
-        ReceiveCommand cmd =
-            new ReceiveCommand(
-                ObjectId.fromString(String.format("%039x1", i)),
-                ObjectId.fromString(String.format("%039x2", i)),
-                "refs/heads/branch" + i);
-        bru.addCommand(cmd);
-        resultSetters[i].accept(cmd);
-      }
-      return bru;
-    }
-  }
-}
diff --git a/javatests/com/google/gwtexpui/safehtml/BUILD b/javatests/com/google/gwtexpui/safehtml/BUILD
deleted file mode 100644
index 694f422..0000000
--- a/javatests/com/google/gwtexpui/safehtml/BUILD
+++ /dev/null
@@ -1,13 +0,0 @@
-load("//tools/bzl:junit.bzl", "junit_tests")
-
-junit_tests(
-    name = "safehtml_tests",
-    srcs = glob(["client/**/*.java"]),
-    deps = [
-        "//java/com/google/gwtexpui/safehtml",
-        "//lib:guava",
-        "//lib/gwt:dev",
-        "//lib/gwt:user",
-        "//lib/truth",
-    ],
-)
diff --git a/javatests/com/google/gwtexpui/safehtml/client/LinkFindReplaceTest.java b/javatests/com/google/gwtexpui/safehtml/client/LinkFindReplaceTest.java
deleted file mode 100644
index a77c5b4..0000000
--- a/javatests/com/google/gwtexpui/safehtml/client/LinkFindReplaceTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-public class LinkFindReplaceTest {
-  @Rule public ExpectedException exception = ExpectedException.none();
-
-  @Test
-  public void noEscaping() {
-    String find = "find";
-    String link = "link";
-    LinkFindReplace a = new LinkFindReplace(find, link);
-    assertThat(a.pattern().getSource()).isEqualTo(find);
-    assertThat(a.replace(find)).isEqualTo("<a href=\"link\">find</a>");
-    assertThat(a.toString()).isEqualTo("find = " + find + ", link = " + link);
-  }
-
-  @Test
-  public void backreference() {
-    LinkFindReplace l = new LinkFindReplace("(bug|issue)\\s*([0-9]+)", "/bug?id=$2");
-    assertThat(l.replace("issue 123")).isEqualTo("<a href=\"/bug?id=123\">issue 123</a>");
-  }
-
-  @Test
-  public void hasValidScheme() {
-    assertThat(LinkFindReplace.hasValidScheme("/absolute/path")).isTrue();
-    assertThat(LinkFindReplace.hasValidScheme("relative/path")).isTrue();
-    assertThat(LinkFindReplace.hasValidScheme("http://url/")).isTrue();
-    assertThat(LinkFindReplace.hasValidScheme("HTTP://url/")).isTrue();
-    assertThat(LinkFindReplace.hasValidScheme("https://url/")).isTrue();
-    assertThat(LinkFindReplace.hasValidScheme("mailto://url/")).isTrue();
-    assertThat(LinkFindReplace.hasValidScheme("ftp://url/")).isFalse();
-    assertThat(LinkFindReplace.hasValidScheme("data:evil")).isFalse();
-    assertThat(LinkFindReplace.hasValidScheme("javascript:alert(1)")).isFalse();
-  }
-
-  @Test
-  public void invalidSchemeInReplace() {
-    exception.expect(IllegalArgumentException.class);
-    new LinkFindReplace("find", "javascript:alert(1)").replace("find");
-  }
-
-  @Test
-  public void invalidSchemeWithBackreference() {
-    exception.expect(IllegalArgumentException.class);
-    new LinkFindReplace(".*(script:[^;]*)", "java$1").replace("Look at this script: alert(1);");
-  }
-
-  @Test
-  public void replaceEscaping() {
-    assertThat(new LinkFindReplace("find", "a\"&'<>b").replace("find"))
-        .isEqualTo("<a href=\"a&quot;&amp;&#39;&lt;&gt;b\">find</a>");
-  }
-
-  @Test
-  public void htmlInFind() {
-    String rawFind = "<b>&quot;bold&quot;</b>";
-    LinkFindReplace a = new LinkFindReplace(rawFind, "/bold");
-    assertThat(a.pattern().getSource()).isEqualTo(rawFind);
-    assertThat(a.replace(rawFind)).isEqualTo("<a href=\"/bold\">" + rawFind + "</a>");
-  }
-}
diff --git a/javatests/com/google/gwtexpui/safehtml/client/RawFindReplaceTest.java b/javatests/com/google/gwtexpui/safehtml/client/RawFindReplaceTest.java
deleted file mode 100644
index 3b5e769..0000000
--- a/javatests/com/google/gwtexpui/safehtml/client/RawFindReplaceTest.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.Test;
-
-public class RawFindReplaceTest {
-  @Test
-  public void findReplace() {
-    final String find = "find";
-    final String replace = "replace";
-    final RawFindReplace a = new RawFindReplace(find, replace);
-    assertThat(a.pattern().getSource()).isEqualTo(find);
-    assertThat(a.replace(find)).isEqualTo(replace);
-    assertThat(a.toString()).isEqualTo("find = " + find + ", replace = " + replace);
-  }
-}
diff --git a/javatests/com/google/gwtexpui/safehtml/client/SafeHtmlBuilderTest.java b/javatests/com/google/gwtexpui/safehtml/client/SafeHtmlBuilderTest.java
deleted file mode 100644
index 9a2dbe3..0000000
--- a/javatests/com/google/gwtexpui/safehtml/client/SafeHtmlBuilderTest.java
+++ /dev/null
@@ -1,290 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-public class SafeHtmlBuilderTest {
-  @Rule public ExpectedException exception = ExpectedException.none();
-
-  @Test
-  public void empty() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    assertThat(b.isEmpty()).isTrue();
-    assertThat(b.hasContent()).isFalse();
-    assertThat(b.asString()).isEmpty();
-
-    b.append("a");
-    assertThat(b.hasContent()).isTrue();
-    assertThat(b.asString()).isEqualTo("a");
-  }
-
-  @Test
-  public void toSafeHtml() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    b.append(1);
-
-    final SafeHtml h = b.toSafeHtml();
-    assertThat(h).isNotNull();
-    assertThat(h).isNotSameAs(b);
-    assertThat(h).isNotInstanceOf(SafeHtmlBuilder.class);
-    assertThat(h.asString()).isEqualTo("1");
-  }
-
-  @Test
-  public void append_boolean() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    assertThat(b).isSameAs(b.append(true));
-    assertThat(b).isSameAs(b.append(false));
-    assertThat(b.asString()).isEqualTo("truefalse");
-  }
-
-  @Test
-  public void append_char() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    assertThat(b).isSameAs(b.append('a'));
-    assertThat(b).isSameAs(b.append('b'));
-    assertThat(b.asString()).isEqualTo("ab");
-  }
-
-  @Test
-  public void append_int() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    assertThat(b).isSameAs(b.append(4));
-    assertThat(b).isSameAs(b.append(2));
-    assertThat(b).isSameAs(b.append(-100));
-    assertThat(b.asString()).isEqualTo("42-100");
-  }
-
-  @Test
-  public void append_long() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    assertThat(b).isSameAs(b.append(4L));
-    assertThat(b).isSameAs(b.append(2L));
-    assertThat(b.asString()).isEqualTo("42");
-  }
-
-  @Test
-  public void append_float() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    assertThat(b).isSameAs(b.append(0.0f));
-    assertThat(b.asString()).isEqualTo("0.0");
-  }
-
-  @Test
-  public void append_double() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    assertThat(b).isSameAs(b.append(0.0));
-    assertThat(b.asString()).isEqualTo("0.0");
-  }
-
-  @Test
-  public void append_String() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    assertThat(b).isSameAs(b.append((String) null));
-    assertThat(b.asString()).isEmpty();
-    assertThat(b).isSameAs(b.append("foo"));
-    assertThat(b).isSameAs(b.append("bar"));
-    assertThat(b.asString()).isEqualTo("foobar");
-  }
-
-  @Test
-  public void append_StringBuilder() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    assertThat(b).isSameAs(b.append((StringBuilder) null));
-    assertThat(b.asString()).isEmpty();
-    assertThat(b).isSameAs(b.append(new StringBuilder("foo")));
-    assertThat(b).isSameAs(b.append(new StringBuilder("bar")));
-    assertThat(b.asString()).isEqualTo("foobar");
-  }
-
-  @Test
-  public void append_StringBuffer() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    assertThat(b).isSameAs(b.append((StringBuffer) null));
-    assertThat(b.asString()).isEmpty();
-    assertThat(b).isSameAs(b.append(new StringBuffer("foo")));
-    assertThat(b).isSameAs(b.append(new StringBuffer("bar")));
-    assertThat(b.asString()).isEqualTo("foobar");
-  }
-
-  @Test
-  public void append_Object() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    assertThat(b).isSameAs(b.append((Object) null));
-    assertThat(b.asString()).isEmpty();
-    assertThat(b)
-        .isSameAs(
-            b.append(
-                new Object() {
-                  @Override
-                  public String toString() {
-                    return "foobar";
-                  }
-                }));
-    assertThat(b.asString()).isEqualTo("foobar");
-  }
-
-  @Test
-  public void append_CharSequence() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    assertThat(b).isSameAs(b.append((CharSequence) null));
-    assertThat(b.asString()).isEmpty();
-    assertThat(b).isSameAs(b.append((CharSequence) "foo"));
-    assertThat(b).isSameAs(b.append((CharSequence) "bar"));
-    assertThat(b.asString()).isEqualTo("foobar");
-  }
-
-  @Test
-  public void append_SafeHtml() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    assertThat(b).isSameAs(b.append((SafeHtml) null));
-    assertThat(b.asString()).isEmpty();
-    assertThat(b).isSameAs(b.append(new SafeHtmlString("foo")));
-    assertThat(b).isSameAs(b.append(new SafeHtmlBuilder().append("bar")));
-    assertThat(b.asString()).isEqualTo("foobar");
-  }
-
-  @Test
-  public void htmlSpecialCharacters() {
-    assertThat(escape("&")).isEqualTo("&amp;");
-    assertThat(escape("<")).isEqualTo("&lt;");
-    assertThat(escape(">")).isEqualTo("&gt;");
-    assertThat(escape("\"")).isEqualTo("&quot;");
-    assertThat(escape("'")).isEqualTo("&#39;");
-
-    assertThat(escape('&')).isEqualTo("&amp;");
-    assertThat(escape('<')).isEqualTo("&lt;");
-    assertThat(escape('>')).isEqualTo("&gt;");
-    assertThat(escape('"')).isEqualTo("&quot;");
-    assertThat(escape('\'')).isEqualTo("&#39;");
-
-    assertThat(escape("<b>")).isEqualTo("&lt;b&gt;");
-    assertThat(escape("&lt;b&gt;")).isEqualTo("&amp;lt;b&amp;gt;");
-  }
-
-  @Test
-  public void entityNbsp() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    assertThat(b).isSameAs(b.nbsp());
-    assertThat(b.asString()).isEqualTo("&nbsp;");
-  }
-
-  @Test
-  public void tagBr() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    assertThat(b).isSameAs(b.br());
-    assertThat(b.asString()).isEqualTo("<br />");
-  }
-
-  @Test
-  public void tagTableTrTd() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    assertThat(b).isSameAs(b.openElement("table"));
-    assertThat(b).isSameAs(b.openTr());
-    assertThat(b).isSameAs(b.openTd());
-    assertThat(b).isSameAs(b.append("d<a>ta"));
-    assertThat(b).isSameAs(b.closeTd());
-    assertThat(b).isSameAs(b.closeTr());
-    assertThat(b).isSameAs(b.closeElement("table"));
-    assertThat(b.asString()).isEqualTo("<table><tr><td>d&lt;a&gt;ta</td></tr></table>");
-  }
-
-  @Test
-  public void tagDiv() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    assertThat(b).isSameAs(b.openDiv());
-    assertThat(b).isSameAs(b.append("d<a>ta"));
-    assertThat(b).isSameAs(b.closeDiv());
-    assertThat(b.asString()).isEqualTo("<div>d&lt;a&gt;ta</div>");
-  }
-
-  @Test
-  public void tagAnchor() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    assertThat(b).isSameAs(b.openAnchor());
-
-    assertThat(b.getAttribute("href")).isEmpty();
-    assertThat(b).isSameAs(b.setAttribute("href", "http://here"));
-    assertThat(b.getAttribute("href")).isEqualTo("http://here");
-    assertThat(b).isSameAs(b.setAttribute("href", "d<a>ta"));
-    assertThat(b.getAttribute("href")).isEqualTo("d<a>ta");
-
-    assertThat(b.getAttribute("target")).isEmpty();
-    assertThat(b).isSameAs(b.setAttribute("target", null));
-    assertThat(b.getAttribute("target")).isEmpty();
-
-    assertThat(b).isSameAs(b.append("go"));
-    assertThat(b).isSameAs(b.closeAnchor());
-    assertThat(b.asString()).isEqualTo("<a href=\"d&lt;a&gt;ta\">go</a>");
-  }
-
-  @Test
-  public void tagHeightWidth() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    assertThat(b).isSameAs(b.openElement("img"));
-    assertThat(b).isSameAs(b.setHeight(100));
-    assertThat(b).isSameAs(b.setWidth(42));
-    assertThat(b).isSameAs(b.closeSelf());
-    assertThat(b.asString()).isEqualTo("<img height=\"100\" width=\"42\" />");
-  }
-
-  @Test
-  public void styleName() {
-    final SafeHtmlBuilder b = new SafeHtmlBuilder();
-    assertThat(b).isSameAs(b.openSpan());
-    assertThat(b).isSameAs(b.setStyleName("foo"));
-    assertThat(b).isSameAs(b.addStyleName("bar"));
-    assertThat(b).isSameAs(b.append("d<a>ta"));
-    assertThat(b).isSameAs(b.closeSpan());
-    assertThat(b.asString()).isEqualTo("<span class=\"foo bar\">d&lt;a&gt;ta</span>");
-  }
-
-  @Test
-  public void rejectJavaScript_AnchorHref() {
-    final String href = "javascript:window.close();";
-    exception.expect(RuntimeException.class);
-    exception.expectMessage("javascript unsafe in href: " + href);
-    new SafeHtmlBuilder().openAnchor().setAttribute("href", href);
-  }
-
-  @Test
-  public void rejectJavaScript_ImgSrc() {
-    final String href = "javascript:window.close();";
-    exception.expect(RuntimeException.class);
-    exception.expectMessage("javascript unsafe in href: " + href);
-    new SafeHtmlBuilder().openElement("img").setAttribute("src", href);
-  }
-
-  @Test
-  public void rejectJavaScript_FormAction() {
-    final String href = "javascript:window.close();";
-    exception.expect(RuntimeException.class);
-    exception.expectMessage("javascript unsafe in href: " + href);
-    new SafeHtmlBuilder().openElement("form").setAttribute("action", href);
-  }
-
-  private static String escape(char c) {
-    return new SafeHtmlBuilder().append(c).asString();
-  }
-
-  private static String escape(String c) {
-    return new SafeHtmlBuilder().append(c).asString();
-  }
-}
diff --git a/javatests/com/google/gwtexpui/safehtml/client/SafeHtml_LinkifyTest.java b/javatests/com/google/gwtexpui/safehtml/client/SafeHtml_LinkifyTest.java
deleted file mode 100644
index b42878b..0000000
--- a/javatests/com/google/gwtexpui/safehtml/client/SafeHtml_LinkifyTest.java
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.Test;
-
-public class SafeHtml_LinkifyTest {
-  @Test
-  public void linkify_SimpleHttp1() {
-    final SafeHtml o = html("A http://go.here/ B");
-    final SafeHtml n = o.linkify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(
-            "A <a href=\"http://go.here/\" target=\"_blank\" rel=\"nofollow\""
-                + ">http://go.here/</a> B");
-  }
-
-  @Test
-  public void linkify_SimpleHttps2() {
-    final SafeHtml o = html("A https://go.here/ B");
-    final SafeHtml n = o.linkify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(
-            "A <a href=\"https://go.here/\" target=\"_blank\" rel=\"nofollow\""
-                + ">https://go.here/</a> B");
-  }
-
-  @Test
-  public void linkify_Parens1() {
-    final SafeHtml o = html("A (http://go.here/) B");
-    final SafeHtml n = o.linkify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(
-            "A (<a href=\"http://go.here/\" target=\"_blank\" rel=\"nofollow\""
-                + ">http://go.here/</a>) B");
-  }
-
-  @Test
-  public void linkify_Parens() {
-    final SafeHtml o = html("A http://go.here/#m() B");
-    final SafeHtml n = o.linkify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(
-            "A <a href=\"http://go.here/#m()\" target=\"_blank\" rel=\"nofollow\""
-                + ">http://go.here/#m()</a> B");
-  }
-
-  @Test
-  public void linkify_AngleBrackets1() {
-    final SafeHtml o = html("A <http://go.here/> B");
-    final SafeHtml n = o.linkify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(
-            "A &lt;<a href=\"http://go.here/\" target=\"_blank\" rel=\"nofollow\""
-                + ">http://go.here/</a>&gt; B");
-  }
-
-  @Test
-  public void linkify_TrailingPlainLetter() {
-    final SafeHtml o = html("A http://go.here/foo B");
-    final SafeHtml n = o.linkify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(
-            "A <a href=\"http://go.here/foo\" target=\"_blank\" rel=\"nofollow\""
-                + ">http://go.here/foo</a> B");
-  }
-
-  @Test
-  public void linkify_TrailingDot() {
-    final SafeHtml o = html("A http://go.here/. B");
-    final SafeHtml n = o.linkify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(
-            "A <a href=\"http://go.here/\" target=\"_blank\" rel=\"nofollow\""
-                + ">http://go.here/</a>. B");
-  }
-
-  @Test
-  public void linkify_TrailingComma() {
-    final SafeHtml o = html("A http://go.here/, B");
-    final SafeHtml n = o.linkify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(
-            "A <a href=\"http://go.here/\" target=\"_blank\" rel=\"nofollow\""
-                + ">http://go.here/</a>, B");
-  }
-
-  @Test
-  public void linkify_TrailingDotDot() {
-    final SafeHtml o = html("A http://go.here/.. B");
-    final SafeHtml n = o.linkify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(
-            "A <a href=\"http://go.here/.\" target=\"_blank\" rel=\"nofollow\""
-                + ">http://go.here/.</a>. B");
-  }
-
-  private static SafeHtml html(String text) {
-    return new SafeHtmlBuilder().append(text).toSafeHtml();
-  }
-}
diff --git a/javatests/com/google/gwtexpui/safehtml/client/SafeHtml_ReplaceTest.java b/javatests/com/google/gwtexpui/safehtml/client/SafeHtml_ReplaceTest.java
deleted file mode 100644
index ac0f6fd6..0000000
--- a/javatests/com/google/gwtexpui/safehtml/client/SafeHtml_ReplaceTest.java
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import org.junit.Test;
-
-public class SafeHtml_ReplaceTest {
-  @Test
-  public void replaceEmpty() {
-    SafeHtml o = html("A\nissue42\nB");
-    assertThat(o.replaceAll(null)).isSameAs(o);
-    assertThat(o.replaceAll(Collections.<FindReplace>emptyList())).isSameAs(o);
-  }
-
-  @Test
-  public void replaceOneLink() {
-    SafeHtml o = html("A\nissue 42\nB");
-    SafeHtml n =
-        o.replaceAll(repls(new RawFindReplace("(issue\\s(\\d+))", "<a href=\"?$2\">$1</a>")));
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString()).isEqualTo("A\n<a href=\"?42\">issue 42</a>\nB");
-  }
-
-  @Test
-  public void replaceNoLeadingOrTrailingText() {
-    SafeHtml o = html("issue 42");
-    SafeHtml n =
-        o.replaceAll(repls(new RawFindReplace("(issue\\s(\\d+))", "<a href=\"?$2\">$1</a>")));
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString()).isEqualTo("<a href=\"?42\">issue 42</a>");
-  }
-
-  @Test
-  public void replaceTwoLinks() {
-    SafeHtml o = html("A\nissue 42\nissue 9918\nB");
-    SafeHtml n =
-        o.replaceAll(repls(new RawFindReplace("(issue\\s(\\d+))", "<a href=\"?$2\">$1</a>")));
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo("A\n<a href=\"?42\">issue 42</a>\n<a href=\"?9918\">issue 9918</a>\nB");
-  }
-
-  @Test
-  public void replaceInOrder() {
-    SafeHtml o = html("A\nissue 42\nReally GWTEXPUI-9918 is better\nB");
-    SafeHtml n =
-        o.replaceAll(
-            repls(
-                new RawFindReplace("(GWTEXPUI-(\\d+))", "<a href=\"gwtexpui-bug?$2\">$1</a>"),
-                new RawFindReplace("(issue\\s+(\\d+))", "<a href=\"generic-bug?$2\">$1</a>")));
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(
-            "A\n"
-                + "<a href=\"generic-bug?42\">issue 42</a>\n"
-                + "Really <a href=\"gwtexpui-bug?9918\">GWTEXPUI-9918</a> is better\n"
-                + "B");
-  }
-
-  @Test
-  public void replaceOverlappingAfterFirstChar() {
-    SafeHtml o = html("abcd");
-    RawFindReplace ab = new RawFindReplace("ab", "AB");
-    RawFindReplace bc = new RawFindReplace("bc", "23");
-    RawFindReplace cd = new RawFindReplace("cd", "YZ");
-
-    assertThat(o.replaceAll(repls(ab, bc)).asString()).isEqualTo("ABcd");
-    assertThat(o.replaceAll(repls(bc, ab)).asString()).isEqualTo("ABcd");
-    assertThat(o.replaceAll(repls(ab, bc, cd)).asString()).isEqualTo("ABYZ");
-  }
-
-  @Test
-  public void replaceOverlappingAtFirstCharLongestMatch() {
-    SafeHtml o = html("abcd");
-    RawFindReplace ab = new RawFindReplace("ab", "AB");
-    RawFindReplace abc = new RawFindReplace("[^d][^d][^d]", "234");
-
-    assertThat(o.replaceAll(repls(ab, abc)).asString()).isEqualTo("ABcd");
-    assertThat(o.replaceAll(repls(abc, ab)).asString()).isEqualTo("234d");
-  }
-
-  @Test
-  public void replaceOverlappingAtFirstCharFirstMatch() {
-    SafeHtml o = html("abcd");
-    RawFindReplace ab1 = new RawFindReplace("ab", "AB");
-    RawFindReplace ab2 = new RawFindReplace("[^cd][^cd]", "12");
-
-    assertThat(o.replaceAll(repls(ab1, ab2)).asString()).isEqualTo("ABcd");
-    assertThat(o.replaceAll(repls(ab2, ab1)).asString()).isEqualTo("12cd");
-  }
-
-  @Test
-  public void failedSanitization() {
-    SafeHtml o = html("abcd");
-    LinkFindReplace evil = new LinkFindReplace("(b)", "javascript:alert('$1')");
-    LinkFindReplace ok = new LinkFindReplace("(b)", "/$1");
-    assertThat(o.replaceAll(repls(evil)).asString()).isEqualTo("abcd");
-    String linked = "a<a href=\"/b\">b</a>cd";
-    assertThat(o.replaceAll(repls(ok)).asString()).isEqualTo(linked);
-    assertThat(o.replaceAll(repls(evil, ok)).asString()).isEqualTo(linked);
-  }
-
-  private static SafeHtml html(String text) {
-    return new SafeHtmlBuilder().append(text).toSafeHtml();
-  }
-
-  private static List<FindReplace> repls(FindReplace... repls) {
-    return Arrays.asList(repls);
-  }
-}
diff --git a/javatests/com/google/gwtexpui/safehtml/client/SafeHtml_WikifyListTest.java b/javatests/com/google/gwtexpui/safehtml/client/SafeHtml_WikifyListTest.java
deleted file mode 100644
index d69b36c..0000000
--- a/javatests/com/google/gwtexpui/safehtml/client/SafeHtml_WikifyListTest.java
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "<p>AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.Test;
-
-public class SafeHtml_WikifyListTest {
-  private static final String BEGIN_LIST = "<ul class=\"wikiList\">";
-  private static final String END_LIST = "</ul>";
-
-  private static String item(String raw) {
-    return "<li>" + raw + "</li>";
-  }
-
-  @Test
-  public void bulletList1() {
-    final SafeHtml o = html("A\n\n* line 1\n* 2nd line");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo("<p>A</p>" + BEGIN_LIST + item("line 1") + item("2nd line") + END_LIST);
-  }
-
-  @Test
-  public void bulletList2() {
-    final SafeHtml o = html("A\n\n* line 1\n* 2nd line\n\nB");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(
-            "<p>A</p>" + BEGIN_LIST + item("line 1") + item("2nd line") + END_LIST + "<p>B</p>");
-  }
-
-  @Test
-  public void bulletList3() {
-    final SafeHtml o = html("* line 1\n* 2nd line\n\nB");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(BEGIN_LIST + item("line 1") + item("2nd line") + END_LIST + "<p>B</p>");
-  }
-
-  @Test
-  public void bulletList4() {
-    final SafeHtml o =
-        html(
-            "To see this bug, you have to:\n" //
-                + "* Be on IMAP or EAS (not on POP)\n" //
-                + "* Be very unlucky\n");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(
-            "<p>To see this bug, you have to:</p>"
-                + BEGIN_LIST
-                + item("Be on IMAP or EAS (not on POP)")
-                + item("Be very unlucky")
-                + END_LIST);
-  }
-
-  @Test
-  public void bulletList5() {
-    final SafeHtml o =
-        html(
-            "To see this bug,\n" //
-                + "you have to:\n" //
-                + "* Be on IMAP or EAS (not on POP)\n" //
-                + "* Be very unlucky\n");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(
-            "<p>To see this bug, you have to:</p>"
-                + BEGIN_LIST
-                + item("Be on IMAP or EAS (not on POP)")
-                + item("Be very unlucky")
-                + END_LIST);
-  }
-
-  @Test
-  public void dashList1() {
-    final SafeHtml o = html("A\n\n- line 1\n- 2nd line");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo("<p>A</p>" + BEGIN_LIST + item("line 1") + item("2nd line") + END_LIST);
-  }
-
-  @Test
-  public void dashList2() {
-    final SafeHtml o = html("A\n\n- line 1\n- 2nd line\n\nB");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(
-            "<p>A</p>" + BEGIN_LIST + item("line 1") + item("2nd line") + END_LIST + "<p>B</p>");
-  }
-
-  @Test
-  public void dashList3() {
-    final SafeHtml o = html("- line 1\n- 2nd line\n\nB");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(BEGIN_LIST + item("line 1") + item("2nd line") + END_LIST + "<p>B</p>");
-  }
-
-  private static SafeHtml html(String text) {
-    return new SafeHtmlBuilder().append(text).toSafeHtml();
-  }
-}
diff --git a/javatests/com/google/gwtexpui/safehtml/client/SafeHtml_WikifyPreformatTest.java b/javatests/com/google/gwtexpui/safehtml/client/SafeHtml_WikifyPreformatTest.java
deleted file mode 100644
index 1346cda..0000000
--- a/javatests/com/google/gwtexpui/safehtml/client/SafeHtml_WikifyPreformatTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "<p>AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.Test;
-
-public class SafeHtml_WikifyPreformatTest {
-  private static final String B = "<span class=\"wikiPreFormat\">";
-  private static final String E = "</span><br />";
-
-  private static String pre(String raw) {
-    return B + raw + E;
-  }
-
-  @Test
-  public void preformat1() {
-    final SafeHtml o = html("A\n\n  This is pre\n  formatted");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo("<p>A</p><p>" + pre("  This is pre") + pre("  formatted") + "</p>");
-  }
-
-  @Test
-  public void preformat2() {
-    final SafeHtml o = html("A\n\n  This is pre\n  formatted\n\nbut this is not");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(
-            "<p>A</p>"
-                + "<p>"
-                + pre("  This is pre")
-                + pre("  formatted")
-                + "</p>"
-                + "<p>but this is not</p>");
-  }
-
-  @Test
-  public void preformat3() {
-    final SafeHtml o = html("A\n\n  Q\n    <R>\n  S\n\nB");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(
-            "<p>A</p>"
-                + "<p>"
-                + pre("  Q")
-                + pre("    &lt;R&gt;")
-                + pre("  S")
-                + "</p>"
-                + "<p>B</p>");
-  }
-
-  @Test
-  public void preformat4() {
-    final SafeHtml o = html("  Q\n    <R>\n  S\n\nB");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo("<p>" + pre("  Q") + pre("    &lt;R&gt;") + pre("  S") + "</p><p>B</p>");
-  }
-
-  private static SafeHtml html(String text) {
-    return new SafeHtmlBuilder().append(text).toSafeHtml();
-  }
-}
diff --git a/javatests/com/google/gwtexpui/safehtml/client/SafeHtml_WikifyQuoteTest.java b/javatests/com/google/gwtexpui/safehtml/client/SafeHtml_WikifyQuoteTest.java
deleted file mode 100644
index 2008447..0000000
--- a/javatests/com/google/gwtexpui/safehtml/client/SafeHtml_WikifyQuoteTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "<p>AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.Test;
-
-public class SafeHtml_WikifyQuoteTest {
-  private static final String B = "<blockquote class=\"wikiQuote\">";
-  private static final String E = "</blockquote>";
-
-  private static String quote(String raw) {
-    return B + raw + E;
-  }
-
-  @Test
-  public void quote1() {
-    final SafeHtml o = html("> I'm happy\n > with quotes!\n\nSee above.");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString()).isEqualTo(quote("I&#39;m happy\nwith quotes!") + "<p>See above.</p>");
-  }
-
-  @Test
-  public void quote2() {
-    final SafeHtml o = html("See this said:\n\n > a quoted\n > string block\n\nOK?");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo("<p>See this said:</p>" + quote("a quoted\nstring block") + "<p>OK?</p>");
-  }
-
-  @Test
-  public void nestedQuotes1() {
-    final SafeHtml o = html(" > > prior\n > \n > next\n");
-    final SafeHtml n = o.wikify();
-    assertThat(n.asString()).isEqualTo(quote(quote("prior") + "next\n"));
-  }
-
-  private static SafeHtml html(String text) {
-    return new SafeHtmlBuilder().append(text).toSafeHtml();
-  }
-}
diff --git a/javatests/com/google/gwtexpui/safehtml/client/SafeHtml_WikifyTest.java b/javatests/com/google/gwtexpui/safehtml/client/SafeHtml_WikifyTest.java
deleted file mode 100644
index 166af97..0000000
--- a/javatests/com/google/gwtexpui/safehtml/client/SafeHtml_WikifyTest.java
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "<p>AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gwtexpui.safehtml.client;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.Test;
-
-public class SafeHtml_WikifyTest {
-  @Test
-  public void wikify_OneLine1() {
-    final SafeHtml o = html("A  B");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString()).isEqualTo("<p>A  B</p>");
-  }
-
-  @Test
-  public void wikify_OneLine2() {
-    final SafeHtml o = html("A  B\n");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString()).isEqualTo("<p>A  B\n</p>");
-  }
-
-  @Test
-  public void wikify_OneParagraph1() {
-    final SafeHtml o = html("A\nB");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString()).isEqualTo("<p>A\nB</p>");
-  }
-
-  @Test
-  public void wikify_OneParagraph2() {
-    final SafeHtml o = html("A\nB\n");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString()).isEqualTo("<p>A\nB\n</p>");
-  }
-
-  @Test
-  public void wikify_TwoParagraphs() {
-    final SafeHtml o = html("A\nB\n\nC\nD");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString()).isEqualTo("<p>A\nB</p><p>C\nD</p>");
-  }
-
-  @Test
-  public void linkify_SimpleHttp1() {
-    final SafeHtml o = html("A http://go.here/ B");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(
-            "<p>A <a href=\"http://go.here/\" target=\"_blank\" rel=\"nofollow\""
-                + ">http://go.here/</a> B</p>");
-  }
-
-  @Test
-  public void linkify_SimpleHttps2() {
-    final SafeHtml o = html("A https://go.here/ B");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(
-            "<p>A <a href=\"https://go.here/\" target=\"_blank\" rel=\"nofollow\""
-                + ">https://go.here/</a> B</p>");
-  }
-
-  @Test
-  public void linkify_Parens1() {
-    final SafeHtml o = html("A (http://go.here/) B");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(
-            "<p>A (<a href=\"http://go.here/\" target=\"_blank\" rel=\"nofollow\""
-                + ">http://go.here/</a>) B</p>");
-  }
-
-  @Test
-  public void linkify_Parens() {
-    final SafeHtml o = html("A http://go.here/#m() B");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(
-            "<p>A <a href=\"http://go.here/#m()\" target=\"_blank\" rel=\"nofollow\""
-                + ">http://go.here/#m()</a> B</p>");
-  }
-
-  @Test
-  public void linkify_AngleBrackets1() {
-    final SafeHtml o = html("A <http://go.here/> B");
-    final SafeHtml n = o.wikify();
-    assertThat(o).isNotSameAs(n);
-    assertThat(n.asString())
-        .isEqualTo(
-            "<p>A &lt;<a href=\"http://go.here/\" target=\"_blank\" rel=\"nofollow\""
-                + ">http://go.here/</a>&gt; B</p>");
-  }
-
-  private static SafeHtml html(String text) {
-    return new SafeHtmlBuilder().append(text).toSafeHtml();
-  }
-}
diff --git a/javatests/org/eclipse/jgit/BUILD b/javatests/org/eclipse/jgit/BUILD
deleted file mode 100644
index 213c8c5..0000000
--- a/javatests/org/eclipse/jgit/BUILD
+++ /dev/null
@@ -1,11 +0,0 @@
-java_test(
-    name = "jgit_patch_tests",
-    srcs = glob(["**/*.java"]),
-    test_class = "org.eclipse.jgit.diff.EditDeserializerTest",
-    visibility = ["//visibility:public"],
-    deps = [
-        "//java/org/eclipse/jgit:server",
-        "//lib:junit",
-        "//lib/jgit/org.eclipse.jgit:jgit",
-    ],
-)
diff --git a/javatests/org/eclipse/jgit/diff/EditDeserializerTest.java b/javatests/org/eclipse/jgit/diff/EditDeserializerTest.java
deleted file mode 100644
index c431715..0000000
--- a/javatests/org/eclipse/jgit/diff/EditDeserializerTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.eclipse.jgit.diff;
-
-import static org.junit.Assert.assertNotNull;
-
-import org.junit.Test;
-
-public class EditDeserializerTest {
-  @Test
-  public void diffDeserializer() {
-    assertNotNull("edit deserializer", new EditDeserializer());
-  }
-}
diff --git a/lib/codemirror/BUILD b/lib/codemirror/BUILD
deleted file mode 100644
index d0c9278..0000000
--- a/lib/codemirror/BUILD
+++ /dev/null
@@ -1,11 +0,0 @@
-load("//lib/codemirror:cm.bzl", "pkg_cm")
-
-# This library is only used to insert a license statement into
-# js_licenses.txt.
-java_library(
-    name = "diff-match-patch",
-    data = ["//lib:LICENSE-Apache2.0"],
-    runtime_deps = ["@diff-match-patch//jar"],
-)
-
-pkg_cm()
diff --git a/lib/codemirror/cm.bzl b/lib/codemirror/cm.bzl
deleted file mode 100644
index 593caa3..0000000
--- a/lib/codemirror/cm.bzl
+++ /dev/null
@@ -1,375 +0,0 @@
-load("//tools/bzl:genrule2.bzl", "genrule2")
-
-CM_CSS = [
-    "lib/codemirror.css",
-    "addon/dialog/dialog.css",
-    "addon/merge/merge.css",
-    "addon/scroll/simplescrollbars.css",
-    "addon/search/matchesonscrollbar.css",
-    "addon/lint/lint.css",
-]
-
-CM_JS = [
-    "lib/codemirror.js",
-    "mode/meta.js",
-    "keymap/emacs.js",
-    "keymap/sublime.js",
-    "keymap/vim.js",
-]
-
-CM_ADDONS = [
-    "dialog/dialog.js",
-    "edit/closebrackets.js",
-    "edit/matchbrackets.js",
-    "edit/trailingspace.js",
-    "scroll/annotatescrollbar.js",
-    "scroll/simplescrollbars.js",
-    "search/jump-to-line.js",
-    "search/matchesonscrollbar.js",
-    "search/searchcursor.js",
-    "search/search.js",
-    "selection/mark-selection.js",
-    "mode/multiplex.js",
-    "mode/overlay.js",
-    "mode/simple.js",
-    "lint/lint.js",
-]
-
-# Available themes must be enumerated here,
-# in gerrit-extension-api/src/main/java/com/google/gerrit/extensions/client/Theme.java,
-# in gerrit-gwtui/src/main/java/net/codemirror/theme/Themes.java
-CM_THEMES = [
-    "3024-day",
-    "3024-night",
-    "abcdef",
-    "ambiance",
-    "base16-dark",
-    "base16-light",
-    "bespin",
-    "blackboard",
-    "cobalt",
-    "colorforth",
-    "dracula",
-    "duotone-dark",
-    "duotone-light",
-    "eclipse",
-    "elegant",
-    "erlang-dark",
-    "gruvbox-dark",
-    "hopscotch",
-    "icecoder",
-    "idea",
-    "isotope",
-    "lesser-dark",
-    "liquibyte",
-    "lucario",
-    "material",
-    "mbo",
-    "mdn-like",
-    "midnight",
-    "monokai",
-    "neat",
-    "neo",
-    "night",
-    "paraiso-dark",
-    "paraiso-light",
-    "pastel-on-dark",
-    "railscasts",
-    "rubyblue",
-    "seti",
-    "solarized",
-    "ssms",
-    "the-matrix",
-    "tomorrow-night-bright",
-    "tomorrow-night-eighties",
-    "ttcn",
-    "twilight",
-    "vibrant-ink",
-    "xq-dark",
-    "xq-light",
-    "yeti",
-    "zenburn",
-]
-
-# Available modes must be enumerated here,
-# in gerrit-gwtui/src/main/java/net/codemirror/mode/Modes.java,
-# gerrit-gwtui/src/main/java/net/codemirror/mode/ModeInfo.java,
-# and in CodeMirror's own mode/meta.js script.
-CM_MODES = [
-    "apl",
-    "asciiarmor",
-    "asn.1",
-    "asterisk",
-    "brainfuck",
-    "clike",
-    "clojure",
-    "cmake",
-    "cobol",
-    "coffeescript",
-    "commonlisp",
-    "crystal",
-    "css",
-    "cypher",
-    "d",
-    "dart",
-    "diff",
-    "django",
-    "dockerfile",
-    "dtd",
-    "dylan",
-    "ebnf",
-    "ecl",
-    "eiffel",
-    "elm",
-    "erlang",
-    "factor",
-    "fcl",
-    "forth",
-    "fortran",
-    "gas",
-    "gfm",
-    "gherkin",
-    "go",
-    "groovy",
-    "haml",
-    "handlebars",
-    "haskell-literate",
-    "haskell",
-    "haxe",
-    "htmlembedded",
-    "htmlmixed",
-    "http",
-    "idl",
-    "javascript",
-    "jinja2",
-    "jsx",
-    "julia",
-    "livescript",
-    "lua",
-    "markdown",
-    "mathematica",
-    "mbox",
-    "mirc",
-    "mllike",
-    "modelica",
-    "mscgen",
-    "mumps",
-    "nginx",
-    "nsis",
-    "ntriples",
-    "octave",
-    "oz",
-    "pascal",
-    "pegjs",
-    "perl",
-    "php",
-    "pig",
-    "powershell",
-    "properties",
-    "protobuf",
-    "pug",
-    "puppet",
-    "python",
-    "q",
-    "r",
-    "rpm",
-    "rst",
-    "ruby",
-    "rust",
-    "sas",
-    "sass",
-    "scheme",
-    "shell",
-    "sieve",
-    "slim",
-    "smalltalk",
-    "smarty",
-    "solr",
-    "soy",
-    "sparql",
-    "spreadsheet",
-    "sql",
-    "stex",
-    "stylus",
-    "swift",
-    "tcl",
-    "textile",
-    "tiddlywiki",
-    "tiki",
-    "toml",
-    "tornado",
-    "troff",
-    "ttcn-cfg",
-    "ttcn",
-    "turtle",
-    "twig",
-    "vb",
-    "vbscript",
-    "velocity",
-    "verilog",
-    "vhdl",
-    "vue",
-    "webidl",
-    "xml",
-    "xquery",
-    "yacas",
-    "yaml-frontmatter",
-    "yaml",
-    "z80",
-]
-
-CM_VERSION = "5.37.0"
-
-TOP = "META-INF/resources/webjars/codemirror/%s" % CM_VERSION
-
-TOP_MINIFIED = "META-INF/resources/webjars/codemirror-minified/%s" % CM_VERSION
-
-LICENSE = "//lib:LICENSE-codemirror-original"
-
-LICENSE_MINIFIED = "//lib:LICENSE-codemirror-minified"
-
-DIFF_MATCH_PATCH_VERSION = "20121119-1"
-
-DIFF_MATCH_PATCH_TOP = ("META-INF/resources/webjars/google-diff-match-patch/%s" %
-                        DIFF_MATCH_PATCH_VERSION)
-
-def pkg_cm():
-    for archive, suffix, top, license in [
-        ("@codemirror-original-gwt//jar", "", TOP, LICENSE),
-        ("@codemirror-minified-gwt//jar", "_r", TOP_MINIFIED, LICENSE_MINIFIED),
-    ]:
-        # Main JavaScript and addons
-        genrule2(
-            name = "cm" + suffix,
-            cmd = " && ".join(
-                [
-                    "echo '/** @license' >$@",
-                    "unzip -p $(location %s) %s/LICENSE >>$@" % (archive, top),
-                    "echo '*/' >>$@",
-                ] +
-                ["unzip -p $(location %s) %s/%s >>$@" % (archive, top, n) for n in CM_JS] +
-                [
-                    "unzip -p $(location %s) %s/addon/%s >>$@" % (archive, top, n)
-                    for n in CM_ADDONS
-                ],
-            ),
-            tools = [archive],
-            outs = ["cm%s.js" % suffix],
-        )
-
-        # Main CSS
-        genrule2(
-            name = "css" + suffix,
-            cmd = " && ".join(
-                [
-                    "echo '/** @license' >$@",
-                    "unzip -p $(location %s) %s/LICENSE >>$@" % (archive, top),
-                    "echo '*/' >>$@",
-                ] +
-                [
-                    "unzip -p $(location %s) %s/%s >>$@" % (archive, top, n)
-                    for n in CM_CSS
-                ],
-            ),
-            tools = [archive],
-            outs = ["cm%s.css" % suffix],
-        )
-
-        # Modes
-        for n in CM_MODES:
-            genrule2(
-                name = "mode_%s%s" % (n, suffix),
-                cmd = " && ".join(
-                    [
-                        "echo '/** @license' >$@",
-                        "unzip -p $(location %s) %s/LICENSE >>$@" % (archive, top),
-                        "echo '*/' >>$@",
-                        "unzip -p $(location %s) %s/mode/%s/%s.js >>$@" % (archive, top, n, n),
-                    ],
-                ),
-                tools = [archive],
-                outs = ["mode_%s%s.js" % (n, suffix)],
-            )
-
-        # Themes
-        for n in CM_THEMES:
-            genrule2(
-                name = "theme_%s%s" % (n, suffix),
-                cmd = " && ".join(
-                    [
-                        "echo '/** @license' >$@",
-                        "unzip -p $(location %s) %s/LICENSE >>$@" % (archive, top),
-                        "echo '*/' >>$@",
-                        "unzip -p $(location %s) %s/theme/%s.css >>$@" % (archive, top, n),
-                    ],
-                ),
-                tools = [archive],
-                outs = ["theme_%s%s.css" % (n, suffix)],
-            )
-
-        # Merge Addon bundled with diff-match-patch
-        genrule2(
-            name = "addon_merge_with_diff_match_patch%s" % suffix,
-            cmd = " && ".join(
-                [
-                    "echo '/** @license' >$@",
-                    "unzip -p $(location %s) %s/LICENSE >>$@" % (archive, top),
-                    "echo '*/\n' >>$@",
-                    "echo '// The google-diff-match-patch library is from https://repo1.maven.org/maven2/org/webjars/google-diff-match-patch/%s/google-diff-match-patch-%s.jar\n' >> $@" % (DIFF_MATCH_PATCH_VERSION, DIFF_MATCH_PATCH_VERSION),
-                    "echo '/** @license' >>$@",
-                    "echo 'LICENSE-Apache2.0' >>$@",
-                    "echo '*/' >>$@",
-                    "unzip -p $(location @diff-match-patch//jar) %s/diff_match_patch.js >>$@" % DIFF_MATCH_PATCH_TOP,
-                    "echo ';' >> $@",
-                    "unzip -p $(location %s) %s/addon/merge/merge.js >>$@" % (archive, top),
-                ],
-            ),
-            tools = [
-                "@diff-match-patch//jar",
-                # dependency just for license tracking.
-                ":diff-match-patch",
-                archive,
-                "//lib:LICENSE-Apache2.0",
-            ],
-            outs = ["addon_merge_with_diff_match_patch%s.js" % suffix],
-        )
-
-        # Jar packaging
-        genrule2(
-            name = "jar" + suffix,
-            cmd = " && ".join([
-                                  "cd $$TMP",
-                                  "mkdir -p net/codemirror/{addon,lib,mode,theme}",
-                                  "cp $$ROOT/$(location :css%s) net/codemirror/lib/cm.css" % suffix,
-                                  "cp $$ROOT/$(location :cm%s) net/codemirror/lib/cm.js" % suffix,
-                              ] +
-                              [
-                                  "cp $$ROOT/$(location :mode_%s%s) net/codemirror/mode/%s.js" % (n, suffix, n)
-                                  for n in CM_MODES
-                              ] +
-                              [
-                                  "cp $$ROOT/$(location :theme_%s%s) net/codemirror/theme/%s.css" % (n, suffix, n)
-                                  for n in CM_THEMES
-                              ] +
-                              ["cp $$ROOT/$(location :addon_merge_with_diff_match_patch%s) net/codemirror/addon/merge_bundled.js" % suffix] +
-                              ["zip -qr $$ROOT/$@ net/codemirror/{addon,lib,mode,theme}"]),
-            tools = [
-                ":addon_merge_with_diff_match_patch%s" % suffix,
-                ":cm%s" % suffix,
-                ":css%s" % suffix,
-            ] + [
-                ":mode_%s%s" % (n, suffix)
-                for n in CM_MODES
-            ] + [
-                ":theme_%s%s" % (n, suffix)
-                for n in CM_THEMES
-            ],
-            outs = ["codemirror%s.jar" % suffix],
-        )
-
-        native.java_import(
-            name = "codemirror" + suffix,
-            jars = [":jar%s" % suffix],
-            visibility = ["//visibility:public"],
-            data = [license],
-        )
diff --git a/lib/greenmail/BUILD b/lib/greenmail/BUILD
index 55eb9f3..b09f27b 100644
--- a/lib/greenmail/BUILD
+++ b/lib/greenmail/BUILD
@@ -1,8 +1,23 @@
 package(default_visibility = ["//visibility:public"])
 
+POST_JDK8_DEPS = [":javax-activation"]
+
+java_library(
+    name = "javax-activation",
+    testonly = 1,
+    data = ["//lib:LICENSE-DO_NOT_DISTRIBUTE"],
+    exports = ["@javax-activation//jar"],
+)
+
 java_library(
     name = "greenmail",
+    testonly = 1,
     data = ["//lib:LICENSE-Apache2.0"],
     visibility = ["//visibility:public"],
     exports = ["@greenmail//jar"],
+    runtime_deps = select({
+        "//:java9": POST_JDK8_DEPS,
+        "//:java_next": POST_JDK8_DEPS,
+        "//conditions:default": [],
+    }),
 )
diff --git a/lib/gwt/BUILD b/lib/gwt/BUILD
deleted file mode 100644
index fa2fef3..0000000
--- a/lib/gwt/BUILD
+++ /dev/null
@@ -1,45 +0,0 @@
-[java_library(
-    name = n,
-    data = ["//lib:LICENSE-Apache2.0"],
-    visibility = ["//visibility:public"],
-    exports = ["@%s//jar" % n],
-) for n in [
-    "ant",
-    "colt",
-    "dev",
-    "javax-validation",
-    "jsinterop-annotations",
-    "tapestry",
-    "user",
-    "w3c-css-sac",
-]]
-
-java_library(
-    name = "user-neverlink",
-    data = ["//lib:LICENSE-Apache2.0"],
-    neverlink = 1,
-    visibility = ["//visibility:public"],
-    exports = ["@user//jar"],
-)
-
-java_library(
-    name = "dev-neverlink",
-    data = ["//lib:LICENSE-Apache2.0"],
-    neverlink = 1,
-    visibility = ["//visibility:public"],
-    exports = ["@dev//jar"],
-)
-
-java_library(
-    name = "javax-validation_src",
-    data = ["//lib:LICENSE-Apache2.0"],
-    visibility = ["//visibility:public"],
-    exports = ["@javax-validation//jar:src"],
-)
-
-java_library(
-    name = "jsinterop-annotations_src",
-    data = ["//lib:LICENSE-Apache2.0"],
-    visibility = ["//visibility:public"],
-    exports = ["@jsinterop-annotations//jar:src"],
-)
diff --git a/plugins/BUILD b/plugins/BUILD
index 137be6e..1ce0fba7 100644
--- a/plugins/BUILD
+++ b/plugins/BUILD
@@ -31,6 +31,7 @@
     "//java/com/google/gerrit/common:annotations",
     "//java/com/google/gerrit/common:server",
     "//java/com/google/gerrit/extensions:api",
+    "//java/com/google/gerrit/git",
     "//java/com/google/gerrit/index",
     "//java/com/google/gerrit/index:query_exception",
     "//java/com/google/gerrit/lifecycle",
diff --git a/plugins/reviewnotes b/plugins/reviewnotes
index 131f578..041ac8d 160000
--- a/plugins/reviewnotes
+++ b/plugins/reviewnotes
@@ -1 +1 @@
-Subproject commit 131f5782a6723d1e017f53cf4e56ff363263b076
+Subproject commit 041ac8d9fb0c0e5adff0aa37773a1931aced5a9a
diff --git a/polygerrit-ui/README.md b/polygerrit-ui/README.md
index 3c21a42..943c328 100644
--- a/polygerrit-ui/README.md
+++ b/polygerrit-ui/README.md
@@ -71,9 +71,9 @@
 that serves PolyGerrit:
 
 ```sh
-bazel build polygerrit &&
+bazel build gerrit &&
   $(bazel info output_base)/external/local_jdk/bin/java \
-  -jar bazel-bin/polygerrit.war daemon --polygerrit-dev \
+  -jar bazel-bin/gerrit.war daemon --polygerrit-dev \
   -d ../gerrit_testsite --console-log --show-stack-trace
 ```
 
diff --git a/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior.html b/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior.html
index 48bd10e..1748647 100644
--- a/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior.html
+++ b/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior.html
@@ -21,27 +21,12 @@
 
   window.Gerrit = window.Gerrit || {};
 
-  const PROJECT_DASHBOARD_PATTERN = /\/p\/(.+)\/\+\/dashboard\/(.*)/;
-  const REPO_URL_PATTERN = /^\/admin\/repos/;
-  const PROJECT_URL = '/admin/projects';
   /** @polymerBehavior Gerrit.BaseUrlBehavior */
   Gerrit.BaseUrlBehavior = {
     /** @return {string} */
     getBaseUrl() {
       return window.CANONICAL_PATH || '';
     },
-
-    computeGwtUrl(path) {
-      const base = this.getBaseUrl();
-      let clientPath = path.substring(base.length);
-      const match = clientPath.match(PROJECT_DASHBOARD_PATTERN);
-      if (match) {
-        clientPath = `/projects/${match[1]},dashboards/${match[2]}`;
-      }
-      // Replace any '/admin/project' links to '/admin/repo'
-      clientPath = clientPath.replace(REPO_URL_PATTERN, PROJECT_URL);
-      return base + '/?polygerrit=0#' + clientPath;
-    },
   };
 })(window);
 </script>
diff --git a/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior_test.html b/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior_test.html
index 429abe1..4b670da 100644
--- a/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior_test.html
@@ -66,24 +66,5 @@
     test('getBaseUrl', () => {
       assert.deepEqual(element.getBaseUrl(), '/r');
     });
-
-    test('computeGwtUrl', () => {
-      assert.deepEqual(
-          element.computeGwtUrl('/r/c/1/'),
-          '/r/?polygerrit=0#/c/1/'
-      );
-    });
-
-    test('computeGwtUrl for project dashboard', () => {
-      assert.deepEqual(
-          element.computeGwtUrl('/r/p/gerrit/proj/+/dashboard/main:default'),
-          '/r/?polygerrit=0#/projects/gerrit/proj,dashboards/main:default');
-    });
-
-    test('computeGwtUrl for project access', () => {
-      assert.deepEqual(
-          element.computeGwtUrl('/r/admin/repos/demo-project,access'),
-          '/r/?polygerrit=0#/admin/projects/demo-project,access');
-    });
   });
 </script>
diff --git a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.js b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.js
index 6443095..77a1e2a 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.js
+++ b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.js
@@ -307,9 +307,9 @@
         commands.push({
           title,
           command: commandObj[title]
-              .replace('${project}', repo)
+              .replace('${project}', encodeURI(repo))
               .replace('${project-base-name}',
-              repo.substring(repo.lastIndexOf('/') + 1)),
+              encodeURI(repo.substring(repo.lastIndexOf('/') + 1))),
         });
       }
       return commands;
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.html b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.html
index 372e6be..2235ae1 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.html
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.html
@@ -55,14 +55,14 @@
       </tr>
       <template is="dom-repeat" items="[[sections]]" as="changeSection"
           index-as="sectionIndex">
-        <template is="dom-if" if="[[changeSection.sectionName]]">
+        <template is="dom-if" if="[[changeSection.name]]">
           <tr class="groupHeader">
             <td class="leftPadding"></td>
             <td class="star" hidden$="[[!showStar]]" hidden></td>
             <td class="cell"
                 colspan$="[[_computeColspan(changeTableColumns, labelNames)]]">
               <a href$="[[_sectionHref(changeSection.query)]]">
-                [[changeSection.sectionName]]
+                [[changeSection.name]]
               </a>
             </td>
           </tr>
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
index de97e62..708a730 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
@@ -63,7 +63,7 @@
        * properties should not be used together.
        *
        * @type {!Array<{
-       *   sectionName: string,
+       *   name: string,
        *   query: string,
        *   results: !Array<!Object>
        * }>}
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
index 56bc17c..0625bbe 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
@@ -207,7 +207,7 @@
               this._showNewUserHelp = lastResultSet.length == 0;
             }
             this._results = changes.map((results, i) => ({
-              sectionName: res.sections[i].name,
+              name: res.sections[i].name,
               query: res.sections[i].query,
               results,
               isOutgoing: res.sections[i].isOutgoing,
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.html b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.html
index 3a3454d..618ec65 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.html
@@ -279,7 +279,7 @@
 
       return element._fetchDashboardChanges({sections}, false).then(() => {
         assert.equal(element._results.length, 1);
-        assert.equal(element._results[0].sectionName, 'test2');
+        assert.equal(element._results[0].name, 'test2');
       });
     });
 
diff --git a/polygerrit-ui/app/elements/change-list/gr-embed-dashboard/gr-embed-dashboard.html b/polygerrit-ui/app/elements/change-list/gr-embed-dashboard/gr-embed-dashboard.html
new file mode 100644
index 0000000..2394e24
--- /dev/null
+++ b/polygerrit-ui/app/elements/change-list/gr-embed-dashboard/gr-embed-dashboard.html
@@ -0,0 +1,41 @@
+<!--
+@license
+Copyright (C) 2018 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<link rel="import" href="../../../bower_components/polymer/polymer.html">
+
+<link rel="import" href="../../change-list/gr-change-list/gr-change-list.html">
+<link rel="import" href="../gr-create-change-help/gr-create-change-help.html">
+
+<dom-module id="gr-embed-dashboard">
+  <template>
+    <gr-change-list
+        show-star
+        account="[[account]]"
+        preferences="[[preferences]]"
+        sections="[[sections]]">
+      <div id="emptyOutgoing" slot="empty-outgoing">
+        <template is="dom-if" if="[[showNewUserHelp]]">
+          <gr-create-change-help></gr-create-change-help>
+        </template>
+        <template is="dom-if" if="[[!showNewUserHelp]]">
+          No changes
+        </template>
+      </div>
+    </gr-change-list>
+  </template>
+  <script src="gr-embed-dashboard.js"></script>
+</dom-module>
diff --git a/polygerrit-ui/app/elements/change-list/gr-embed-dashboard/gr-embed-dashboard.js b/polygerrit-ui/app/elements/change-list/gr-embed-dashboard/gr-embed-dashboard.js
new file mode 100644
index 0000000..e31f9ad
--- /dev/null
+++ b/polygerrit-ui/app/elements/change-list/gr-embed-dashboard/gr-embed-dashboard.js
@@ -0,0 +1,29 @@
+/**
+ * @license
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+(function() {
+  'use strict';
+
+  Polymer({
+    is: 'gr-embed-dashboard',
+    properties: {
+      account: Object,
+      sections: Array,
+      preferences: Object,
+      showNewUserHelp: Boolean,
+    },
+  });
+})();
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
index 3f5bd13..38f5f2f 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
@@ -531,6 +531,7 @@
             patch-num="{{_patchRange.patchNum}}"
             base-patch-num="{{_patchRange.basePatchNum}}"
             files-expanded="[[_filesExpanded]]"
+            diff-prefs-disabled="[[_diffPrefsDisabled]]"
             on-open-diff-prefs="_handleOpenDiffPrefs"
             on-open-download-dialog="_handleOpenDownloadDialog"
             on-open-upload-help-dialog="_handleOpenUploadHelpDialog"
@@ -587,6 +588,7 @@
             change-comments="[[_changeComments]]"
             project-name="[[_change.project]]"
             show-reply-buttons="[[_loggedIn]]"
+            on-message-anchor-tap="_handleMessageAnchorTap"
             on-reply="_handleMessageReply"></gr-messages-list>
       </template>
       <template is="dom-if" if="[[!_showMessagesView]]">
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
index 909a1ee..bb51fcc 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
@@ -44,6 +44,8 @@
 
   const TRAILING_WHITESPACE_REGEX = /[ \t]+$/gm;
 
+  const MSG_PREFIX = '#message-';
+
   const ReloadToastMessage = {
     NEWER_REVISION: 'A newer patch set has been uploaded',
     RESTORED: 'This change has been restored',
@@ -106,6 +108,14 @@
         type: Boolean,
         value: false,
       },
+      disableDiffPrefs: {
+        type: Boolean,
+        value: false,
+      },
+      _diffPrefsDisabled: {
+        type: Boolean,
+        computed: '_computeDiffPrefsDisabled(disableDiffPrefs, _loggedIn)',
+      },
       _commentThreads: Array,
       /** @type {?} */
       _serverConfig: {
@@ -452,9 +462,9 @@
     },
 
     _handleCommentSave(e) {
-      if (!e.target.comment.__draft) { return; }
+      const draft = e.detail.comment;
+      if (!draft.__draft) { return; }
 
-      const draft = e.target.comment;
       draft.patch_set = draft.patch_set || this._patchRange.patchNum;
 
       // The use of path-based notification helpers (set, push) can’t be used
@@ -484,9 +494,9 @@
     },
 
     _handleCommentDiscard(e) {
-      if (!e.target.comment.__draft) { return; }
+      const draft = e.detail.comment;
+      if (!draft.__draft) { return; }
 
-      const draft = e.target.comment;
       if (!this._diffDrafts[draft.path]) {
         return;
       }
@@ -721,10 +731,17 @@
       this.viewState.numFilesShown = numFilesShown;
     },
 
+    _handleMessageAnchorTap(e) {
+      const hash = MSG_PREFIX + e.detail.id;
+      const url = Gerrit.Nav.getUrlForChange(this._change,
+          this._patchRange.patchNum, this._patchRange.basePatchNum,
+          this._editMode, hash);
+      history.replaceState(null, '', url);
+    },
+
     _maybeScrollToMessage(hash) {
-      const msgPrefix = '#message-';
-      if (hash.startsWith(msgPrefix)) {
-        this.messagesList.scrollToMessage(hash.substr(msgPrefix.length));
+      if (hash.startsWith(MSG_PREFIX)) {
+        this.messagesList.scrollToMessage(hash.substr(MSG_PREFIX.length));
       }
     },
 
@@ -978,6 +995,8 @@
       if (this.shouldSuppressKeyboardShortcut(e) ||
           this.modifierPressed(e)) { return; }
 
+      if (this._diffPrefsDisabled) { return; }
+
       e.preventDefault();
       this.$.fileList.openDiffPrefs();
     },
@@ -1664,5 +1683,9 @@
     _computeCurrentRevision(currentRevision, revisions) {
       return revisions && revisions[currentRevision];
     },
+
+    _computeDiffPrefsDisabled(disableDiffPrefs, loggedIn) {
+      return disableDiffPrefs || !loggedIn;
+    },
   });
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html
index f6acef6..a88142e 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html
@@ -95,6 +95,20 @@
       return element.getComputedStyleValue(cssParam);
     };
 
+    test('_handleMessageAnchorTap', () => {
+      element._changeNum = '1';
+      element._patchRange = {
+        basePatchNum: 'PARENT',
+        patchNum: 1,
+      };
+      const getUrlStub = sandbox.stub(Gerrit.Nav, 'getUrlForChange');
+      const replaceStateStub = sandbox.stub(history, 'replaceState');
+      element._handleMessageAnchorTap({detail: {id: 'a12345'}});
+
+      assert.equal(getUrlStub.lastCall.args[4], '#message-a12345');
+      assert.isTrue(replaceStateStub.called);
+    });
+
     suite('keyboard shortcuts', () => {
       test('t to add topic', () => {
         const editStub = sandbox.stub(element.$.metadata, 'editTopic');
@@ -284,6 +298,16 @@
 
       test(', should open diff preferences', () => {
         const stub = sandbox.stub(element.$.fileList.$.diffPreferences, 'open');
+        element._loggedIn = false;
+        element.disableDiffPrefs = true;
+        MockInteractions.pressAndReleaseKeyOn(element, 188, null, ',');
+        assert.isFalse(stub.called);
+
+        element._loggedIn = true;
+        MockInteractions.pressAndReleaseKeyOn(element, 188, null, ',');
+        assert.isFalse(stub.called);
+
+        element.disableDiffPrefs = false;
         MockInteractions.pressAndReleaseKeyOn(element, 188, null, ',');
         assert.isTrue(stub.called);
       });
@@ -642,12 +666,12 @@
         path: '/foo/bar.txt',
         text: 'hello',
       };
-      element._handleCommentSave({target: {comment: draft}});
+      element._handleCommentSave({detail: {comment: draft}});
       draft.patch_set = 2;
       assert.deepEqual(element._diffDrafts, {'/foo/bar.txt': [draft]});
       draft.patch_set = null;
       draft.text = 'hello, there';
-      element._handleCommentSave({target: {comment: draft}});
+      element._handleCommentSave({detail: {comment: draft}});
       draft.patch_set = 2;
       assert.deepEqual(element._diffDrafts, {'/foo/bar.txt': [draft]});
       const draft2 = {
@@ -656,14 +680,14 @@
         path: '/foo/bar.txt',
         text: 'hola',
       };
-      element._handleCommentSave({target: {comment: draft2}});
+      element._handleCommentSave({detail: {comment: draft2}});
       draft2.patch_set = 2;
       assert.deepEqual(element._diffDrafts, {'/foo/bar.txt': [draft, draft2]});
       draft.patch_set = null;
-      element._handleCommentDiscard({target: {comment: draft}});
+      element._handleCommentDiscard({detail: {comment: draft}});
       draft.patch_set = 2;
       assert.deepEqual(element._diffDrafts, {'/foo/bar.txt': [draft2]});
-      element._handleCommentDiscard({target: {comment: draft2}});
+      element._handleCommentDiscard({detail: {comment: draft2}});
       assert.deepEqual(element._diffDrafts, {});
     });
 
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.html b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.html
index 142e706..924ddab 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.html
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.html
@@ -249,10 +249,10 @@
           <gr-diff-mode-selector
               id="modeSelect"
               mode="{{diffViewMode}}"
-              save-on-change="[[loggedIn]]"></gr-diff-mode-selector>
+              save-on-change="[[!diffPrefsDisabled]]"></gr-diff-mode-selector>
           <span id="diffPrefsContainer"
               class="hideOnEdit"
-              hidden$="[[_computePrefsButtonHidden(diffPrefs, loggedIn)]]"
+              hidden$="[[_computePrefsButtonHidden(diffPrefs, diffPrefsDisabled)]]"
               hidden>
             <gr-button
                 link
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.js b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.js
index 665472b..b9e6288 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.js
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.js
@@ -62,6 +62,7 @@
       serverConfig: Object,
       shownFileCount: Number,
       diffPrefs: Object,
+      diffPrefsDisabled: Boolean,
       diffViewMode: {
         type: String,
         notify: true,
@@ -186,11 +187,10 @@
           });
     },
 
-    _computePrefsButtonHidden(prefs, loggedIn) {
-      return !loggedIn || !prefs;
+    _computePrefsButtonHidden(prefs, diffPrefsDisabled) {
+      return diffPrefsDisabled || !prefs;
     },
 
-
     _fileListActionsVisible(shownFileCount, maxFilesForBulkActions) {
       return shownFileCount <= maxFilesForBulkActions;
     },
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.html b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.html
index e2685e1..adfeeb4 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.html
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.html
@@ -62,21 +62,21 @@
       });
     });
 
-    test('Diff preferences hidden when no prefs or logged out', () => {
-      element.loggedIn = false;
+    test('Diff preferences hidden when no prefs or diffPrefsDisabled', () => {
+      element.diffPrefsDisabled = true;
       flushAsynchronousOperations();
       assert.isTrue(element.$.diffPrefsContainer.hidden);
 
-      element.loggedIn = true;
+      element.diffPrefsDisabled = false;
       flushAsynchronousOperations();
       assert.isTrue(element.$.diffPrefsContainer.hidden);
 
-      element.loggedIn = false;
+      element.diffPrefsDisabled = true;
       element.diffPrefs = {font_size: '12'};
       flushAsynchronousOperations();
       assert.isTrue(element.$.diffPrefsContainer.hidden);
 
-      element.loggedIn = true;
+      element.diffPrefsDisabled = false;
       flushAsynchronousOperations();
       assert.isFalse(element.$.diffPrefsContainer.hidden);
     });
@@ -265,7 +265,7 @@
 
     suite('editMode behavior', () => {
       setup(() => {
-        element.loggedIn = true;
+        element.diffPrefsDisabled = false;
         element.diffPrefs = {};
       });
 
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html
index 358e994..fa9ec7f 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html
@@ -400,7 +400,6 @@
                 path="[[file.__path]]"
                 prefs="[[diffPrefs]]"
                 project-name="[[change.project]]"
-                project-config="[[projectConfig]]"
                 on-line-selected="_onLineSelected"
                 no-render-on-prefs-change
                 view-mode="[[diffViewMode]]"></gr-diff-host>
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html
index df92b1e..51f0e5f 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html
@@ -1358,7 +1358,7 @@
         id: '503008e2_0ab203ee',
         line: 10,
         updated: '2018-02-14 22:07:43.000000000',
-        message: 'response',
+        message: 'a comment',
         unresolved: true,
       },
       {
@@ -1367,7 +1367,7 @@
         line: 20,
         in_reply_to: 'ecf0b9fa_fe1a5f62',
         updated: '2018-02-13 22:07:43.000000000',
-        message: 'a comments',
+        message: 'response',
         unresolved: true,
       },
     ];
@@ -1704,11 +1704,43 @@
     });
 
     test('reloadCommentsForThreadWithRootId', () => {
+      // Expand the commit message diff
+      MockInteractions.keyUpOn(element, 73, 'shift', 'i');
+      const diffs = renderAndGetNewDiffs(0);
+      flushAsynchronousOperations();
+
+      // Two comment threads should be generated by renderAndGetNewDiffs
+      const threadEls = diffs[0].getThreadEls();
+      assert.equal(threadEls.length, 2);
+      const threadElsByRootId = new Map(
+          threadEls.map(threadEl => [threadEl.rootId, threadEl]));
+
+      const thread1 = threadElsByRootId.get('503008e2_0ab203ee');
+      assert.equal(thread1.comments.length, 1);
+      assert.equal(thread1.comments[0].message, 'a comment');
+      assert.equal(thread1.comments[0].line, 10);
+
+      const thread2 = threadElsByRootId.get('ecf0b9fa_fe1a5f62');
+      assert.equal(thread2.comments.length, 2);
+      assert.isTrue(thread2.comments[0].unresolved);
+      assert.equal(thread2.comments[0].message, 'another comment');
+      assert.equal(thread2.comments[0].line, 20);
+
       const commentStub =
           sandbox.stub(element.changeComments, 'getCommentsForThread');
       const commentStubRes1 = [
         {
           patch_set: 2,
+          id: '503008e2_0ab203ee',
+          line: 20,
+          updated: '2018-02-08 18:49:18.000000000',
+          message: 'edited text',
+          unresolved: false,
+        },
+      ];
+      const commentStubRes2 = [
+        {
+          patch_set: 2,
           id: 'ecf0b9fa_fe1a5f62',
           line: 20,
           updated: '2018-02-08 18:49:18.000000000',
@@ -1719,6 +1751,7 @@
           patch_set: 2,
           id: '503008e2_0ab203ee',
           line: 10,
+          in_reply_to: 'ecf0b9fa_fe1a5f62',
           updated: '2018-02-14 22:07:43.000000000',
           message: 'response',
           unresolved: true,
@@ -1727,57 +1760,35 @@
           patch_set: 2,
           id: '503008e2_0ab203ef',
           line: 20,
-          in_reply_to: 'ecf0b9fa_fe1a5f62',
+          in_reply_to: '503008e2_0ab203ee',
           updated: '2018-02-15 22:07:43.000000000',
           message: 'a third comment in the thread',
           unresolved: true,
         },
       ];
-      const commentStubRes2 = [
-        {
-          patch_set: 2,
-          id: 'ecf0b9fa_fe1a5f62',
-          line: 20,
-          updated: '2018-02-08 18:49:18.000000000',
-          message: 'edited text',
-          unresolved: false,
-        },
-      ];
-      commentStub.withArgs('cc788d2c_cb1d728c').returns(
+      commentStub.withArgs('503008e2_0ab203ee').returns(
           commentStubRes1);
       commentStub.withArgs('ecf0b9fa_fe1a5f62').returns(
           commentStubRes2);
-      // Expand the commit message diff
-      MockInteractions.keyUpOn(element, 73, 'shift', 'i');
-      const diffs = renderAndGetNewDiffs(0);
-      flushAsynchronousOperations();
-
-      // Two comment threads sould be generated
-      const commentThreadEls = diffs[0].getThreadEls();
-      assert(commentThreadEls[0].comments.length, 2);
-      assert(commentThreadEls[1].comments.length, 1);
-      assert.isTrue(commentThreadEls[1].comments[0].unresolved);
-      assert.equal(commentThreadEls[1].comments[0].message, 'another comment');
-
-      // Reload comments from the first comment thread, which should have a new
-      // reply.
-      element.reloadCommentsForThreadWithRootId('cc788d2c_cb1d728c',
-          '/COMMIT_MSG');
-      assert(commentThreadEls[0].comments.length, 3);
-
 
       // Reload comments from the first comment thread, which should have a
       // an updated message and a toggled resolve state.
+      element.reloadCommentsForThreadWithRootId('503008e2_0ab203ee',
+          '/COMMIT_MSG');
+      assert.equal(thread1.comments.length, 1);
+      assert.isFalse(thread1.comments[0].unresolved);
+      assert.equal(thread1.comments[0].message, 'edited text');
+
+      // Reload comments from the second comment thread, which should have a new
+      // reply.
       element.reloadCommentsForThreadWithRootId('ecf0b9fa_fe1a5f62',
           '/COMMIT_MSG');
-      assert(commentThreadEls[1].comments.length, 1);
-      assert.isFalse(commentThreadEls[1].comments[0].unresolved);
-      assert.equal(commentThreadEls[1].comments[0].message, 'edited text');
+      assert.equal(thread2.comments.length, 3);
 
       const commentStubCount = commentStub.callCount;
       const getThreadsSpy = sandbox.spy(diffs[0], 'getThreadEls');
 
-      // Should not be getting threadss when the file is not expanded.
+      // Should not be getting threads when the file is not expanded.
       element.reloadCommentsForThreadWithRootId('ecf0b9fa_fe1a5f62',
           'other/file');
       assert.isFalse(getThreadsSpy.called);
diff --git a/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row.js b/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row.js
index 0682ab2..f472331 100644
--- a/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row.js
+++ b/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row.js
@@ -69,7 +69,8 @@
     },
 
     _computeBlankItems(permittedLabels, label, side) {
-      if (!permittedLabels || !permittedLabels[label] || !this.labelValues ||
+      if (!permittedLabels || !permittedLabels[label] ||
+          !permittedLabels[label].length || !this.labelValues ||
           !Object.keys(this.labelValues).length) {
         return [];
       }
@@ -135,7 +136,8 @@
     },
 
     _computeAnyPermittedLabelValues(permittedLabels, label) {
-      return permittedLabels.hasOwnProperty(label);
+      return permittedLabels.hasOwnProperty(label) &&
+        permittedLabels[label].length;
     },
 
     _computeHiddenClass(permittedLabels, label) {
diff --git a/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row_test.html b/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row_test.html
index e5431f6..1e4d471 100644
--- a/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row_test.html
+++ b/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row_test.html
@@ -258,6 +258,11 @@
       flushAsynchronousOperations();
       assert.isOk(element.$$('iron-selector'));
       assert.isTrue(element.$$('iron-selector').hidden);
+
+      element.permittedLabels = {Verified: []};
+      flushAsynchronousOperations();
+      assert.isOk(element.$$('iron-selector'));
+      assert.isTrue(element.$$('iron-selector').hidden);
     });
 
     test('asymetrical labels', () => {
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message.html b/polygerrit-ui/app/elements/change/gr-message/gr-message.html
index 19b0716b..32c4c1f 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message.html
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message.html
@@ -132,9 +132,12 @@
         right: var(--default-horizontal-margin);
         top: 10px;
       }
-      .date {
+      span.date {
         color: var(--deemphasized-text-color);
       }
+      span.date:hover {
+        text-decoration: underline;
+      }
       .dateContainer iron-icon {
         cursor: pointer;
       }
@@ -227,12 +230,12 @@
             </span>
           </template>
           <template is="dom-if" if="[[message.id]]">
-            <a class="date" href$="[[_computeMessageHash(message)]]" on-tap="_handleLinkTap">
+            <span class="date" on-tap="_handleAnchorTap">
               <gr-date-formatter
                   has-tooltip
                   show-date-and-time
                   date-str="[[message.date]]"></gr-date-formatter>
-            </a>
+            </span>
           </template>
           <iron-icon
               id="expandToggle"
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message.js b/polygerrit-ui/app/elements/change/gr-message/gr-message.js
index 0590c73..8ecd6b0 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message.js
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message.js
@@ -24,17 +24,17 @@
     is: 'gr-message',
 
     /**
-     * Fired when this message's permalink is tapped.
-     *
-     * @event scroll-to
-     */
-
-    /**
      * Fired when this message's reply link is tapped.
      *
      * @event reply
      */
 
+    /**
+     * Fired when the message's timestamp is tapped.
+     *
+     * @event message-anchor-tap
+     */
+
     listeners: {
       tap: '_handleTap',
     },
@@ -223,22 +223,12 @@
       return classes.join(' ');
     },
 
-    _computeMessageHash(message) {
-      return '#message-' + message.id;
-    },
-
-    _handleLinkTap(e) {
+    _handleAnchorTap(e) {
       e.preventDefault();
-
-      this.fire('scroll-to', {message: this.message}, {bubbles: false});
-
-      const hash = this._computeMessageHash(this.message);
-      // Don't add the hash to the window history if it's already there.
-      // Otherwise you mess up expected back button behavior.
-      if (window.location.hash == hash) { return; }
-      // Change the URL but don’t trigger a nav event. Otherwise it will
-      // reload the page.
-      page.show(window.location.pathname + hash, null, false);
+      this.dispatchEvent(new CustomEvent('message-anchor-tap', {
+        bubbles: true,
+        detail: {id: this.message.id},
+      }));
     },
 
     _handleReplyTap(e) {
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message_test.html b/polygerrit-ui/app/elements/change/gr-message/gr-message_test.html
index 870f366..64a5b26 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message_test.html
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message_test.html
@@ -164,6 +164,24 @@
       });
     });
 
+    test('clicking on date link fires event', () => {
+      element.message = {
+        type: 'REVIEWER_UPDATE',
+        updated: '2016-01-12 20:24:49.448000000',
+        reviewer: {},
+        id: '47c43261_55aa2c41',
+      };
+      flushAsynchronousOperations();
+      const stub = sinon.stub();
+      element.addEventListener('message-anchor-tap', stub);
+      const dateEl = element.$$('.date');
+      assert.ok(dateEl);
+      MockInteractions.tap(dateEl);
+
+      assert.isTrue(stub.called);
+      assert.deepEqual(stub.lastCall.args[0].detail, {id: element.message.id});
+    });
+
     test('votes', () => {
       element.message = {
         author: {},
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.html b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.html
index 0a7dacc..80708a1 100644
--- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.html
+++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.html
@@ -109,7 +109,7 @@
           hide-automated="[[_hideAutomated]]"
           project-name="[[projectName]]"
           show-reply-button="[[showReplyButtons]]"
-          on-scroll-to="_handleScrollTo"
+          on-message-anchor-tap="_handleAnchorTap"
           label-extremes="[[_labelExtremes]]"
           data-message-id$="[[message.id]]"></gr-message>
     </template>
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.js b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.js
index 89a3523..023431c 100644
--- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.js
+++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.js
@@ -184,8 +184,8 @@
       this.handleExpandCollapse(!this._expanded);
     },
 
-    _handleScrollTo(e) {
-      this.scrollToMessage(e.detail.message.id);
+    _handleAnchorTap(e) {
+      this.scrollToMessage(e.detail.id);
     },
 
     _hasAutomatedMessages(messages) {
diff --git a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.html b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.html
index 3650707..b1433a3 100644
--- a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.html
+++ b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.html
@@ -33,6 +33,8 @@
     //        also be provided.
     //    - `edit`, optional, Boolean: whether or not to load the file list with
     //        edit controls.
+    //    - `messageHash`, optional, String: the hash of the change message to
+    //        scroll to.
     //
     // - Gerrit.Nav.View.SEARCH:
     //    - `query`, optional, String: the literal search query. If provided,
@@ -353,9 +355,11 @@
        * @param {number|string=} opt_basePatchNum The string 'PARENT' can be
        *     used for none.
        * @param {boolean=} opt_isEdit
+       * @param {string=} opt_messageHash
        * @return {string}
        */
-      getUrlForChange(change, opt_patchNum, opt_basePatchNum, opt_isEdit) {
+      getUrlForChange(change, opt_patchNum, opt_basePatchNum, opt_isEdit,
+          opt_messageHash) {
         if (opt_basePatchNum === PARENT_PATCHNUM) {
           opt_basePatchNum = undefined;
         }
@@ -369,6 +373,7 @@
           basePatchNum: opt_basePatchNum,
           edit: opt_isEdit,
           host: change.internalHost || undefined,
+          messageHash: opt_messageHash,
         });
       },
 
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router.js b/polygerrit-ui/app/elements/core/gr-router/gr-router.js
index 2a62115..8ae30ad 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router.js
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.js
@@ -395,6 +395,9 @@
       } else if (params.edit) {
         suffix += ',edit';
       }
+      if (params.messageHash) {
+        suffix += params.messageHash;
+      }
       if (params.project) {
         const encodedProject = this.encodeURL(params.project, true);
         return `/c/${encodedProject}/+/${params.changeNum}${suffix}`;
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router_test.html b/polygerrit-ui/app/elements/core/gr-router/gr-router_test.html
index f221706..584fb35 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router_test.html
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router_test.html
@@ -301,6 +301,9 @@
         paramsWithQuery.basePatchNum = 5;
         assert.equal(element._generateUrl(paramsWithQuery),
             '/c/test/+/1234/5..10?revert&foo=bar');
+
+        params.messageHash = '#123';
+        assert.equal(element._generateUrl(params), '/c/test/+/1234/5..10#123');
       });
 
       test('change with repo name encoding', () => {
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 b2fc64c..d2731a2 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
@@ -14,14 +14,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-(function(window, GrDiffBuilderSideBySide) {
+(function(window, GrDiffBuilder) {
   'use strict';
 
   // Prevent redefinition.
   if (window.GrDiffBuilderBinary) { return; }
 
-  function GrDiffBuilderBinary(diff, comments, prefs, outputEl) {
-    GrDiffBuilder.call(this, diff, comments, null, prefs, outputEl);
+  function GrDiffBuilderBinary(diff, commentThreadEls, prefs,
+      outputEl) {
+    GrDiffBuilder.call(this, diff, commentThreadEls, prefs,
+        outputEl);
   }
 
   GrDiffBuilderBinary.prototype = Object.create(GrDiffBuilder.prototype);
@@ -43,4 +45,4 @@
   };
 
   window.GrDiffBuilderBinary = GrDiffBuilderBinary;
-})(window, GrDiffBuilderSideBySide);
+})(window, GrDiffBuilder);
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 88ff79b..f05f4f0 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,9 +22,9 @@
 
   const IMAGE_MIME_PATTERN = /^image\/(bmp|gif|jpeg|jpg|png|tiff|webp)$/;
 
-  function GrDiffBuilderImage(diff, comments, createThreadGroupFn, prefs,
+  function GrDiffBuilderImage(diff, commentThreadEls, prefs,
       outputEl, baseImage, revisionImage) {
-    GrDiffBuilderSideBySide.call(this, diff, comments, createThreadGroupFn,
+    GrDiffBuilderSideBySide.call(this, diff, commentThreadEls,
         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 fafae63..81cbabb 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,9 +20,9 @@
   // Prevent redefinition.
   if (window.GrDiffBuilderSideBySide) { return; }
 
-  function GrDiffBuilderSideBySide(diff, comments, createThreadGroupFn, prefs,
-      outputEl, layers) {
-    GrDiffBuilder.call(this, diff, comments, createThreadGroupFn, prefs,
+  function GrDiffBuilderSideBySide(diff, commentThreadEls,
+      prefs, outputEl, layers) {
+    GrDiffBuilder.call(this, diff, commentThreadEls, prefs,
         outputEl, layers);
   }
   GrDiffBuilderSideBySide.prototype = Object.create(GrDiffBuilder.prototype);
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 9a04b1f..2dcdee4 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,9 +20,9 @@
   // Prevent redefinition.
   if (window.GrDiffBuilderUnified) { return; }
 
-  function GrDiffBuilderUnified(diff, comments, createThreadGroupFn, prefs,
+  function GrDiffBuilderUnified(diff, commentThreadEls, prefs,
       outputEl, layers) {
-    GrDiffBuilder.call(this, diff, comments, createThreadGroupFn, prefs,
+    GrDiffBuilder.call(this, diff, commentThreadEls, prefs,
         outputEl, layers);
   }
   GrDiffBuilderUnified.prototype = Object.create(GrDiffBuilder.prototype);
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 cc66e3b..6aea35b 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
@@ -16,9 +16,9 @@
 -->
 <link rel="import" href="../../../bower_components/polymer/polymer.html">
 <link rel="import" href="../../core/gr-reporting/gr-reporting.html">
-<link rel="import" href="../gr-diff-comment-thread/gr-diff-comment-thread.html">
-<link rel="import" href="../gr-diff-comment-thread-group/gr-diff-comment-thread-group.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">
 
@@ -29,7 +29,7 @@
     </div>
     <gr-ranged-comment-layer
         id="rangeLayer"
-        comments="[[comments]]"></gr-ranged-comment-layer>
+        comment-ranges="[[commentRanges]]"></gr-ranged-comment-layer>
     <gr-syntax-layer
         id="syntaxLayer"
         diff="[[diff]]"></gr-syntax-layer>
@@ -51,16 +51,6 @@
     (function() {
       'use strict';
 
-      const Defs = {};
-
-      /**
-       * @typedef {{
-       *  number: number,
-       *  leftSide: {boolean}
-       * }}
-       */
-      Defs.LineOfInterest;
-
       const DiffViewMode = {
         SIDE_BY_SIDE: 'SIDE_BY_SIDE',
         UNIFIED: 'UNIFIED_DIFF',
@@ -109,32 +99,32 @@
           changeNum: String,
           patchNum: String,
           viewMode: String,
-          comments: Object,
           isImageDiff: Boolean,
           baseImage: Object,
           revisionImage: Object,
-          projectName: String,
           parentIndex: Number,
-          /**
-           * @type {Defs.LineOfInterest|null}
-           */
-          lineOfInterest: Object,
-
-          /**
-           * @type {function(number, booleam, !string)}
-           */
-          createCommentFn: Function,
+          path: String,
+          projectName: String,
 
           _builder: Object,
           _groups: Array,
           _layers: Array,
           _showTabs: Boolean,
+          /** @type {!Array<!Gerrit.HoveredRange>} */
+          commentRanges: {
+            type: Array,
+            value: () => [],
+          },
         },
 
         get diffElement() {
           return this.queryEffectiveChildren('#diffTable');
         },
 
+        get _commentThreadElements() {
+          return this.queryAllEffectiveChildren('.comment-thread');
+        },
+
         observers: [
           '_groupsChanged(_groups.splices)',
         ],
@@ -156,13 +146,9 @@
           }
 
           this._layers = layers;
-
-          this.async(() => {
-            this._preRenderThread();
-          });
         },
 
-        render(comments, prefs) {
+        render(keyLocations, prefs) {
           this.$.syntaxLayer.enabled = prefs.syntax_highlighting;
           this._showTabs = !!prefs.show_tabs;
           this._showTrailingWhitespace = !!prefs.show_whitespace_errors;
@@ -170,11 +156,10 @@
           // Stop the processor and syntax layer (if they're running).
           this.cancel();
 
-          this._builder = this._getDiffBuilder(this.diff, comments, prefs);
+          this._builder = this._getDiffBuilder(this.diff, prefs);
 
           this.$.processor.context = prefs.context;
-          this.$.processor.keyLocations = this._getKeyLocations(comments,
-              this.lineOfInterest);
+          this.$.processor.keyLocations = keyLocations;
 
           this._clearDiffContent();
           this._builder.addColumns(this.diffElement, prefs.font_size);
@@ -294,7 +279,7 @@
           throw Error(`Invalid preference value: ${pref}`);
         },
 
-        _getDiffBuilder(diff, comments, prefs) {
+        _getDiffBuilder(diff, prefs) {
           if (isNaN(prefs.tab_size) || prefs.tab_size <= 0) {
             this._handlePreferenceError('tab size');
             return;
@@ -306,20 +291,22 @@
           }
 
           let builder = null;
-          const createFn = this.createCommentFn;
           if (this.isImageDiff) {
-            builder = new GrDiffBuilderImage(diff, comments, createFn, prefs,
-              this.diffElement, this.baseImage, this.revisionImage);
+            builder = new GrDiffBuilderImage(diff,
+              this._commentThreadElements, prefs, this.diffElement,
+              this.baseImage, this.revisionImage);
           } else if (diff.binary) {
             // If the diff is binary, but not an image.
-            return new GrDiffBuilderBinary(diff, comments, prefs,
-                this.diffElement);
+            return new GrDiffBuilderBinary(diff,
+                this._commentThreadElements, prefs, this.diffElement);
           } else if (this.viewMode === DiffViewMode.SIDE_BY_SIDE) {
-            builder = new GrDiffBuilderSideBySide(diff, comments, createFn,
-                prefs, this.diffElement, this._layers);
+            builder = new GrDiffBuilderSideBySide(diff,
+                this._commentThreadElements, prefs, this.diffElement,
+                this._layers);
           } else if (this.viewMode === DiffViewMode.UNIFIED) {
-            builder = new GrDiffBuilderUnified(diff, comments, createFn, prefs,
-                this.diffElement, this._layers);
+            builder = new GrDiffBuilderUnified(diff,
+                this._commentThreadElements, prefs, this.diffElement,
+                this._layers);
           }
           if (!builder) {
             throw Error('Unsupported diff view mode: ' + this.viewMode);
@@ -331,33 +318,6 @@
           this.diffElement.innerHTML = null;
         },
 
-        /**
-         * @param {!Object} comments
-         * @param {Defs.LineOfInterest|null} lineOfInterest
-         */
-        _getKeyLocations(comments, lineOfInterest) {
-          const result = {
-            left: {},
-            right: {},
-          };
-          for (const side in comments) {
-            if (side !== GrDiffBuilder.Side.LEFT &&
-                side !== GrDiffBuilder.Side.RIGHT) {
-              continue;
-            }
-            for (const c of comments[side]) {
-              result[side][c.line || GrDiffLine.FILE] = true;
-            }
-          }
-
-          if (lineOfInterest) {
-            const side = lineOfInterest.leftSide ? 'left' : 'right';
-            result[side][lineOfInterest.number] = true;
-          }
-
-          return result;
-        },
-
         _groupsChanged(changeRecord) {
           if (!changeRecord) { return; }
           for (const splice of changeRecord.indexSplices) {
@@ -446,25 +406,6 @@
         },
 
         /**
-         * In pages with large diffs, creating the first comment thread can be
-         * slow because nested Polymer elements (particularly
-         * iron-autogrow-textarea) add style elements to the document head,
-         * which, in turn, triggers a reflow on the page. Create a hidden
-         * thread, attach it to the page, and remove it so the stylesheet will
-         * already exist and the user's comment will be quick to load.
-         * @see https://gerrit-review.googlesource.com/c/82213/
-         */
-        _preRenderThread() {
-          const thread = document.createElement('gr-diff-comment-thread');
-          thread.setAttribute('hidden', true);
-          thread.addDraft();
-          const parent = Polymer.dom(this.root);
-          parent.appendChild(thread);
-          Polymer.dom.flush();
-          parent.removeChild(thread);
-        },
-
-        /**
          * @return {boolean} whether any of the lines in _groups are longer
          * than SYNTAX_MAX_LINE_LENGTH.
          */
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 4b85c22..d428f68 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,6 +20,60 @@
   // 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
@@ -42,11 +96,9 @@
    */
   const REGEX_TAB_OR_SURROGATE_PAIR = /\t|[\uD800-\uDBFF][\uDC00-\uDFFF]/;
 
-  function GrDiffBuilder(diff, comments, createThreadGroupFn, prefs, outputEl,
-      layers) {
+  function GrDiffBuilder(diff, commentThreadEls, prefs,
+      outputEl, layers) {
     this._diff = diff;
-    this._comments = comments;
-    this._createThreadGroupFn = createThreadGroupFn;
     this._prefs = prefs;
     this._outputEl = outputEl;
     this.groups = [];
@@ -67,6 +119,8 @@
         layer.addListener(this._handleLayerUpdate.bind(this));
       }
     }
+
+    this._threadEls = commentThreadEls;
   }
 
   GrDiffBuilder.GroupType = {
@@ -319,148 +373,27 @@
     return button;
   };
 
-  GrDiffBuilder.prototype._getCommentsForLine = function(comments, line,
-      opt_side) {
-    function byLineNum(lineNum) {
-      return function(c) {
-        return (c.line === lineNum) ||
-               (c.line === undefined && lineNum === GrDiffLine.FILE);
-      };
-    }
-    const leftComments =
-        comments[GrDiffBuilder.Side.LEFT].filter(byLineNum(line.beforeNumber));
-    const rightComments =
-        comments[GrDiffBuilder.Side.RIGHT].filter(byLineNum(line.afterNumber));
-
-    leftComments.forEach(c => { c.__commentSide = 'left'; });
-    rightComments.forEach(c => { c.__commentSide = 'right'; });
-
-    let result;
-
-    switch (opt_side) {
-      case GrDiffBuilder.Side.LEFT:
-        result = leftComments;
-        break;
-      case GrDiffBuilder.Side.RIGHT:
-        result = rightComments;
-        break;
-      default:
-        result = leftComments.concat(rightComments);
-        break;
-    }
-
-    return result;
-  };
-
   /**
-   * @param {Array<Object>} comments
-   * @param {string} patchForNewThreads
-   */
-  GrDiffBuilder.prototype._getThreads = function(comments, patchForNewThreads) {
-    const sortedComments = comments.slice(0).sort((a, b) => {
-      if (b.__draft && !a.__draft ) { return 0; }
-      if (a.__draft && !b.__draft ) { return 1; }
-      return util.parseDate(a.updated) - util.parseDate(b.updated);
-    });
-
-    const threads = [];
-    for (const comment of sortedComments) {
-      // If the comment is in reply to another comment, find that comment's
-      // thread and append to it.
-      if (comment.in_reply_to) {
-        const thread = threads.find(thread =>
-            thread.comments.some(c => c.id === comment.in_reply_to));
-        if (thread) {
-          thread.comments.push(comment);
-          continue;
-        }
-      }
-
-      // Otherwise, this comment starts its own thread.
-      const newThread = {
-        start_datetime: comment.updated,
-        comments: [comment],
-        commentSide: comment.__commentSide,
-        /**
-         * Determines what the patchNum of a thread should be. Use patchNum from
-         * comment if it exists, otherwise the property of the thread group.
-         * This is needed for switching between side-by-side and unified views
-         * when there are unsaved drafts.
-         */
-        patchNum: comment.patch_set || patchForNewThreads,
-        rootId: comment.id || comment.__draftID,
-      };
-      if (comment.range) {
-        newThread.range = Object.assign({}, comment.range);
-      }
-      threads.push(newThread);
-    }
-    return threads;
-  };
-
-  /**
-   * Returns the patch number that new comment threads should be attached to.
-   *
-   * @param {GrDiffLine} line The line new thread will be attached to.
-   * @param {string=} opt_side Set to LEFT to force adding it to the LEFT side -
-   *     will be ignored if the left is a parent or a merge parent
-   * @return {number} Patch set to attach the new thread to
-   */
-  GrDiffBuilder.prototype._determinePatchNumForNewThreads = function(
-      patchRange, line, opt_side) {
-    if ((line.type === GrDiffLine.Type.REMOVE ||
-         opt_side === GrDiffBuilder.Side.LEFT) &&
-        patchRange.basePatchNum !== 'PARENT' &&
-        !Gerrit.PatchSetBehavior.isMergeParent(patchRange.basePatchNum)) {
-      return patchRange.basePatchNum;
-    } else {
-      return patchRange.patchNum;
-    }
-  };
-
-  /**
-   * Returns whether the comments on the given line are on a (merge) parent.
-   *
-   * @param {string} firstCommentSide
-   * @param {{basePatchNum: number, patchNum: number}} patchRange
-   * @param {GrDiffLine} line The line the comments are on.
-   * @param {string=} opt_side
-   * @return {boolean} True iff the comments on the given line are on a (merge)
-   *    parent.
-   */
-  GrDiffBuilder.prototype._determineIsOnParent = function(
-      firstCommentSide, patchRange, line, opt_side) {
-    return ((line.type === GrDiffLine.Type.REMOVE ||
-             opt_side === GrDiffBuilder.Side.LEFT) &&
-            (patchRange.basePatchNum === 'PARENT' ||
-             Gerrit.PatchSetBehavior.isMergeParent(
-                 patchRange.basePatchNum))) ||
-          firstCommentSide === 'PARENT';
-  };
-
-  /**
-   * @param {GrDiffLine} line
-   * @param {string=} opt_side
+   * @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, opt_side) {
-    const comments =
-    this._getCommentsForLine(this._comments, line, opt_side);
-    if (!comments || comments.length === 0) {
+      line, commentSide = GrDiffBuilder.Side.BOTH) {
+    const threadElsForGroup =
+        Gerrit.filterThreadElsForLocation(this._threadEls, line, commentSide);
+    if (!threadElsForGroup || threadElsForGroup.length === 0) {
       return null;
     }
 
-    const patchNum = this._determinePatchNumForNewThreads(
-        this._comments.meta.patchRange, line, opt_side);
-    const isOnParent = this._determineIsOnParent(
-        comments[0].side, this._comments.meta.patchRange, line, opt_side);
-
-    const threadGroupEl = this._createThreadGroupFn(patchNum, isOnParent,
-        opt_side);
-    threadGroupEl.threads = this._getThreads(comments, patchNum);
-    if (opt_side) {
-      threadGroupEl.setAttribute('data-side', opt_side);
+    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;
   };
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 3238cbc..c7a1140 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
@@ -57,9 +57,9 @@
 
 <script>
   suite('gr-diff-builder tests', () => {
+    let prefs;
     let element;
     let builder;
-    let createThreadGroupFn;
     let sandbox;
     const LINE_FEED_HTML = '<span class="style-scope gr-diff br"></span>';
 
@@ -70,178 +70,73 @@
         getLoggedIn() { return Promise.resolve(false); },
         getProjectConfig() { return Promise.resolve({}); },
       });
-      const prefs = {
+      prefs = {
         line_length: 10,
         show_tabs: true,
         tab_size: 4,
       };
-      createThreadGroupFn = sinon.spy(() => ({
-        setAttribute: sinon.spy(),
-      }));
-      builder = new GrDiffBuilder(
-          {content: []}, {left: [], right: []}, createThreadGroupFn, prefs);
+      builder = new GrDiffBuilder({content: []}, [], prefs);
     });
 
     teardown(() => { sandbox.restore(); });
 
-    test('_getThreads', () => {
-      const patchForNewThreads = 3;
-      const comments = [
-        {
-          id: 'sallys_confession',
-          message: 'i like you, jack',
-          updated: '2015-12-23 15:00:20.396000000',
-          __commentSide: 'left',
-        }, {
-          id: 'jacks_reply',
-          message: 'i like you, too',
-          updated: '2015-12-24 15:01:20.396000000',
-          __commentSide: 'left',
-          in_reply_to: 'sallys_confession',
-        },
-        {
-          id: 'new_draft',
-          message: 'i do not like either of you',
-          __commentSide: 'left',
-          __draft: true,
-          updated: '2015-12-20 15:01:20.396000000',
-        },
-      ];
+    test('filterThreadElsForLocation with no threads', () => {
+      const line = {beforeNumber: 3, afterNumber: 5};
 
-      let expectedThreadGroups = [
-        {
-          start_datetime: '2015-12-23 15:00:20.396000000',
-          commentSide: 'left',
-          comments: [{
-            id: 'sallys_confession',
-            message: 'i like you, jack',
-            updated: '2015-12-23 15:00:20.396000000',
-            __commentSide: 'left',
-          }, {
-            id: 'jacks_reply',
-            message: 'i like you, too',
-            updated: '2015-12-24 15:01:20.396000000',
-            __commentSide: 'left',
-            in_reply_to: 'sallys_confession',
-          }],
-          rootId: 'sallys_confession',
-          patchNum: 3,
-        },
-        {
-          start_datetime: '2015-12-20 15:01:20.396000000',
-          commentSide: 'left',
-          comments: [
-            {
-              id: 'new_draft',
-              message: 'i do not like either of you',
-              __commentSide: 'left',
-              __draft: true,
-              updated: '2015-12-20 15:01:20.396000000',
-            },
-          ],
-          rootId: 'new_draft',
-          patchNum: 3,
-        },
-      ];
-
-      assert.deepEqual(
-          builder._getThreads(comments, patchForNewThreads),
-          expectedThreadGroups);
-
-      // Patch num should get inherited from comment rather
-      comments.push({
-        id: 'betsys_confession',
-        message: 'i like you, jack',
-        updated: '2015-12-24 15:00:10.396000000',
-        range: {
-          start_line: 1,
-          start_character: 1,
-          end_line: 1,
-          end_character: 2,
-        },
-        __commentSide: 'left',
-      });
-
-      expectedThreadGroups = [
-        {
-          start_datetime: '2015-12-23 15:00:20.396000000',
-          commentSide: 'left',
-          comments: [{
-            id: 'sallys_confession',
-            message: 'i like you, jack',
-            updated: '2015-12-23 15:00:20.396000000',
-            __commentSide: 'left',
-          }, {
-            id: 'jacks_reply',
-            in_reply_to: 'sallys_confession',
-            message: 'i like you, too',
-            updated: '2015-12-24 15:01:20.396000000',
-            __commentSide: 'left',
-          }],
-          patchNum: 3,
-          rootId: 'sallys_confession',
-        },
-        {
-          start_datetime: '2015-12-24 15:00:10.396000000',
-          commentSide: 'left',
-          comments: [{
-            id: 'betsys_confession',
-            message: 'i like you, jack',
-            updated: '2015-12-24 15:00:10.396000000',
-            range: {
-              start_line: 1,
-              start_character: 1,
-              end_line: 1,
-              end_character: 2,
-            },
-            __commentSide: 'left',
-          }],
-          patchNum: 3,
-          rootId: 'betsys_confession',
-          range: {
-            start_line: 1,
-            start_character: 1,
-            end_line: 1,
-            end_character: 2,
-          },
-        },
-        {
-          start_datetime: '2015-12-20 15:01:20.396000000',
-          commentSide: 'left',
-          comments: [
-            {
-              id: 'new_draft',
-              message: 'i do not like either of you',
-              __commentSide: 'left',
-              __draft: true,
-              updated: '2015-12-20 15:01:20.396000000',
-            },
-          ],
-          rootId: 'new_draft',
-          patchNum: 3,
-        },
-      ];
-
-      assert.deepEqual(
-          builder._getThreads(comments, patchForNewThreads),
-          expectedThreadGroups);
+      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('multiple comments at same location but not threaded', () => {
-      const comments = [
-        {
-          id: 'sallys_confession',
-          message: 'i like you, jack',
-          updated: '2015-12-23 15:00:20.396000000',
-          __commentSide: 'left',
-        }, {
-          id: 'jacks_reply',
-          message: 'i like you, too',
-          updated: '2015-12-24 15:01:20.396000000',
-          __commentSide: 'left',
-        },
-      ];
-      assert.equal(builder._getThreads(comments, '3').length, 2);
+    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', () => {
@@ -417,135 +312,77 @@
       }
     });
 
-    test('comments', () => {
-      const line = new GrDiffLine(GrDiffLine.Type.BOTH);
-      line.beforeNumber = 3;
-      line.afterNumber = 5;
-
-      let comments = {left: [], right: []};
-      assert.deepEqual(builder._getCommentsForLine(comments, line), []);
-      assert.deepEqual(builder._getCommentsForLine(comments, line,
-          GrDiffBuilder.Side.LEFT), []);
-      assert.deepEqual(builder._getCommentsForLine(comments, line,
-          GrDiffBuilder.Side.RIGHT), []);
-
-      comments = {
-        left: [
-          {id: 'l3', line: 3},
-          {id: 'l5', line: 5},
-        ],
-        right: [
-          {id: 'r3', line: 3},
-          {id: 'r5', line: 5},
-        ],
-      };
-      assert.deepEqual(builder._getCommentsForLine(comments, line),
-          [{id: 'l3', line: 3, __commentSide: 'left'},
-          {id: 'r5', line: 5, __commentSide: 'right'}]);
-      assert.deepEqual(builder._getCommentsForLine(comments, line,
-          GrDiffBuilder.Side.LEFT), [{id: 'l3', line: 3,
-            __commentSide: 'left'}]);
-      assert.deepEqual(builder._getCommentsForLine(comments, line,
-          GrDiffBuilder.Side.RIGHT), [{id: 'r5', line: 5,
-            __commentSide: 'right'}]);
-    });
-
     test('comment thread group creation', () => {
-      const l3 = {id: 'l3', line: 3, updated: '2016-08-09 00:42:32.000000000',
-        __commentSide: 'left'};
-      const l5 = {id: 'l5', line: 5, updated: '2016-08-09 00:42:32.000000000',
-        __commentSide: 'left'};
-      const r5 = {id: 'r5', line: 5, updated: '2016-08-09 00:42:32.000000000',
-        __commentSide: 'right'};
+      const l3 = document.createElement('div');
+      l3.className = 'comment-thread';
+      l3.setAttribute('comment-side', 'left');
+      l3.setAttribute('line-num', 3);
 
-      builder._comments = {
-        meta: {
-          changeNum: '42',
-          patchRange: {
-            basePatchNum: 'PARENT',
-            patchNum: '3',
-          },
-          path: '/path/to/foo',
-          projectConfig: {foo: 'bar'},
-        },
-        left: [l3, l5],
-        right: [r5],
-      };
+      const l5 = document.createElement('div');
+      l5.className = 'comment-thread';
+      l5.setAttribute('comment-side', 'left');
+      l5.setAttribute('line-num', 5);
 
-      function threadForComment(c, patchNum) {
-        return {
-          commentSide: c.__commentSide,
-          comments: [c],
-          patchNum,
-          rootId: c.id,
-          start_datetime: c.updated,
-        };
-      }
+      const r5 = document.createElement('div');
+      r5.className = 'comment-thread';
+      r5.setAttribute('comment-side', 'right');
+      r5.setAttribute('line-num', 5);
 
-      function checkThreadGroupProps(threadGroupEl, patchNum, isOnParent,
-          comments) {
-        assert.equal(createThreadGroupFn.lastCall.args[0], patchNum);
-        assert.equal(createThreadGroupFn.lastCall.args[1], isOnParent);
-        assert.deepEqual(
-            threadGroupEl.threads,
-            comments.map(c => threadForComment(c, patchNum)));
+      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);
-      assert.isTrue(createThreadGroupFn.calledOnce);
-      checkThreadGroupProps(threadGroupEl, '3', false, [l5, r5]);
+      checkThreadGroupProps(threadGroupEl, [l5, r5]);
 
       threadGroupEl =
           builder._commentThreadGroupForLine(line, GrDiffBuilder.Side.RIGHT);
-      assert.isTrue(createThreadGroupFn.calledTwice);
-      checkThreadGroupProps(threadGroupEl, '3', false, [r5]);
+      checkThreadGroupProps(threadGroupEl, [r5]);
 
       threadGroupEl =
           builder._commentThreadGroupForLine(line, GrDiffBuilder.Side.LEFT);
-      assert.isTrue(createThreadGroupFn.calledThrice);
-      checkThreadGroupProps(threadGroupEl, '3', true, [l5]);
-
-      builder._comments.meta.patchRange.basePatchNum = '1';
+      checkThreadGroupProps(threadGroupEl, [l5]);
 
       threadGroupEl = builder._commentThreadGroupForLine(line);
-      assert.equal(createThreadGroupFn.callCount, 4);
-      checkThreadGroupProps(threadGroupEl, '3', false, [l5, r5]);
+      checkThreadGroupProps(threadGroupEl, [l5, r5]);
 
       threadEl =
           builder._commentThreadGroupForLine(line, GrDiffBuilder.Side.LEFT);
-      assert.equal(createThreadGroupFn.callCount, 5);
-      checkThreadGroupProps(threadEl, '1', false, [l5]);
+      checkThreadGroupProps(threadEl, [l5]);
 
       threadGroupEl =
           builder._commentThreadGroupForLine(line, GrDiffBuilder.Side.RIGHT);
-      assert.equal(createThreadGroupFn.callCount, 6);
-      checkThreadGroupProps(threadGroupEl, '3', false, [r5]);
-
-      builder._comments.meta.patchRange.basePatchNum = 'PARENT';
+      checkThreadGroupProps(threadGroupEl, [r5]);
 
       line = new GrDiffLine(GrDiffLine.Type.REMOVE);
       line.beforeNumber = 5;
       line.afterNumber = 5;
       threadGroupEl = builder._commentThreadGroupForLine(line);
-      assert.equal(createThreadGroupFn.callCount, 7);
-      checkThreadGroupProps(threadGroupEl, '3', true, [l5, r5]);
+      checkThreadGroupProps(threadGroupEl, [l5, r5]);
 
       line = new GrDiffLine(GrDiffLine.Type.ADD);
       line.beforeNumber = 3;
       line.afterNumber = 5;
       threadGroupEl = builder._commentThreadGroupForLine(line);
-      assert.equal(createThreadGroupFn.callCount, 8);
-      checkThreadGroupProps(threadGroupEl, '3', false, [l3, r5]);
+      checkThreadGroupProps(threadGroupEl, [l3, r5]);
     });
 
 
     test('_handlePreferenceError called with invalid preference', () => {
       sandbox.stub(element, '_handlePreferenceError');
       const prefs = {tab_size: 0};
-      element._getDiffBuilder(element.diff, element.comments, prefs);
+      element._getDiffBuilder(element.diff, prefs);
       assert.isTrue(element._handlePreferenceError.lastCall
           .calledWithExactly('tab size'));
     });
@@ -559,31 +396,6 @@
         `Fix in diff preferences`);
     });
 
-    test('_getKeyLocations', () => {
-      assert.deepEqual(element._getKeyLocations({left: [], right: []}, null),
-          {left: {}, right: {}});
-      const comments = {
-        left: [{line: 123}, {}],
-        right: [{line: 456}],
-      };
-      assert.deepEqual(element._getKeyLocations(comments, null), {
-        left: {FILE: true, 123: true},
-        right: {456: true},
-      });
-
-      const lineOfInterest = {number: 789, leftSide: true};
-      assert.deepEqual(element._getKeyLocations(comments, lineOfInterest), {
-        left: {FILE: true, 123: true, 789: true},
-        right: {456: true},
-      });
-
-      delete lineOfInterest.leftSide;
-      assert.deepEqual(element._getKeyLocations(comments, lineOfInterest), {
-        left: {FILE: true, 123: true},
-        right: {456: true, 789: true},
-      });
-    });
-
     suite('_isTotal', () => {
       test('is total for add', () => {
         const group = new GrDiffGroup(GrDiffGroup.Type.DELTA);
@@ -1013,7 +825,7 @@
 
     suite('rendering text, images and binary files', () => {
       let processStub;
-      let comments;
+      let keyLocations;
       let prefs;
       let content;
 
@@ -1023,7 +835,7 @@
         processStub = sandbox.stub(element.$.processor, 'process')
             .returns(Promise.resolve());
         sandbox.stub(element, '_anyLineTooLong').returns(true);
-        comments = {left: [], right: []};
+        keyLocations = {left: {}, right: {}};
         prefs = {
           line_length: 10,
           show_tabs: true,
@@ -1044,7 +856,7 @@
 
       test('text', () => {
         element.diff = {content};
-        return element.render(comments, prefs).then(() => {
+        return element.render(keyLocations, prefs).then(() => {
           assert.isTrue(processStub.calledOnce);
           assert.isFalse(processStub.lastCall.args[1]);
         });
@@ -1053,7 +865,7 @@
       test('image', () => {
         element.diff = {content, binary: true};
         element.isImageDiff = true;
-        return element.render(comments, prefs).then(() => {
+        return element.render(keyLocations, prefs).then(() => {
           assert.isTrue(processStub.calledOnce);
           assert.isTrue(processStub.lastCall.args[1]);
         });
@@ -1061,7 +873,7 @@
 
       test('binary', () => {
         element.diff = {content, binary: true};
-        return element.render(comments, prefs).then(() => {
+        return element.render(keyLocations, prefs).then(() => {
           assert.isTrue(processStub.calledOnce);
           assert.isTrue(processStub.lastCall.args[1]);
         });
@@ -1071,6 +883,7 @@
     suite('rendering', () => {
       let content;
       let outputEl;
+      let keyLocations;
 
       setup(done => {
         const prefs = {
@@ -1098,9 +911,9 @@
         });
         element = fixture('basic');
         outputEl = element.queryEffectiveChildren('#diffTable');
+        keyLocations = {left: {}, right: {}};
         sandbox.stub(element, '_getDiffBuilder', () => {
-          const builder = new GrDiffBuilder(
-              {content}, {left: [], right: []}, null, prefs, outputEl);
+          const builder = new GrDiffBuilder({content}, [], prefs, outputEl);
           sandbox.stub(builder, 'addColumns');
           builder.buildSectionElement = function(group) {
             const section = document.createElement('stub');
@@ -1112,7 +925,7 @@
           return builder;
         });
         element.diff = {content};
-        element.render({left: [], right: []}, prefs).then(done);
+        element.render(keyLocations, prefs).then(done);
       });
 
       test('reporting', done => {
@@ -1137,7 +950,7 @@
       });
 
       test('addColumns is called', done => {
-        element.render({left: [], right: []}, {}).then(done);
+        element.render(keyLocations, {}).then(done);
         assert.isTrue(element._builder.addColumns.called);
       });
 
@@ -1161,7 +974,7 @@
 
       test('render-start and render are fired', done => {
         const dispatchEventStub = sandbox.stub(element, 'dispatchEvent');
-        element.render({left: [], right: []}, {}).then(() => {
+        element.render(keyLocations, {}).then(() => {
           const firedEventTypes = dispatchEventStub.getCalls()
               .map(c => { return c.args[0].type; });
           assert.include(firedEventTypes, 'render-start');
@@ -1189,7 +1002,7 @@
           context: -1,
           syntax_highlighting: true,
         };
-        element.render({left: [], right: []}, prefs);
+        element.render(keyLocations, prefs);
       });
 
       test('cancel', () => {
@@ -1206,6 +1019,7 @@
       let builder;
       let diff;
       let prefs;
+      let keyLocations;
 
       setup(done => {
         element = fixture('mock-diff');
@@ -1217,8 +1031,9 @@
           show_tabs: true,
           tab_size: 4,
         };
+        keyLocations = {left: {}, right: {}};
 
-        element.render({left: [], right: []}, prefs).then(() => {
+        element.render(keyLocations, prefs).then(() => {
           builder = element._builder;
           done();
         });
@@ -1328,7 +1143,7 @@
       test('_getNextContentOnSide unified left', done => {
         // Re-render as unified:
         element.viewMode = 'UNIFIED_DIFF';
-        element.render({left: [], right: []}, prefs).then(() => {
+        element.render(keyLocations, prefs).then(() => {
           builder = element._builder;
 
           const startElem = builder.getContentByLine(5, 'left',
@@ -1348,7 +1163,7 @@
       test('_getNextContentOnSide unified right', done => {
         // Re-render as unified:
         element.viewMode = 'UNIFIED_DIFF';
-        element.render({left: [], right: []}, prefs).then(() => {
+        element.render(keyLocations, prefs).then(() => {
           builder = element._builder;
 
           const startElem = builder.getContentByLine(5, 'right',
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-comment-thread-group/gr-diff-comment-thread-group.html b/polygerrit-ui/app/elements/diff/gr-diff-comment-thread-group/gr-diff-comment-thread-group.html
deleted file mode 100644
index 58b7c32..0000000
--- a/polygerrit-ui/app/elements/diff/gr-diff-comment-thread-group/gr-diff-comment-thread-group.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<link rel="import" href="../../../bower_components/polymer/polymer.html">
-<link rel="import" href="../gr-diff-comment-thread/gr-diff-comment-thread.html">
-<link rel="import" href="../../../styles/shared-styles.html">
-
-<dom-module id="gr-diff-comment-thread-group">
-  <template>
-    <style include="shared-styles">
-      :host {
-        display: block;
-        max-width: var(--content-width, 80ch);
-        white-space: normal;
-      }
-      gr-diff-comment-thread + gr-diff-comment-thread {
-        margin-top: .2em;
-      }
-    </style>
-    <template is="dom-repeat" items="[[threads]]" as="thread">
-      <gr-diff-comment-thread
-          comments="[[thread.comments]]"
-          comment-side="[[thread.commentSide]]"
-          is-on-parent="[[isOnParent]]"
-          parent-index="[[parentIndex]]"
-          change-num="[[changeNum]]"
-          patch-num="[[thread.patchNum]]"
-          root-id="{{thread.rootId}}"
-          path="[[path]]"
-          project-name="[[projectName]]"
-          range="[[thread.range]]"
-          on-thread-discard="_handleThreadDiscard"></gr-diff-comment-thread>
-    </template>
-  </template>
-  <script src="gr-diff-comment-thread-group.js"></script>
-</dom-module>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-comment-thread-group/gr-diff-comment-thread-group.js b/polygerrit-ui/app/elements/diff/gr-diff-comment-thread-group/gr-diff-comment-thread-group.js
deleted file mode 100644
index ae45c93..0000000
--- a/polygerrit-ui/app/elements/diff/gr-diff-comment-thread-group/gr-diff-comment-thread-group.js
+++ /dev/null
@@ -1,133 +0,0 @@
-/**
- * @license
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-(function() {
-  'use strict';
-
-  Polymer({
-    is: 'gr-diff-comment-thread-group',
-
-    properties: {
-      changeNum: String,
-      projectName: String,
-      patchForNewThreads: String,
-      range: Object,
-      isOnParent: {
-        type: Boolean,
-        value: false,
-      },
-      parentIndex: {
-        type: Number,
-        value: null,
-      },
-      threads: {
-        type: Array,
-        value() { return []; },
-      },
-    },
-
-    get threadEls() {
-      return Polymer.dom(this.root).querySelectorAll('gr-diff-comment-thread');
-    },
-
-    /**
-     * Adds a new thread. Range is optional because a comment can be
-     * added to a line without a range selected.
-     *
-     * @param {!Object} opt_range
-     */
-    addNewThread(commentSide, opt_range) {
-      this.push('threads', {
-        comments: [],
-        commentSide,
-        patchNum: this.patchForNewThreads,
-        range: opt_range,
-      });
-    },
-
-    removeThread(rootId) {
-      for (let i = 0; i < this.threads.length; i++) {
-        if (this.threads[i].rootId === rootId) {
-          this.splice('threads', i, 1);
-          return;
-        }
-      }
-    },
-
-    /**
-     * Fetch the thread group at the given range, or the range-less thread
-     * on the line if no range is provided, lineNum, and side.
-     *
-     * @param {string} side
-     * @param {!Object=} opt_range
-     * @return {!Object|undefined}
-     */
-    getThread(side, opt_range) {
-      const threads = [].filter.call(this.threadEls,
-          thread => this._rangesEqual(thread.range, opt_range))
-          .filter(thread => thread.commentSide === side);
-      if (threads.length === 1) {
-        return threads[0];
-      }
-    },
-
-    _handleThreadDiscard(e) {
-      this.removeThread(e.detail.rootId);
-    },
-
-    /**
-     * Compare two ranges. Either argument may be falsy, but will only return
-     * true if both are falsy or if neither are falsy and have the same position
-     * values.
-     *
-     * @param {Object=} a range 1
-     * @param {Object=} b range 2
-     * @return {boolean}
-     */
-    _rangesEqual(a, b) {
-      if (!a && !b) { return true; }
-      if (!a || !b) { return false; }
-      return a.startLine === b.startLine &&
-          a.startChar === b.startChar &&
-          a.endLine === b.endLine &&
-          a.endChar === b.endChar;
-    },
-
-    _sortByDate(threadGroups) {
-      if (!threadGroups.length) { return; }
-      return threadGroups.sort((a, b) => {
-        // If a comment is a draft, it doesn't have a start_datetime yet.
-        // Assume it is newer than the comment it is being compared to.
-        if (!a.start_datetime) {
-          return 1;
-        }
-        if (!b.start_datetime) {
-          return -1;
-        }
-        return util.parseDate(a.start_datetime) -
-            util.parseDate(b.start_datetime);
-      });
-    },
-
-    _calculateLocationRange(range, comment) {
-      return 'range-' + range.start_line + '-' +
-          range.start_character + '-' +
-          range.end_line + '-' +
-          range.end_character + '-' +
-          comment.__commentSide;
-    },
-  });
-})();
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-comment-thread-group/gr-diff-comment-thread-group_test.html b/polygerrit-ui/app/elements/diff/gr-diff-comment-thread-group/gr-diff-comment-thread-group_test.html
deleted file mode 100644
index 1fb8136..0000000
--- a/polygerrit-ui/app/elements/diff/gr-diff-comment-thread-group/gr-diff-comment-thread-group_test.html
+++ /dev/null
@@ -1,232 +0,0 @@
-<!DOCTYPE html>
-<!--
-@license
-Copyright (C) 2017 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<title>gr-diff-comment-thread-group</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-group.html">
-
-<script>void(0);</script>
-
-<test-fixture id="basic">
-  <template>
-    <gr-diff-comment-thread-group></gr-diff-comment-thread-group>
-  </template>
-</test-fixture>
-
-<script>
-  suite('gr-diff-comment-thread-group tests', () => {
-    let element;
-    let sandbox;
-
-    setup(() => {
-      sandbox = sinon.sandbox.create();
-      stub('gr-rest-api-interface', {
-        getLoggedIn() { return Promise.resolve(false); },
-      });
-      element = fixture('basic');
-    });
-
-    teardown(() => {
-      sandbox.restore();
-    });
-
-    test('getThread', () => {
-      const range = {
-        start_line: 1,
-        start_character: 1,
-        end_line: 1,
-        end_character: 2,
-      };
-      element.threads = [
-        {
-          rootId: 'sallys_confession',
-          commentSide: 'left',
-          comments: [
-            {
-              id: 'sallys_confession',
-              message: 'i like you, jack',
-              updated: '2015-12-23 15:00:20.396000000',
-              __commentSide: 'left',
-            }, {
-              id: 'jacks_reply',
-              message: 'i like you, too',
-              updated: '2015-12-24 15:01:20.396000000',
-              __commentSide: 'left',
-              in_reply_to: 'sallys_confession',
-            }, {
-              id: 'new_draft',
-              message: 'i do not like either of you',
-              __commentSide: 'left',
-              __draft: true,
-              in_reply_to: 'sallys_confession',
-              updated: '2015-12-20 15:01:20.396000000',
-            },
-          ],
-        },
-        {
-          rootId: 'right_side_comment',
-          commentSide: 'right',
-          comments: [
-            {
-              id: 'right_side_comment',
-              message: 'right side comment',
-              __commentSide: 'right',
-              __draft: true,
-              updated: '2015-12-20 15:01:20.396000000',
-            },
-          ],
-        }, {
-          rootId: 'betsys_confession',
-          commentSide: 'left',
-          range,
-          comments: [
-            {
-              id: 'betsys_confession',
-              message: 'i like you more, jack',
-              updated: '2015-12-24 15:00:10.396000000',
-              range,
-              __commentSide: 'left',
-            },
-          ],
-        },
-      ];
-
-      flushAsynchronousOperations();
-      assert.deepEqual(element.getThread('right').rootId, 'right_side_comment');
-      assert.deepEqual(element.getThread('right').comments.length, 1);
-      assert.deepEqual(element.getThread('left').rootId, 'sallys_confession');
-      assert.deepEqual(element.getThread('left').comments.length, 3);
-      assert.deepEqual(element.getThread('left', range).rootId,
-          'betsys_confession');
-      assert.deepEqual(element.getThread('left', range).comments.length, 1);
-    });
-
-    test('_sortByDate', () => {
-      let threadGroups = [
-        {
-          start_datetime: '2015-12-23 15:00:20.396000000',
-          comments: [],
-          locationRange: 'line',
-        },
-        {
-          start_datetime: '2015-12-22 15:00:10.396000000',
-          comments: [],
-          locationRange: 'range-1-1-1-2',
-        },
-      ];
-
-      let expectedResult = [
-        {
-          start_datetime: '2015-12-22 15:00:10.396000000',
-          comments: [],
-          locationRange: 'range-1-1-1-2',
-        }, {
-          start_datetime: '2015-12-23 15:00:20.396000000',
-          comments: [],
-          locationRange: 'line',
-        },
-      ];
-
-      assert.deepEqual(element._sortByDate(threadGroups), expectedResult);
-
-      // When a comment doesn't have a date, the one without the date should be
-      // last.
-      threadGroups = [
-        {
-          start_datetime: '2015-12-23 15:00:20.396000000',
-          comments: [],
-          locationRange: 'line',
-        },
-        {
-          comments: [],
-          locationRange: 'range-1-1-1-2',
-        },
-      ];
-
-      expectedResult = [
-        {
-          start_datetime: '2015-12-23 15:00:20.396000000',
-          comments: [],
-          locationRange: 'line',
-        },
-        {
-          comments: [],
-          locationRange: 'range-1-1-1-2',
-        },
-      ];
-
-      assert.deepEqual(element._sortByDate(threadGroups), expectedResult);
-    });
-
-    test('_calculateLocationRange', () => {
-      const comment = {__commentSide: 'left'};
-      const range = {
-        start_line: 1,
-        start_character: 2,
-        end_line: 3,
-        end_character: 4,
-      };
-      assert.equal(
-          element._calculateLocationRange(range, comment),
-          'range-1-2-3-4-left');
-    });
-
-    test('addNewThread', () => {
-      const locationRange = 'range-1-2-3-4';
-      element._threads = [{locationRange: 'line'}];
-      element.addNewThread(locationRange);
-      assert(element._threads.length, 2);
-    });
-
-    test('removeThread', () => {
-      const locationRange = 'range-1-2-3-4';
-      element._threads = [
-        {locationRange: 'range-1-2-3-4', comments: []},
-        {locationRange: 'line', comments: []},
-      ];
-      flushAsynchronousOperations();
-      element.removeThread(locationRange);
-      flushAsynchronousOperations();
-      assert(element._threads.length, 1);
-    });
-
-    test('_rangesEqual', () => {
-      const range1 =
-          {startLine: 123, startChar: 345, endLine: 234, endChar: 456};
-      const range2 =
-          {startLine: 1, startChar: 2, endLine: 3, endChar: 4};
-
-      assert.isTrue(element._rangesEqual(null, null));
-      assert.isTrue(element._rangesEqual(null, undefined));
-      assert.isTrue(element._rangesEqual(undefined, null));
-      assert.isTrue(element._rangesEqual(undefined, undefined));
-
-      assert.isFalse(element._rangesEqual(range1, null));
-      assert.isFalse(element._rangesEqual(null, range1));
-      assert.isFalse(element._rangesEqual(range1, range2));
-
-      assert.isTrue(element._rangesEqual(range1, Object.assign({}, range1)));
-    });
-  });
-</script>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-comment-thread/gr-diff-comment-thread.js b/polygerrit-ui/app/elements/diff/gr-diff-comment-thread/gr-diff-comment-thread.js
index d5e6855..a2439d7 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-comment-thread/gr-diff-comment-thread.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-comment-thread/gr-diff-comment-thread.js
@@ -35,18 +35,48 @@
      * @event thread-changed
      */
 
+     /**
+      * gr-diff-comment-thread exposes the following attributes that allow a
+      * diff widget like gr-diff to show the thread in the right location:
+      *
+      * line-num:
+      *     1-based line number or undefined if it refers to the entire file.
+      *
+      * comment-side:
+      *     "left" or "right". These indicate which of the two diffed versions
+      *     the comment relates to. In the case of unified diff, the left
+      *     version is the one whose line number column is further to the left.
+      *
+      * range:
+      *     The range of text that the comment refers to (start_line,
+      *     start_character, end_line, end_character), serialized as JSON. If
+      *     set, range's end_line will have the same value as line-num. Line
+      *     numbers are 1-based, char numbers are 0-based. The start position
+      *     (start_line, start_character) is inclusive, and the end position
+      *     (end_line, end_character) is exclusive.
+      */
     properties: {
       changeNum: String,
       comments: {
         type: Array,
         value() { return []; },
       },
-      range: Object,
+      /**
+       * @type {?{start_line: number, start_character: number, end_line: number,
+       *          end_character: number}}
+       */
+      range: {
+        type: Object,
+        reflectToAttribute: true,
+      },
       keyEventTarget: {
         type: Object,
         value() { return document.body; },
       },
-      commentSide: String,
+      commentSide: {
+        type: String,
+        reflectToAttribute: true,
+      },
       patchNum: String,
       path: String,
       projectName: {
@@ -79,8 +109,11 @@
         type: Boolean,
         value: false,
       },
-      /** Necessary only if showFilePath is true */
-      lineNum: Number,
+      /** Necessary only if showFilePath is true or when used with gr-diff */
+      lineNum: {
+        type: Number,
+        reflectToAttribute: true,
+      },
       unresolved: {
         type: Boolean,
         notify: true,
@@ -231,7 +264,7 @@
         // Ensure drafts are at the end. There should only be one but in edge
         // cases could be more. In the unlikely event two drafts are being
         // compared, use the typical date compare.
-        if (c2.__draft && !c1.__draft ) { return 0; }
+        if (c2.__draft && !c1.__draft ) { return -1; }
         if (c1.__draft && !c2.__draft ) { return 1; }
         if (dateCompare === 0 && (!c1.id || !c1.id.localeCompare)) { return 0; }
         // If same date, fall back to sorting by id.
@@ -358,12 +391,7 @@
         d.line = opt_lineNum;
       }
       if (opt_range) {
-        d.range = {
-          start_line: opt_range.startLine,
-          start_character: opt_range.startChar,
-          end_line: opt_range.endLine,
-          end_character: opt_range.endChar,
-        };
+        d.range = opt_range;
       }
       if (this.parentIndex) {
         d.parent = this.parentIndex;
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-comment-thread/gr-diff-comment-thread_test.html b/polygerrit-ui/app/elements/diff/gr-diff-comment-thread/gr-diff-comment-thread_test.html
index b525a60..1881497 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-comment-thread/gr-diff-comment-thread_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-comment-thread/gr-diff-comment-thread_test.html
@@ -714,5 +714,38 @@
       assert.equal(element._orderedComments[1].id, '2');
       assert.equal(element._orderedComments[2].id, '3');
     });
+
+    test('reflects lineNum and commentSide to attributes', () => {
+      element.lineNum = 7;
+      element.commentSide = 'left';
+
+      assert.equal(element.getAttribute('line-num'), '7');
+      assert.equal(element.getAttribute('comment-side'), 'left');
+    });
+
+    test('reflects range to JSON serialized attribute if set', () => {
+      element.range = {
+        start_line: 4,
+        end_line: 5,
+        start_character: 6,
+        end_character: 7,
+      };
+
+      assert.deepEqual(
+          JSON.parse(element.getAttribute('range')),
+          {start_line: 4, end_line: 5, start_character: 6, end_character: 7});
+    });
+
+    test('removes range attribute if range is unset', () => {
+      element.range = {
+        start_line: 4,
+        end_line: 5,
+        start_character: 6,
+        end_character: 7,
+      };
+      element.range = undefined;
+
+      assert.notOk(element.hasAttribute('range'));
+    });
   });
 </script>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.html b/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.html
index 6ea0330..72c7285 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.html
@@ -91,10 +91,12 @@
         text-align: right;
         white-space: nowrap;
       }
-      a.date:link,
-      a.date:visited {
+      span.date {
         color: var(--deemphasized-text-color);
       }
+      span.date:hover {
+        text-decoration: underline;
+      }
       .actions {
         display: flex;
         justify-content: flex-end;
@@ -255,11 +257,11 @@
             on-tap="_handleCommentDelete">
           (Delete)
         </gr-button>
-        <a class="date" href$="[[_computeLinkToComment(comment)]]" on-tap="_handleLinkTap">
+        <span class="date" on-tap="_handleAnchorTap">
           <gr-date-formatter
               has-tooltip
               date-str="[[comment.updated]]"></gr-date-formatter>
-        </a>
+        </span>
         <div class="show-hide">
           <label class="show-hide">
             <input type="checkbox" class="show-hide"
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.js b/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.js
index 90d465f..5165db0 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.js
@@ -29,6 +29,8 @@
   const REPORT_UPDATE_DRAFT = 'UpdateDraftComment';
   const REPORT_DISCARD_DRAFT = 'DiscardDraftComment';
 
+  const FILE = 'FILE';
+
   Polymer({
     is: 'gr-diff-comment',
 
@@ -64,6 +66,12 @@
      * @event comment-mouse-out
      */
 
+    /**
+     * Fired when the comment's timestamp is tapped.
+     *
+     * @event comment-anchor-tap
+     */
+
     properties: {
       changeNum: String,
       /** @type {?} */
@@ -333,10 +341,6 @@
       }
     },
 
-    _computeLinkToComment(comment) {
-      return '#' + comment.line;
-    },
-
     _computeDeleteButtonClass(isAdmin, draft) {
       return isAdmin && !draft ? 'showDeleteButtons' : '';
     },
@@ -401,15 +405,16 @@
       }, STORAGE_DEBOUNCE_INTERVAL);
     },
 
-    _handleLinkTap(e) {
+    _handleAnchorTap(e) {
       e.preventDefault();
-      const hash = this._computeLinkToComment(this.comment);
-      // Don't add the hash to the window history if it's already there.
-      // Otherwise you mess up expected back button behavior.
-      if (window.location.hash == hash) { return; }
-      // Change the URL but don’t trigger a nav event. Otherwise it will
-      // reload the page.
-      page.show(window.location.pathname + hash, null, false);
+      if (!this.comment.line) { return; }
+      this.dispatchEvent(new CustomEvent('comment-anchor-tap', {
+        bubbles: true,
+        detail: {
+          number: this.comment.line || FILE,
+          side: this.side,
+        },
+      }));
     },
 
     _handleEdit(e) {
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment_test.html b/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment_test.html
index ca85892..912e615 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment_test.html
@@ -99,15 +99,17 @@
           'header middle content is not visible');
     });
 
-    test('clicking on date link does not trigger nav', () => {
-      const showStub = sinon.stub(page, 'show');
+    test('clicking on date link fires event', () => {
+      element.side = 'PARENT';
+      const stub = sinon.stub();
+      element.addEventListener('comment-anchor-tap', stub);
       const dateEl = element.$$('.date');
       assert.ok(dateEl);
       MockInteractions.tap(dateEl);
-      const dest = window.location.pathname + '#5';
-      assert(showStub.lastCall.calledWithExactly(dest, null, false),
-          'Should navigate to ' + dest + ' without triggering nav');
-      showStub.restore();
+
+      assert.isTrue(stub.called);
+      assert.deepEqual(stub.lastCall.args[0].detail,
+          {side: element.side, number: element.comment.line});
     });
 
     test('message is not retrieved from storage when other edits', done => {
@@ -733,17 +735,6 @@
       assert.isTrue(saveStub.calledOnce);
     });
 
-    test('clicking on date link does not trigger nav', () => {
-      const showStub = sinon.stub(page, 'show');
-      const dateEl = element.$$('.date');
-      assert.ok(dateEl);
-      MockInteractions.tap(dateEl);
-      const dest = window.location.pathname + '#5';
-      assert(showStub.lastCall.calledWithExactly(dest, null, false),
-          'Should navigate to ' + dest + ' without triggering nav');
-      showStub.restore();
-    });
-
     test('proper event fires on resolve, comment is not saved', done => {
       const save = sandbox.stub(element, 'save');
       element.addEventListener('comment-update', e => {
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor_test.html b/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor_test.html
index 9668a54..f111378 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor_test.html
@@ -60,7 +60,11 @@
 
       diffElement.loggedIn = false;
       diffElement.patchRange = {basePatchNum: 1, patchNum: 2};
-      diffElement.comments = {left: [], right: []};
+      diffElement.comments = {
+        left: [],
+        right: [],
+        meta: {patchRange: undefined},
+      };
       const setupDone = () => {
         cursorElement._updateStops();
         cursorElement.moveToFirstChunk();
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 af8725e..85ba202 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
@@ -21,7 +21,11 @@
     is: 'gr-diff-highlight',
 
     properties: {
-      comments: Object,
+      /** @type {!Array<!Gerrit.HoveredRange>} */
+      commentRanges: {
+        type: Array,
+        notify: true,
+      },
       loggedIn: Boolean,
       /**
        * querySelector can return null, so needs to be nullable.
@@ -35,7 +39,7 @@
     listeners: {
       'comment-mouse-out': '_handleCommentMouseOut',
       'comment-mouse-over': '_handleCommentMouseOver',
-      'create-comment': '_createComment',
+      'create-range-comment': '_createRangeComment',
     },
 
     observers: [
@@ -71,35 +75,44 @@
     },
 
     _handleCommentMouseOver(e) {
-      const comment = e.detail.comment;
-      if (!comment.range) { return; }
-      const lineEl = this.diffBuilder.getLineElByChild(e.target);
-      const side = this.diffBuilder.getSideByLineEl(lineEl);
-      const index = this._indexOfComment(side, comment);
+      const threadEl = Polymer.dom(e).localTarget;
+      const index = this._indexForThreadEl(threadEl);
+
       if (index !== undefined) {
-        this.set(['comments', side, index, '__hovering'], true);
+        this.set(['commentRanges', index, 'hovering'], true);
       }
     },
 
     _handleCommentMouseOut(e) {
-      const comment = e.detail.comment;
-      if (!comment.range) { return; }
-      const lineEl = this.diffBuilder.getLineElByChild(e.target);
-      const side = this.diffBuilder.getSideByLineEl(lineEl);
-      const index = this._indexOfComment(side, comment);
+      const threadEl = Polymer.dom(e).localTarget;
+      const index = this._indexForThreadEl(threadEl);
+
       if (index !== undefined) {
-        this.set(['comments', side, index, '__hovering'], false);
+        this.set(['commentRanges', index, 'hovering'], false);
       }
     },
 
-    _indexOfComment(side, comment) {
-      const idProp = comment.id ? 'id' : '__draftID';
-      for (let i = 0; i < this.comments[side].length; i++) {
-        if (comment[idProp] &&
-            this.comments[side][i][idProp] === comment[idProp]) {
-          return i;
-        }
+    _indexForThreadEl(threadEl) {
+      const side = threadEl.getAttribute('comment-side');
+      const range = JSON.parse(threadEl.getAttribute('range'));
+
+      if (!range) return undefined;
+
+      return this._indexOfCommentRange(side, range);
+    },
+
+    _indexOfCommentRange(side, range) {
+      function rangesEqual(a, b) {
+        if (!a && !b) { return true; }
+        if (!a || !b) { return false; }
+        return a.start_line === b.start_line &&
+            a.start_character === b.start_character &&
+            a.end_line === b.end_line &&
+            a.end_character === b.end_character;
       }
+
+      return this.commentRanges.findIndex(commentRange =>
+          commentRange.side === side && rangesEqual(commentRange.range, range));
     },
 
     /**
@@ -295,10 +308,10 @@
       const root = Polymer.dom(this.root);
       root.insertBefore(actionBox, root.firstElementChild);
       actionBox.range = {
-        startLine: start.line,
-        startChar: start.column,
-        endLine: end.line,
-        endChar: end.column,
+        start_line: start.line,
+        start_character: start.column,
+        end_line: end.line,
+        end_character: end.column,
       };
       actionBox.side = start.side;
       if (start.line === end.line) {
@@ -317,7 +330,7 @@
       }
     },
 
-    _createComment(e) {
+    _createRangeComment(e) {
       this._removeActionBox();
     },
 
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 b10e3cc..23de407 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
@@ -205,7 +205,7 @@
 
       test('comment-mouse-over from ranged comment causes set', () => {
         sandbox.stub(element, 'set');
-        sandbox.stub(element, '_indexOfComment').returns(0);
+        sandbox.stub(element, '_indexForThreadEl').returns(0);
         element.fire('comment-mouse-over', {comment: {range: {}}});
         assert.isTrue(element.set.called);
       });
@@ -215,9 +215,9 @@
         assert.isFalse(builder.getContentsByLineRange.called);
       });
 
-      test('on create-comment action box is removed', () => {
+      test('on create-range-comment action box is removed', () => {
         sandbox.stub(element, '_removeActionBox');
-        element.fire('create-comment', {
+        element.fire('create-range-comment', {
           comment: {
             range: {},
           },
@@ -318,10 +318,10 @@
         const actionBox = element.$$('gr-selection-action-box');
         assert.isTrue(element.isRangeSelected());
         assert.deepEqual(getActionRange(), {
-          startLine: 138,
-          startChar: 5,
-          endLine: 138,
-          endChar: 12,
+          start_line: 138,
+          start_character: 5,
+          end_line: 138,
+          end_character: 12,
         });
         assert.equal(getActionSide(), 'left');
         assert.notOk(actionBox.positionBelow);
@@ -337,10 +337,10 @@
         const actionBox = element.$$('gr-selection-action-box');
 
         assert.deepEqual(getActionRange(), {
-          startLine: 119,
-          startChar: 10,
-          endLine: 120,
-          endChar: 36,
+          start_line: 119,
+          start_character: 10,
+          end_line: 120,
+          end_character: 36,
         });
         assert.equal(getActionSide(), 'right');
         assert.notOk(actionBox.positionBelow);
@@ -370,10 +370,10 @@
         element._handleSelection();
         assert.isTrue(element.isRangeSelected());
         assert.deepEqual(getActionRange(), {
-          startLine: 119,
-          startChar: 10,
-          endLine: 120,
-          endChar: 36,
+          start_line: 119,
+          start_character: 10,
+          end_line: 120,
+          end_character: 36,
         });
       });
 
@@ -383,10 +383,10 @@
         emulateSelection(startContent.firstChild, 10, endContent.firstChild, 2);
         assert.isTrue(element.isRangeSelected());
         assert.deepEqual(getActionRange(), {
-          startLine: 119,
-          startChar: 10,
-          endLine: 120,
-          endChar: 2,
+          start_line: 119,
+          start_character: 10,
+          end_line: 120,
+          end_character: 2,
         });
         assert.equal(getActionSide(), 'right');
       });
@@ -404,10 +404,10 @@
         emulateSelection(hl.firstChild, 2, hl.nextSibling, 7);
         assert.isTrue(element.isRangeSelected());
         assert.deepEqual(getActionRange(), {
-          startLine: 140,
-          startChar: 8,
-          endLine: 140,
-          endChar: 23,
+          start_line: 140,
+          start_character: 8,
+          end_line: 140,
+          end_character: 23,
         });
         assert.equal(getActionSide(), 'left');
       });
@@ -418,10 +418,10 @@
         emulateSelection(hl.previousSibling, 2, hl.firstChild, 3);
         assert.isTrue(element.isRangeSelected());
         assert.deepEqual(getActionRange(), {
-          startLine: 140,
-          startChar: 18,
-          endLine: 140,
-          endChar: 27,
+          start_line: 140,
+          start_character: 18,
+          end_line: 140,
+          end_character: 27,
         });
       });
 
@@ -431,10 +431,10 @@
         emulateSelection(content.firstChild, 2, hl.firstChild, 2);
         assert.isTrue(element.isRangeSelected());
         assert.deepEqual(getActionRange(), {
-          startLine: 140,
-          startChar: 2,
-          endLine: 140,
-          endChar: 61,
+          start_line: 140,
+          start_character: 2,
+          end_line: 140,
+          end_character: 61,
         });
         assert.equal(getActionSide(), 'left');
       });
@@ -470,10 +470,10 @@
         emulateSelection(comment.firstChild, 2, endContent.firstChild, 4);
         assert.isTrue(element.isRangeSelected());
         assert.deepEqual(getActionRange(), {
-          startLine: 140,
-          startChar: 83,
-          endLine: 141,
-          endChar: 4,
+          start_line: 140,
+          start_character: 83,
+          end_line: 141,
+          end_character: 4,
         });
         assert.equal(getActionSide(), 'left');
       });
@@ -485,10 +485,10 @@
         emulateSelection(content.firstChild, 4, comment.firstChild, 1);
         assert.isTrue(element.isRangeSelected());
         assert.deepEqual(getActionRange(), {
-          startLine: 140,
-          startChar: 4,
-          endLine: 140,
-          endChar: 83,
+          start_line: 140,
+          start_character: 4,
+          end_line: 140,
+          end_character: 83,
         });
         assert.equal(getActionSide(), 'left');
       });
@@ -517,10 +517,10 @@
         emulateSelection(startContent.firstChild, 3, endContent.firstChild, 14);
         assert.isTrue(element.isRangeSelected());
         assert.deepEqual(getActionRange(), {
-          startLine: 130,
-          startChar: 3,
-          endLine: 146,
-          endChar: 14,
+          start_line: 130,
+          start_character: 3,
+          end_line: 146,
+          end_character: 14,
         });
         assert.equal(getActionSide(), 'right');
       });
@@ -531,10 +531,10 @@
             content.firstChild, 1, content.querySelector('span'), 0);
         assert.isTrue(element.isRangeSelected());
         assert.deepEqual(getActionRange(), {
-          startLine: 140,
-          startChar: 1,
-          endLine: 140,
-          endChar: 51,
+          start_line: 140,
+          start_character: 1,
+          end_line: 140,
+          end_character: 51,
         });
         assert.equal(getActionSide(), 'left');
       });
@@ -546,10 +546,10 @@
             content.querySelectorAll('span')[1].nextSibling, 1);
         assert.isTrue(element.isRangeSelected());
         assert.deepEqual(getActionRange(), {
-          startLine: 140,
-          startChar: 51,
-          endLine: 140,
-          endChar: 71,
+          start_line: 140,
+          start_character: 51,
+          end_line: 140,
+          end_character: 71,
         });
         assert.equal(getActionSide(), 'left');
       });
@@ -582,10 +582,10 @@
         emulateSelection(startContent.firstChild, 0, endContent.firstChild, 0);
         assert.isTrue(element.isRangeSelected());
         assert.deepEqual(getActionRange(), {
-          startLine: 119,
-          startChar: 0,
-          endLine: 119,
-          endChar: element._getLength(startContent),
+          start_line: 119,
+          start_character: 0,
+          end_line: 119,
+          end_character: element._getLength(startContent),
         });
         assert.equal(getActionSide(), 'right');
       });
@@ -597,10 +597,10 @@
             endContent.parentElement.previousElementSibling, 0);
         assert.isTrue(element.isRangeSelected());
         assert.deepEqual(getActionRange(), {
-          startLine: 146,
-          startChar: 0,
-          endLine: 146,
-          endChar: 84,
+          start_line: 146,
+          start_character: 0,
+          end_line: 146,
+          end_character: 84,
         });
         assert.equal(getActionSide(), 'right');
       });
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 e3bf866..3eb7b37 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
@@ -16,9 +16,10 @@
 -->
 
 <link rel="import" href="../../../bower_components/polymer/polymer.html">
+<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="../gr-diff/gr-diff.html">
 
 <dom-module id="gr-diff-host">
@@ -30,14 +31,12 @@
         patch-range="[[patchRange]]"
         path="[[path]]"
         prefs="[[prefs]]"
-        project-config="[[projectConfig]]"
         project-name="[[projectName]]"
         display-line="[[displayLine]]"
         is-image-diff="[[isImageDiff]]"
         commit-range="[[commitRange]]"
         hidden$="[[hidden]]"
         no-render-on-prefs-change="[[noRenderOnPrefsChange]]"
-        comments="[[comments]]"
         line-wrapping="[[lineWrapping]]"
         view-mode="[[viewMode]]"
         line-of-interest="[[lineOfInterest]]"
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 6f61fb9..5839141 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
@@ -46,12 +46,29 @@
   }
 
   /**
+   * Compare two ranges. Either argument may be falsy, but will only return
+   * true if both are falsy or if neither are falsy and have the same position
+   * values.
+   *
+   * @param {Gerrit.Range=} a range 1
+   * @param {Gerrit.Range=} b range 2
+   * @return {boolean}
+   */
+  function rangesEqual(a, b) {
+    if (!a && !b) { return true; }
+    if (!a || !b) { return false; }
+    return a.start_line === b.start_line &&
+        a.start_character === b.start_character &&
+        a.end_line === b.end_line &&
+        a.end_character === b.end_character;
+  }
+
+  /**
    * Wrapper around gr-diff.
    *
    * Webcomponent fetching diffs and related data from restAPI and passing them
    * to the presentational gr-diff for rendering.
    */
-  // TODO(oler): Move all calls to restAPI from gr-diff here.
   Polymer({
     is: 'gr-diff-host',
 
@@ -84,9 +101,6 @@
       prefs: {
         type: Object,
       },
-      projectConfig: {
-        type: Object,
-      },
       projectName: String,
       displayLine: {
         type: Boolean,
@@ -111,7 +125,10 @@
         type: Boolean,
         value: false,
       },
-      comments: Object,
+      comments: {
+        type: Object,
+        observer: '_commentsChanged',
+      },
       lineWrapping: {
         type: Boolean,
         value: false,
@@ -174,10 +191,33 @@
       },
 
       _loadedWhitespaceLevel: String,
+
+      _parentIndex: {
+        type: Number,
+        computed: '_computeParentIndex(patchRange.*)',
+      },
+
+      _threadEls: {
+        type: Array,
+        value: () => [],
+      },
     },
 
+    behaviors: [
+      Gerrit.PatchSetBehavior,
+    ],
+
     listeners: {
-      'draft-interaction': '_handleDraftInteraction',
+      // These are named inconsistently for a reason:
+      // The create-comment event is fired to indicate that we should
+      // create a comment.
+      // The comment-* events are just notifying that the comments did already
+      // change in some way, and that we should update any models we may want
+      // to keep in sync.
+      'create-comment': '_handleCreateComment',
+      'comment-discard': '_handleCommentDiscard',
+      'comment-update': '_handleCommentUpdate',
+      'comment-save': '_handleCommentSave',
     },
 
     observers: [
@@ -299,9 +339,12 @@
       this._blame = null;
     },
 
-    /** @return {!Array<!HTMLElement>} */
+    /**
+     * The thread elements in this diff, in no particular order.
+     * @return {!Array<!HTMLElement>}
+     */
     getThreadEls() {
-      return this.$.diff.getThreadEls();
+      return this._threadEls;
     },
 
     /** @param {HTMLElement} el */
@@ -428,6 +471,70 @@
       return isImageDiff(diff);
     },
 
+
+    _commentsChanged(newComments) {
+      const allComments = [];
+      for (const side of [GrDiffBuilder.Side.LEFT, GrDiffBuilder.Side.RIGHT]) {
+        // This is needed by the threading.
+        for (const comment of newComments[side]) {
+          comment.__commentSide = side;
+        }
+        allComments.push(...newComments[side]);
+      }
+      // Currently, the only way this is ever changed here is when the initial
+      // comments are loaded, so it's okay performance wise to clear the threads
+      // and recreate them. If this changes in future, we might want to reuse
+      // some DOM nodes here.
+      this._clearThreads();
+      const threads = this._createThreads(allComments);
+      for (const thread of threads) {
+        const threadEl = this._createThreadElement(thread);
+        this._attachThreadElement(threadEl);
+      }
+    },
+
+    /**
+     * @param {!Array<!Object>} comments
+     * @return {!Array<!Object>} Threads for the given comments.
+     */
+    _createThreads(comments) {
+      const sortedComments = comments.slice(0).sort((a, b) => {
+        if (b.__draft && !a.__draft ) { return 0; }
+        if (a.__draft && !b.__draft ) { return 1; }
+        return util.parseDate(a.updated) - util.parseDate(b.updated);
+      });
+
+      const threads = [];
+      for (const comment of sortedComments) {
+        // If the comment is in reply to another comment, find that comment's
+        // thread and append to it.
+        if (comment.in_reply_to) {
+          const thread = threads.find(thread =>
+              thread.comments.some(c => c.id === comment.in_reply_to));
+          if (thread) {
+            thread.comments.push(comment);
+            continue;
+          }
+        }
+
+        // Otherwise, this comment starts its own thread.
+        const newThread = {
+          start_datetime: comment.updated,
+          comments: [comment],
+          commentSide: comment.__commentSide,
+          patchNum: comment.patch_set,
+          rootId: comment.id || comment.__draftID,
+          lineNum: comment.line,
+          isOnParent: comment.side === 'PARENT',
+        };
+        if (comment.range) {
+          newThread.range = Object.assign({}, comment.range);
+        }
+        threads.push(newThread);
+      }
+      return threads;
+    },
+
     /**
      * @param {Object} blame
      * @return {boolean}
@@ -445,11 +552,120 @@
           this.patchRange);
     },
 
-    _handleDraftInteraction() {
+    /** @param {CustomEvent} e */
+    _handleCreateComment(e) {
+      const {lineNum, side, patchNum, isOnParent, range} = e.detail;
+      const threadEl = this._getOrCreateThread(patchNum, lineNum, side, range,
+          isOnParent);
+      threadEl.addOrEditDraft(lineNum, range);
+
       this.$.reporting.recordDraftInteraction();
     },
 
     /**
+     * Gets or creates a comment thread at a given location.
+     * May provide a range, to get/create a range comment.
+     *
+     * @param {string} patchNum
+     * @param {?number} lineNum
+     * @param {string} commentSide
+     * @param {Gerrit.Range|undefined} range
+     * @param {boolean} isOnParent
+     * @return {!Object}
+     */
+    _getOrCreateThread(patchNum, lineNum, commentSide, range, isOnParent) {
+      let threadEl = this._getThreadEl(lineNum, commentSide, range);
+      if (!threadEl) {
+        threadEl = this._createThreadElement({
+          comments: [],
+          commentSide,
+          patchNum,
+          lineNum,
+          range,
+          isOnParent,
+        });
+        this._attachThreadElement(threadEl);
+      }
+      return threadEl;
+    },
+
+    _attachThreadElement(threadEl) {
+      this._threadEls.push(threadEl);
+      Polymer.dom(this.$.diff).appendChild(threadEl);
+    },
+
+    _clearThreads() {
+      for (const threadEl of this._threadEls) {
+        const parent = Polymer.dom(threadEl).parentNode;
+        Polymer.dom(parent).removeChild(threadEl);
+      }
+      this._threadEls = [];
+    },
+
+    _createThreadElement(thread) {
+      const threadEl = document.createElement('gr-diff-comment-thread');
+      threadEl.className = 'comment-thread';
+      threadEl.comments = thread.comments;
+      threadEl.commentSide = thread.commentSide;
+      threadEl.isOnParent = !!thread.isOnParent;
+      threadEl.parentIndex = this._parentIndex;
+      threadEl.changeNum = this.changeNum;
+      threadEl.patchNum = thread.patchNum;
+      threadEl.lineNum = thread.lineNum;
+      const rootIdChangedListener = changeEvent => {
+        thread.rootId = changeEvent.detail.value;
+      };
+      threadEl.addEventListener('root-id-changed', rootIdChangedListener);
+      threadEl.path = this.path;
+      threadEl.projectName = this.projectName;
+      threadEl.range = thread.range;
+      const threadDiscardListener = e => {
+        const threadEl = /** @type {!Node} */ (e.currentTarget);
+
+        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);
+      };
+      threadEl.addEventListener('thread-discard', threadDiscardListener);
+      return threadEl;
+    },
+
+    /**
+     * Gets a comment thread element at a given location.
+     * May provide a range, to get a range comment.
+     *
+     * @param {?number} lineNum
+     * @param {string} commentSide
+     * @param {!Gerrit.Range=} range
+     * @return {?Node}
+     */
+    _getThreadEl(lineNum, commentSide, range=undefined) {
+      let line;
+      if (commentSide === GrDiffBuilder.Side.LEFT) {
+        line = {beforeNumber: lineNum};
+      } else if (commentSide === GrDiffBuilder.Side.RIGHT) {
+        line = {afterNumber: lineNum};
+      } else {
+        throw new Error(`Unknown side: ${commentSide}`);
+      }
+      function matchesRange(threadEl) {
+        const threadRange = /** @type {!Gerrit.Range} */(
+            JSON.parse(threadEl.getAttribute('range')));
+        return rangesEqual(threadRange, range);
+      }
+
+      const filteredThreadEls = Gerrit.filterThreadElsForLocation(
+          this._threadEls, line, commentSide).filter(matchesRange);
+      return filteredThreadEls.length ? filteredThreadEls[0] : null;
+    },
+
+    /**
      * Take a diff that was loaded with a ignore-whitespace other than
      * IGNORE_NONE, and convert delta chunks labeled as common into shared
      * chunks.
@@ -506,5 +722,86 @@
         this.reload();
       }
     },
+
+    /**
+     * @param {Object} patchRangeRecord
+     * @return {number|null}
+     */
+    _computeParentIndex(patchRangeRecord) {
+      return this.isMergeParent(patchRangeRecord.base.basePatchNum) ?
+          this.getParentIndex(patchRangeRecord.base.basePatchNum) : null;
+    },
+
+    _handleCommentSave(e) {
+      const comment = e.detail.comment;
+      const side = e.detail.comment.__commentSide;
+      const idx = this._findDraftIndex(comment, side);
+      this.set(['comments', side, idx], comment);
+      this._handleCommentSaveOrDiscard();
+    },
+
+    _handleCommentDiscard(e) {
+      const comment = e.detail.comment;
+      this._removeComment(comment);
+      this._handleCommentSaveOrDiscard();
+    },
+
+    /**
+     * Closure annotation for Polymer.prototype.push is off. Submitted PR:
+     * https://github.com/Polymer/polymer/pull/4776
+     * but for not supressing annotations.
+     *
+     * @suppress {checkTypes}
+     */
+    _handleCommentUpdate(e) {
+      const comment = e.detail.comment;
+      const side = e.detail.comment.__commentSide;
+      let idx = this._findCommentIndex(comment, side);
+      if (idx === -1) {
+        idx = this._findDraftIndex(comment, side);
+      }
+      if (idx !== -1) { // Update draft or comment.
+        this.set(['comments', side, idx], comment);
+      } else { // Create new draft.
+        this.push(['comments', side], comment);
+      }
+    },
+
+    _handleCommentSaveOrDiscard() {
+      this.dispatchEvent(new CustomEvent('diff-comments-modified',
+          {bubbles: true}));
+    },
+
+    _removeComment(comment) {
+      const side = comment.__commentSide;
+      this._removeCommentFromSide(comment, side);
+    },
+
+    _removeCommentFromSide(comment, side) {
+      let idx = this._findCommentIndex(comment, side);
+      if (idx === -1) {
+        idx = this._findDraftIndex(comment, side);
+      }
+      if (idx !== -1) {
+        this.splice('comments.' + side, idx, 1);
+      }
+    },
+
+    /** @return {number} */
+    _findCommentIndex(comment, side) {
+      if (!comment.id || !this.comments[side]) {
+        return -1;
+      }
+      return this.comments[side].findIndex(item => item.id === comment.id);
+    },
+
+    /** @return {number} */
+    _findDraftIndex(comment, side) {
+      if (!comment.__draftID || !this.comments[side]) {
+        return -1;
+      }
+      return this.comments[side].findIndex(
+          item => item.__draftID === comment.__draftID);
+    },
   });
 })();
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 f83253e..5344256 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
@@ -37,9 +37,14 @@
   suite('gr-diff-host tests', () => {
     let element;
     let sandbox;
+    let getLoggedIn;
 
     setup(() => {
       sandbox = sinon.sandbox.create();
+      getLoggedIn = false;
+      stub('gr-rest-api-interface', {
+        async getLoggedIn() { return getLoggedIn; },
+      });
       element = fixture('basic');
     });
 
@@ -47,6 +52,215 @@
       sandbox.restore();
     });
 
+    suite('handle comment-update', () => {
+      setup(() => {
+        sandbox.stub(element, '_commentsChanged');
+        element.comments = {
+          meta: {
+            changeNum: '42',
+            patchRange: {
+              basePatchNum: 'PARENT',
+              patchNum: 3,
+            },
+            path: '/path/to/foo',
+            projectConfig: {foo: 'bar'},
+          },
+          left: [
+            {id: 'bc1', side: 'PARENT', __commentSide: 'left'},
+            {id: 'bc2', side: 'PARENT', __commentSide: 'left'},
+            {id: 'bd1', __draft: true, side: 'PARENT', __commentSide: 'left'},
+            {id: 'bd2', __draft: true, side: 'PARENT', __commentSide: 'left'},
+          ],
+          right: [
+            {id: 'c1', __commentSide: 'right'},
+            {id: 'c2', __commentSide: 'right'},
+            {id: 'd1', __draft: true, __commentSide: 'right'},
+            {id: 'd2', __draft: true, __commentSide: 'right'},
+          ],
+        };
+      });
+
+      test('creating a draft', () => {
+        const comment = {__draft: true, __draftID: 'tempID', side: 'PARENT',
+          __commentSide: 'left'};
+        element.fire('comment-update', {comment});
+        assert.include(element.comments.left, comment);
+      });
+
+      test('discarding a draft', () => {
+        const draftID = 'tempID';
+        const id = 'savedID';
+        const comment = {
+          __draft: true,
+          __draftID: draftID,
+          side: 'PARENT',
+          __commentSide: 'left',
+        };
+        const diffCommentsModifiedStub = sandbox.stub();
+        element.addEventListener('diff-comments-modified',
+            diffCommentsModifiedStub);
+        element.comments.left.push(comment);
+        comment.id = id;
+        element.fire('comment-discard', {comment});
+        const drafts = element.comments.left.filter(item => {
+          return item.__draftID === draftID;
+        });
+        assert.equal(drafts.length, 0);
+        assert.isTrue(diffCommentsModifiedStub.called);
+      });
+
+      test('saving a draft', () => {
+        const draftID = 'tempID';
+        const id = 'savedID';
+        const comment = {
+          __draft: true,
+          __draftID: draftID,
+          side: 'PARENT',
+          __commentSide: 'left',
+        };
+        const diffCommentsModifiedStub = sandbox.stub();
+        element.addEventListener('diff-comments-modified',
+            diffCommentsModifiedStub);
+        element.comments.left.push(comment);
+        comment.id = id;
+        element.fire('comment-save', {comment});
+        const drafts = element.comments.left.filter(item => {
+          return item.__draftID === draftID;
+        });
+        assert.equal(drafts.length, 1);
+        assert.equal(drafts[0].id, id);
+        assert.isTrue(diffCommentsModifiedStub.called);
+      });
+    });
+
+    test('remove comment', () => {
+      sandbox.stub(element, '_commentsChanged');
+      element.comments = {
+        meta: {
+          changeNum: '42',
+          patchRange: {
+            basePatchNum: 'PARENT',
+            patchNum: 3,
+          },
+          path: '/path/to/foo',
+          projectConfig: {foo: 'bar'},
+        },
+        left: [
+          {id: 'bc1', side: 'PARENT', __commentSide: 'left'},
+          {id: 'bc2', side: 'PARENT', __commentSide: 'left'},
+          {id: 'bd1', __draft: true, side: 'PARENT', __commentSide: 'left'},
+          {id: 'bd2', __draft: true, side: 'PARENT', __commentSide: 'left'},
+        ],
+        right: [
+          {id: 'c1', __commentSide: 'right'},
+          {id: 'c2', __commentSide: 'right'},
+          {id: 'd1', __draft: true, __commentSide: 'right'},
+          {id: 'd2', __draft: true, __commentSide: 'right'},
+        ],
+      };
+
+      element._removeComment({});
+      // Using JSON.stringify because Safari 9.1 (11601.5.17.1) doesn’t seem
+      // to believe that one object deepEquals another even when they do :-/.
+      assert.equal(JSON.stringify(element.comments), JSON.stringify({
+        meta: {
+          changeNum: '42',
+          patchRange: {
+            basePatchNum: 'PARENT',
+            patchNum: 3,
+          },
+          path: '/path/to/foo',
+          projectConfig: {foo: 'bar'},
+        },
+        left: [
+          {id: 'bc1', side: 'PARENT', __commentSide: 'left'},
+          {id: 'bc2', side: 'PARENT', __commentSide: 'left'},
+          {id: 'bd1', __draft: true, side: 'PARENT', __commentSide: 'left'},
+          {id: 'bd2', __draft: true, side: 'PARENT', __commentSide: 'left'},
+        ],
+        right: [
+          {id: 'c1', __commentSide: 'right'},
+          {id: 'c2', __commentSide: 'right'},
+          {id: 'd1', __draft: true, __commentSide: 'right'},
+          {id: 'd2', __draft: true, __commentSide: 'right'},
+        ],
+      }));
+
+      element._removeComment({id: 'bc2', side: 'PARENT',
+        __commentSide: 'left'});
+      assert.deepEqual(element.comments, {
+        meta: {
+          changeNum: '42',
+          patchRange: {
+            basePatchNum: 'PARENT',
+            patchNum: 3,
+          },
+          path: '/path/to/foo',
+          projectConfig: {foo: 'bar'},
+        },
+        left: [
+          {id: 'bc1', side: 'PARENT', __commentSide: 'left'},
+          {id: 'bd1', __draft: true, side: 'PARENT', __commentSide: 'left'},
+          {id: 'bd2', __draft: true, side: 'PARENT', __commentSide: 'left'},
+        ],
+        right: [
+          {id: 'c1', __commentSide: 'right'},
+          {id: 'c2', __commentSide: 'right'},
+          {id: 'd1', __draft: true, __commentSide: 'right'},
+          {id: 'd2', __draft: true, __commentSide: 'right'},
+        ],
+      });
+
+      element._removeComment({id: 'd2', __commentSide: 'right'});
+      assert.deepEqual(element.comments, {
+        meta: {
+          changeNum: '42',
+          patchRange: {
+            basePatchNum: 'PARENT',
+            patchNum: 3,
+          },
+          path: '/path/to/foo',
+          projectConfig: {foo: 'bar'},
+        },
+        left: [
+          {id: 'bc1', side: 'PARENT', __commentSide: 'left'},
+          {id: 'bd1', __draft: true, side: 'PARENT', __commentSide: 'left'},
+          {id: 'bd2', __draft: true, side: 'PARENT', __commentSide: 'left'},
+        ],
+        right: [
+          {id: 'c1', __commentSide: 'right'},
+          {id: 'c2', __commentSide: 'right'},
+          {id: 'd1', __draft: true, __commentSide: 'right'},
+        ],
+      });
+    });
+
+    test('thread-discard handling', () => {
+      const threads = [
+        {comments: [{id: 4711}]},
+        {comments: [{id: 42}]},
+      ];
+      element._parentIndex = 1;
+      element.changeNum = '2';
+      element.path = 'some/path';
+      element.projectName = 'Some project';
+      const threadEls = threads.map(
+          thread => element._createThreadElement(thread));
+      assert.equal(threadEls.length, 2);
+      assert.equal(threadEls[0].rootId, 4711);
+      assert.equal(threadEls[1].rootId, 42);
+      for (const threadEl of threadEls) {
+        Polymer.dom(element).appendChild(threadEl);
+      }
+
+      threadEls[0].dispatchEvent(
+          new CustomEvent('thread-discard', {detail: {rootId: 4711}}));
+      const attachedThreads = element.queryAllEffectiveChildren(
+          'gr-diff-comment-thread');
+      assert.equal(attachedThreads.length, 1);
+      assert.equal(attachedThreads[0].rootId, 42);
+    });
+
     test('reload() cancels before network resolves', () => {
       const cancelStub = sandbox.stub(element.$.diff, 'cancel');
 
@@ -59,12 +273,8 @@
 
     suite('not logged in', () => {
       setup(() => {
-        const getLoggedInPromise = Promise.resolve(false);
-        stub('gr-rest-api-interface', {
-          getLoggedIn() { return getLoggedInPromise; },
-        });
+        getLoggedIn = false;
         element = fixture('basic');
-        return getLoggedInPromise;
       });
 
       test('reload() loads files weblinks', () => {
@@ -181,7 +391,11 @@
               });
 
           element.patchRange = {basePatchNum: 'PARENT', patchNum: 1};
-          element.comments = {left: [], right: []};
+          element.comments = {
+            left: [],
+            right: [],
+            meta: {patchRange: element.patchRange},
+          };
         });
 
         test('renders image diffs with same file name', done => {
@@ -555,13 +769,10 @@
       });
     });
 
-    test('delegates getThreadEls()', () => {
+    test('getThreadEls() returns _threadEls', () => {
       const returnValue = [document.createElement('b')];
-      const stub = sandbox.stub(element.$.diff, 'getThreadEls')
-          .returns(returnValue);
+      element._threadEls = returnValue;
       assert.equal(element.getThreadEls(), returnValue);
-      assert.isTrue(stub.calledOnce);
-      assert.equal(stub.lastCall.args.length, 0);
     });
 
     test('delegates addDraftAtLine(el)', () => {
@@ -617,12 +828,6 @@
       assert.equal(element.$.diff.prefs, value);
     });
 
-    test('passes in projectConfig', () => {
-      const value = {};
-      element.projectConfig = value;
-      assert.equal(element.$.diff.projectConfig, value);
-    });
-
     test('passes in changeNum', () => {
       const value = '12345';
       element.changeNum = value;
@@ -660,12 +865,6 @@
       assert.equal(element.$.diff.noRenderOnPrefsChange, value);
     });
 
-    test('passes in comments', () => {
-      const value = {left: [], right: []};
-      element.comments = value;
-      assert.equal(element.$.diff.comments, value);
-    });
-
     test('passes in lineWrapping', () => {
       const value = true;
       element.lineWrapping = value;
@@ -776,6 +975,190 @@
       });
     });
 
+    test('_createThreads', () => {
+      const comments = [
+        {
+          id: 'sallys_confession',
+          message: 'i like you, jack',
+          updated: '2015-12-23 15:00:20.396000000',
+          line: 1,
+          __commentSide: 'left',
+        }, {
+          id: 'jacks_reply',
+          message: 'i like you, too',
+          updated: '2015-12-24 15:01:20.396000000',
+          __commentSide: 'left',
+          line: 1,
+          in_reply_to: 'sallys_confession',
+        },
+        {
+          id: 'new_draft',
+          message: 'i do not like either of you',
+          __commentSide: 'left',
+          __draft: true,
+          updated: '2015-12-20 15:01:20.396000000',
+        },
+      ];
+
+      const actualThreads = element._createThreads(comments);
+
+      assert.equal(actualThreads.length, 2);
+
+      assert.equal(
+          actualThreads[0].start_datetime, '2015-12-23 15:00:20.396000000');
+      assert.equal(actualThreads[0].commentSide, 'left');
+      assert.equal(actualThreads[0].comments.length, 2);
+      assert.deepEqual(actualThreads[0].comments[0], comments[0]);
+      assert.deepEqual(actualThreads[0].comments[1], comments[1]);
+      assert.equal(actualThreads[0].patchNum, undefined);
+      assert.equal(actualThreads[0].rootId, 'sallys_confession');
+      assert.equal(actualThreads[0].lineNum, 1);
+
+      assert.equal(
+          actualThreads[1].start_datetime, '2015-12-20 15:01:20.396000000');
+      assert.equal(actualThreads[1].commentSide, 'left');
+      assert.equal(actualThreads[1].comments.length, 1);
+      assert.deepEqual(actualThreads[1].comments[0], comments[2]);
+      assert.equal(actualThreads[1].patchNum, undefined);
+      assert.equal(actualThreads[1].rootId, 'new_draft');
+      assert.equal(actualThreads[1].lineNum, undefined);
+    });
+
+    test('_createThreads inherits patchNum and range', () => {
+      const comments = [{
+        id: 'betsys_confession',
+        message: 'i like you, jack',
+        updated: '2015-12-24 15:00:10.396000000',
+        range: {
+          start_line: 1,
+          start_character: 1,
+          end_line: 1,
+          end_character: 2,
+        },
+        patch_set: 5,
+        __commentSide: 'left',
+        line: 1,
+      }];
+
+      expectedThreads = [
+        {
+          start_datetime: '2015-12-24 15:00:10.396000000',
+          commentSide: 'left',
+          comments: [{
+            id: 'betsys_confession',
+            message: 'i like you, jack',
+            updated: '2015-12-24 15:00:10.396000000',
+            range: {
+              start_line: 1,
+              start_character: 1,
+              end_line: 1,
+              end_character: 2,
+            },
+            patch_set: 5,
+            __commentSide: 'left',
+            line: 1,
+          }],
+          patchNum: 5,
+          rootId: 'betsys_confession',
+          range: {
+            start_line: 1,
+            start_character: 1,
+            end_line: 1,
+            end_character: 2,
+          },
+          lineNum: 1,
+          isOnParent: false,
+        },
+      ];
+
+      assert.deepEqual(
+          element._createThreads(comments),
+          expectedThreads);
+    });
+
+    test('_createThreads does not thread unrelated comments at same location',
+        () => {
+          const comments = [
+            {
+              id: 'sallys_confession',
+              message: 'i like you, jack',
+              updated: '2015-12-23 15:00:20.396000000',
+              __commentSide: 'left',
+            }, {
+              id: 'jacks_reply',
+              message: 'i like you, too',
+              updated: '2015-12-24 15:01:20.396000000',
+              __commentSide: 'left',
+            },
+          ];
+          assert.equal(element._createThreads(comments).length, 2);
+        });
+
+    test('_createThreads derives isOnParent using  side from first comment',
+        () => {
+          const comments = [
+            {
+              id: 'sallys_confession',
+              message: 'i like you, jack',
+              updated: '2015-12-23 15:00:20.396000000',
+              // line: 1,
+              // __commentSide: 'left',
+            }, {
+              id: 'jacks_reply',
+              message: 'i like you, too',
+              updated: '2015-12-24 15:01:20.396000000',
+              // __commentSide: 'left',
+              // line: 1,
+              in_reply_to: 'sallys_confession',
+            },
+          ];
+
+          assert.equal(element._createThreads(comments)[0].isOnParent, false);
+
+          comments[0].side = 'REVISION';
+          assert.equal(element._createThreads(comments)[0].isOnParent, false);
+
+          comments[0].side = 'PARENT';
+          assert.equal(element._createThreads(comments)[0].isOnParent, true);
+        });
+
+    test('_getOrCreateThread', () => {
+      const commentSide = 'left';
+
+      assert.isOk(element._getOrCreateThread('2', 3,
+          commentSide, undefined, false));
+
+      let threads = Polymer.dom(element.$.diff)
+          .queryDistributedElements('gr-diff-comment-thread');
+
+      assert.equal(threads.length, 1);
+      assert.equal(threads[0].commentSide, commentSide);
+      assert.equal(threads[0].range, undefined);
+      assert.equal(threads[0].isOnParent, false);
+      assert.equal(threads[0].patchNum, 2);
+
+
+      // Try to fetch a thread with a different range.
+      range = {
+        start_line: 1,
+        start_character: 1,
+        end_line: 1,
+        end_character: 3,
+      };
+
+      assert.isOk(element._getOrCreateThread(
+          '3', 1, commentSide, range, true));
+
+      threads = Polymer.dom(element.$.diff)
+          .queryDistributedElements('gr-diff-comment-thread');
+
+      assert.equal(threads.length, 2);
+      assert.equal(threads[1].commentSide, commentSide);
+      assert.equal(threads[1].range, range);
+      assert.equal(threads[1].isOnParent, true);
+      assert.equal(threads[1].patchNum, 3);
+    });
+
     suite('_translateChunksToIgnore', () => {
       let content;
 
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html
index 0866849..b3210cc 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html
@@ -286,11 +286,11 @@
             <span>Diff view:</span>
             <gr-diff-mode-selector
                 id="modeSelect"
-                save-on-change="[[_loggedIn]]"
+                save-on-change="[[!_diffPrefsDisabled]]"
                 mode="{{changeViewState.diffMode}}"></gr-diff-mode-selector>
           </div>
           <span id="diffPrefsContainer"
-              hidden$="[[_computePrefsButtonHidden(_prefs, _loggedIn)]]" hidden>
+              hidden$="[[_computePrefsButtonHidden(_prefs, _diffPrefsDisabled)]]" hidden>
             <span class="preferences desktop">
               <gr-button
                   link
@@ -332,10 +332,10 @@
         patch-range="[[_patchRange]]"
         path="[[_path]]"
         prefs="[[_prefs]]"
-        project-config="[[_projectConfig]]"
         project-name="[[_change.project]]"
         view-mode="[[_diffMode]]"
         is-blame-loaded="{{_isBlameLoaded}}"
+        on-comment-anchor-tap="_onLineSelected"
         on-line-selected="_onLineSelected">
     </gr-diff-host>
     <gr-diff-preferences
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 095dc72..5a56069 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
@@ -69,6 +69,14 @@
         value() { return {}; },
         observer: '_changeViewStateChanged',
       },
+      disableDiffPrefs: {
+        type: Boolean,
+        value: false,
+      },
+      _diffPrefsDisabled: {
+        type: Boolean,
+        computed: '_computeDiffPrefsDisabled(disableDiffPrefs, _loggedIn)',
+      },
       /** @type {?} */
       _patchRange: Object,
       /** @type {?} */
@@ -455,6 +463,7 @@
     _handleCommaKey(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
           this.modifierPressed(e)) { return; }
+      if (this._diffPrefsDisabled) { return; }
 
       e.preventDefault();
       this.$.diffPreferences.open();
@@ -804,8 +813,8 @@
           (unresolvedString ? `${unresolvedString}` : '');
     },
 
-    _computePrefsButtonHidden(prefs, loggedIn) {
-      return !loggedIn || !prefs;
+    _computePrefsButtonHidden(prefs, prefsDisabled) {
+      return prefsDisabled || !prefs;
     },
 
     _handleFileChange(e) {
@@ -1026,6 +1035,10 @@
       this.$.diffHost.expandAllContext();
     },
 
+    _computeDiffPrefsDisabled(disableDiffPrefs, loggedIn) {
+      return disableDiffPrefs || !loggedIn;
+    },
+
     _handleNextUnreviewedFile(e) {
       if (this.shouldSuppressKeyboardShortcut(e)) { return; }
       this._setReviewed(true);
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html
index 958acdb..0274330 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html
@@ -136,6 +136,7 @@
       element._fileList = ['chell.go', 'glados.txt', 'wheatley.md'];
       element._path = 'glados.txt';
       element.changeViewState.selectedFileIndex = 1;
+      element._loggedIn = true;
 
       const diffNavStub = sandbox.stub(Gerrit.Nav, 'navigateToDiff');
       const changeNavStub = sandbox.stub(Gerrit.Nav, 'navigateToChange');
@@ -178,6 +179,10 @@
       MockInteractions.pressAndReleaseKeyOn(element, 188, null, ',');
       assert(showPrefsStub.calledOnce);
 
+      element.disableDiffPrefs = true;
+      MockInteractions.pressAndReleaseKeyOn(element, 188, null, ',');
+      assert(showPrefsStub.calledOnce);
+
       let scrollStub = sandbox.stub(element.$.cursor, 'moveToNextChunk');
       MockInteractions.pressAndReleaseKeyOn(element, 78, null, 'n');
       assert(scrollStub.calledOnce);
@@ -344,23 +349,39 @@
           PARENT), 'Should navigate to /c/42/1');
     });
 
-    test('Diff preferences hidden when no prefs or logged out', () => {
-      element._loggedIn = false;
-      flushAsynchronousOperations();
-      assert.isTrue(element.$.diffPrefsContainer.hidden);
+    suite('diff prefs hidden', () => {
+      test('when no prefs or logged out', () => {
+        element.disableDiffPrefs = false;
+        element._loggedIn = false;
+        flushAsynchronousOperations();
+        assert.isTrue(element.$.diffPrefsContainer.hidden);
 
-      element._loggedIn = true;
-      flushAsynchronousOperations();
-      assert.isTrue(element.$.diffPrefsContainer.hidden);
+        element._loggedIn = true;
+        flushAsynchronousOperations();
+        assert.isTrue(element.$.diffPrefsContainer.hidden);
 
-      element._loggedIn = false;
-      element._prefs = {font_size: '12'};
-      flushAsynchronousOperations();
-      assert.isTrue(element.$.diffPrefsContainer.hidden);
+        element._loggedIn = false;
+        element._prefs = {font_size: '12'};
+        flushAsynchronousOperations();
+        assert.isTrue(element.$.diffPrefsContainer.hidden);
 
-      element._loggedIn = true;
-      flushAsynchronousOperations();
-      assert.isFalse(element.$.diffPrefsContainer.hidden);
+        element._loggedIn = true;
+        flushAsynchronousOperations();
+        assert.isFalse(element.$.diffPrefsContainer.hidden);
+      });
+
+      test('when disableDiffPrefs is set', () => {
+        element._loggedIn = true;
+        element._prefs = {font_size: '12'};
+        element.disableDiffPrefs = false;
+        flushAsynchronousOperations();
+
+        assert.isFalse(element.$.diffPrefsContainer.hidden);
+        element.disableDiffPrefs = true;
+        flushAsynchronousOperations();
+
+        assert.isTrue(element.$.diffPrefsContainer.hidden);
+      });
     });
 
     test('prefsButton opens gr-diff-preferences', () => {
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 bddfc6d..e587953 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
@@ -20,7 +20,6 @@
 <link rel="import" href="../../../styles/shared-styles.html">
 <link rel="import" href="../../shared/gr-button/gr-button.html">
 <link rel="import" href="../gr-diff-builder/gr-diff-builder.html">
-<link rel="import" href="../gr-diff-comment-thread/gr-diff-comment-thread.html">
 <link rel="import" href="../gr-diff-highlight/gr-diff-highlight.html">
 <link rel="import" href="../gr-diff-selection/gr-diff-selection.html">
 <link rel="import" href="../gr-syntax-themes/gr-syntax-theme.html">
@@ -36,6 +35,11 @@
       :host(.no-left) .sideBySide ::content .right:not([data-value]) + td {
         display: none;
       }
+      .thread-group, ::slotted(*) .thread-group {
+        display: block;
+        max-width: var(--content-width, 80ch);
+        white-space: normal;
+      }
       .diffContainer {
         display: flex;
         font-family: var(--monospace-font-family);
@@ -276,10 +280,10 @@
         <gr-diff-highlight
             id="highlights"
             logged-in="[[loggedIn]]"
-            comments="{{comments}}">
+            comment-ranges="{{_commentRanges}}">
           <gr-diff-builder
               id="diffBuilder"
-              comments="[[comments]]"
+              comment-ranges="[[_commentRanges]]"
               project-name="[[projectName]]"
               diff="[[diff]]"
               diff-path="[[path]]"
@@ -289,10 +293,8 @@
               line-wrapping="[[lineWrapping]]"
               is-image-diff="[[isImageDiff]]"
               base-image="[[baseImage]]"
-              revision-image="[[revisionImage]]"
-              parent-index="[[_parentIndex]]"
-              create-comment-fn="[[_createThreadGroupFn]]"
-              line-of-interest="[[lineOfInterest]]">
+              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 3ae8806..a8cf320 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
@@ -35,10 +35,31 @@
     RIGHT: 'right',
   };
 
+  const Defs = {};
+
+  /**
+   * Special line number which should not be collapsed into a shared region.
+   *
+   * @typedef {{
+   *  number: number,
+   *  leftSide: boolean
+   * }}
+   */
+  Defs.LineOfInterest;
+
   const LARGE_DIFF_THRESHOLD_LINES = 10000;
   const FULL_CONTEXT = -1;
   const LIMITED_CONTEXT = 10;
 
+  /** @typedef {{start_line: number, start_character: number,
+   *             end_line: number, end_character: number}} */
+  Gerrit.Range;
+
+  function isThreadEl(node) {
+    return node.nodeType === Node.ELEMENT_NODE &&
+        node.classList.contains('comment-thread');
+  }
+
   Polymer({
     is: 'gr-diff',
 
@@ -53,16 +74,10 @@
      * @event show-auth-required
      */
 
-    /**
-     * Fired when a comment is saved or discarded
-     *
-     * @event diff-comments-modified
-     */
-
      /**
-      * Fired when a draft is added or edited.
+      * Fired when a comment is created
       *
-      * @event draft-interaction
+      * @event create-comment
       */
 
     properties: {
@@ -78,10 +93,6 @@
         type: Object,
         observer: '_prefsObserver',
       },
-      projectConfig: {
-        type: Object,
-        observer: '_projectConfigChanged',
-      },
       projectName: String,
       displayLine: {
         type: Boolean,
@@ -96,9 +107,10 @@
         reflectToAttribute: true,
       },
       noRenderOnPrefsChange: Boolean,
-      comments: {
-        type: Object,
-        value: {left: [], right: []},
+      /** @type {!Array<!Gerrit.HoveredRange>} */
+      _commentRanges: {
+        type: Array,
+        value: () => [],
       },
       lineWrapping: {
         type: Boolean,
@@ -111,15 +123,24 @@
         observer: '_viewModeObserver',
       },
 
-      /**
-       * Special line number which should not be collapsed into a shared region.
-       * @type {{
-       *  number: number,
-       *  leftSide: {boolean}
-       * }|null}
-       */
+       /** @type ?Defs.LineOfInterest */
       lineOfInterest: Object,
 
+      /**
+       * The key locations based on the comments and line of interests,
+       * where lines should not be collapsed.
+       *
+       * @type {{left: Object<(string|number), number>,
+       *     right: Object<(string|number), number>}}
+       */
+      _keyLocations: {
+        type: Object,
+        value: () => ({
+          left: {},
+          right: {},
+        }),
+      },
+
       loading: {
         type: Boolean,
         value: false,
@@ -176,27 +197,29 @@
         observer: '_blameChanged',
       },
 
-      _parentIndex: {
-        type: Number,
-        computed: '_computeParentIndex(patchRange.*)',
-      },
+      parentIndex: Number,
 
       _newlineWarning: {
         type: String,
         computed: '_computeNewlineWarning(diff)',
       },
 
-      /**
-       * @type {function(number, boolean, !string)}
-       */
-      _createThreadGroupFn: {
-        type: Function,
-        value() {
-          return this._createCommentThreadGroup.bind(this);
-        },
-      },
-
       _diffLength: Number,
+
+      /**
+       * Observes comment nodes added or removed after the initial render.
+       * Can be used to unregister when the entire diff is (re-)rendered or upon
+       * detachment.
+       * @type {?PolymerDomApi.ObserveHandle}
+       */
+      _incrementalNodeObserver: Object,
+
+      /**
+       * Observes comment nodes added or removed at any point.
+       * Can be used to unregister upon detachment.
+       * @type {?PolymerDomApi.ObserveHandle}
+       */
+      _nodeObserver: Object,
     },
 
     behaviors: [
@@ -204,10 +227,51 @@
     ],
 
     listeners: {
-      'comment-discard': '_handleCommentDiscard',
-      'comment-update': '_handleCommentUpdate',
-      'comment-save': '_handleCommentSave',
-      'create-comment': '_handleCreateComment',
+      'create-range-comment': '_handleCreateRangeComment',
+      'render-content': '_handleRenderContent',
+    },
+
+    attached() {
+      this._observeNodes();
+    },
+
+    detached() {
+      this._unobserveIncrementalNodes();
+      this._unobserveNodes();
+    },
+
+    _observeNodes() {
+      this._nodeObserver = Polymer.dom(this).observeNodes(info => {
+        const addedThreadEls = info.addedNodes.filter(isThreadEl);
+        // In principle we should also handle removed nodes, but I have not
+        // figured out how to do that yet without also catching all the removals
+        // caused by further redistribution. Right now, comments are never
+        // removed by no longer slotting them in, so I decided to not handle
+        // this situation until it occurs.
+        this._updateRanges(addedThreadEls);
+        this._updateKeyLocations(addedThreadEls);
+      });
+    },
+
+    _updateRanges(addedThreadEls) {
+      function commentRangeFromThreadEl(threadEl) {
+        const side = threadEl.getAttribute('comment-side');
+        const range = JSON.parse(threadEl.getAttribute('range'));
+        return {side, range, hovering: false};
+      }
+
+      const addedCommentRanges = addedThreadEls
+          .map(commentRangeFromThreadEl)
+          .filter(({range}) => range);
+      this.push('_commentRanges', ...addedCommentRanges);
+    },
+
+    _updateKeyLocations(addedThreadEls) {
+      for (const threadEl of addedThreadEls) {
+        const commentSide = threadEl.getAttribute('comment-side');
+        const lineNum = threadEl.getAttribute('line-num') || GrDiffLine.FILE;
+        this._keyLocations[commentSide][lineNum] = true;
+      }
     },
 
     /** Cancel any remaining diff builder rendering work. */
@@ -242,22 +306,6 @@
       }
     },
 
-    _handleCommentSaveOrDiscard() {
-      this.dispatchEvent(new CustomEvent('diff-comments-modified',
-          {bubbles: true}));
-    },
-
-    /** @return {!Array<!HTMLElement>} */
-    getThreadEls() {
-      let threads = [];
-      const threadGroupEls = Polymer.dom(this.root)
-          .querySelectorAll('gr-diff-comment-thread-group');
-      for (const threadGroupEl of threadGroupEls) {
-        threads = threads.concat(threadGroupEl.threadEls);
-      }
-      return threads;
-    },
-
     /** @return {string} */
     _computeContainerClass(loggedIn, viewMode, displayLine) {
       const classes = ['diffContainer'];
@@ -322,10 +370,10 @@
       this._createComment(el, lineNum);
     },
 
-    _handleCreateComment(e) {
+    _handleCreateRangeComment(e) {
       const range = e.detail.range;
       const side = e.detail.side;
-      const lineNum = range.endLine;
+      const lineNum = range.end_line;
       const lineEl = this.$.diffBuilder.getLineElByNumber(lineNum, side);
 
       if (this._isValidElForComment(lineEl)) {
@@ -359,88 +407,49 @@
 
     /**
      * @param {!Object} lineEl
-     * @param {number=} opt_lineNum
-     * @param {string=} opt_side
-     * @param {!Object=} opt_range
+     * @param {number=} lineNum
+     * @param {string=} side
+     * @param {!Object=} range
      */
-    _createComment(lineEl, opt_lineNum, opt_side, opt_range) {
-      this.dispatchEvent(new CustomEvent('draft-interaction', {bubbles: true}));
+    _createComment(lineEl, lineNum=undefined, side=undefined, range=undefined) {
       const contentText = this.$.diffBuilder.getContentByLineEl(lineEl);
       const contentEl = contentText.parentElement;
-      const side = opt_side ||
+      side = side ||
           this._getCommentSideByLineAndContent(lineEl, contentEl);
-      const patchNum = this._getPatchNumByLineAndContent(lineEl, contentEl);
+      const patchForNewThreads = this._getPatchNumByLineAndContent(
+          lineEl, contentEl);
       const isOnParent =
-        this._getIsParentCommentByLineAndContent(lineEl, contentEl);
-      const threadEl = this._getOrCreateThread(contentEl, patchNum,
-          side, isOnParent, opt_range);
-      threadEl.addOrEditDraft(opt_lineNum, opt_range);
-    },
-
-    /**
-     * Fetch the thread group at the given range, or the range-less thread
-     * on the line if no range is provided.
-     *
-     * @param {!Object} threadGroupEl
-     * @param {string} commentSide
-     * @param {!Object=} opt_range
-     * @return {!Object}
-     */
-    _getThread(threadGroupEl, commentSide, opt_range) {
-      return threadGroupEl.getThread(commentSide, opt_range);
+          this._getIsParentCommentByLineAndContent(lineEl, contentEl);
+      this.dispatchEvent(new CustomEvent('create-comment', {
+        bubbles: true,
+        detail: {
+          lineNum,
+          side,
+          patchNum: patchForNewThreads,
+          isOnParent,
+          range,
+        },
+      }));
     },
 
     _getThreadGroupForLine(contentEl) {
-      return contentEl.querySelector('gr-diff-comment-thread-group');
+      return contentEl.querySelector('.thread-group');
     },
 
     /**
-     * Gets or creates a comment thread for a specific spot on a diff.
-     * May include a range, if the comment is a range comment.
-     *
+     * Gets or creates a comment thread group for a specific line and side on a
+     * diff.
      * @param {!Object} contentEl
-     * @param {number} patchNum
-     * @param {string} commentSide
-     * @param {boolean} isOnParent
-     * @param {!Object=} opt_range
-     * @return {!Object}
+     * @return {!Node}
      */
-    _getOrCreateThread(contentEl, patchNum, commentSide,
-        isOnParent, opt_range) {
+    _getOrCreateThreadGroup(contentEl) {
       // Check if thread group exists.
       let threadGroupEl = this._getThreadGroupForLine(contentEl);
       if (!threadGroupEl) {
-        threadGroupEl = this._createCommentThreadGroup(patchNum, isOnParent,
-            commentSide);
+        threadGroupEl = document.createElement('div');
+        threadGroupEl.className = 'thread-group';
         contentEl.appendChild(threadGroupEl);
       }
-
-      let threadEl = this._getThread(threadGroupEl, commentSide, opt_range);
-
-      if (!threadEl) {
-        threadGroupEl.addNewThread(commentSide, opt_range);
-        Polymer.dom.flush();
-        threadEl = this._getThread(threadGroupEl, commentSide, opt_range);
-      }
-      return threadEl;
-    },
-
-    /**
-     * @param {number} patchNum
-     * @param {boolean} isOnParent
-     * @param {!string} commentSide
-     * @return {!Object}
-     */
-    _createCommentThreadGroup(patchNum, isOnParent, commentSide) {
-      const threadGroupEl =
-          document.createElement('gr-diff-comment-thread-group');
-      threadGroupEl.changeNum = this.changeNum;
-      threadGroupEl.commentSide = commentSide;
-      threadGroupEl.patchForNewThreads = patchNum;
-      threadGroupEl.path = this.path;
-      threadGroupEl.isOnParent = isOnParent;
-      threadGroupEl.projectName = this.projectName;
-      threadGroupEl.parentIndex = this._parentIndex;
       return threadGroupEl;
     },
 
@@ -491,75 +500,6 @@
       return side;
     },
 
-    _handleCommentDiscard(e) {
-      const comment = e.detail.comment;
-      this._removeComment(comment);
-      this._handleCommentSaveOrDiscard();
-    },
-
-    _removeComment(comment) {
-      const side = comment.__commentSide;
-      this._removeCommentFromSide(comment, side);
-    },
-
-    _handleCommentSave(e) {
-      const comment = e.detail.comment;
-      const side = e.detail.comment.__commentSide;
-      const idx = this._findDraftIndex(comment, side);
-      this.set(['comments', side, idx], comment);
-      this._handleCommentSaveOrDiscard();
-    },
-
-    /**
-     * Closure annotation for Polymer.prototype.push is off. Submitted PR:
-     * https://github.com/Polymer/polymer/pull/4776
-     * but for not supressing annotations.
-     *
-     * @suppress {checkTypes} */
-    _handleCommentUpdate(e) {
-      const comment = e.detail.comment;
-      const side = e.detail.comment.__commentSide;
-      let idx = this._findCommentIndex(comment, side);
-      if (idx === -1) {
-        idx = this._findDraftIndex(comment, side);
-      }
-      if (idx !== -1) { // Update draft or comment.
-        this.set(['comments', side, idx], comment);
-      } else { // Create new draft.
-        this.push(['comments', side], comment);
-      }
-    },
-
-    _removeCommentFromSide(comment, side) {
-      let idx = this._findCommentIndex(comment, side);
-      if (idx === -1) {
-        idx = this._findDraftIndex(comment, side);
-      }
-      if (idx !== -1) {
-        this.splice('comments.' + side, idx, 1);
-      }
-    },
-
-    /** @return {number} */
-    _findCommentIndex(comment, side) {
-      if (!comment.id || !this.comments[side]) {
-        return -1;
-      }
-      return this.comments[side].findIndex(item => {
-        return item.id === comment.id;
-      });
-    },
-
-    /** @return {number} */
-    _findDraftIndex(comment, side) {
-      if (!comment.__draftID || !this.comments[side]) {
-        return -1;
-      }
-      return this.comments[side].findIndex(item => {
-        return item.__draftID === comment.__draftID;
-      });
-    },
-
     _prefsObserver(newPrefs, oldPrefs) {
       // Scan the preference objects one level deep to see if they differ.
       let differ = !oldPrefs;
@@ -619,7 +559,7 @@
 
       this.updateStyles(stylesToUpdate);
 
-      if (this.diff && this.comments && !this.noRenderOnPrefsChange) {
+      if (this.diff && !this.noRenderOnPrefsChange) {
         this._renderDiffTable();
       }
     },
@@ -632,6 +572,7 @@
     },
 
     _renderDiffTable() {
+      this._unobserveIncrementalNodes();
       if (!this.prefs) {
         this.dispatchEvent(new CustomEvent('render', {bubbles: true}));
         return;
@@ -645,7 +586,45 @@
       }
 
       this._showWarning = false;
-      this.$.diffBuilder.render(this.comments, this._getBypassPrefs());
+
+      if (this.lineOfInterest) {
+        const side = this.lineOfInterest.leftSide ? 'left' : 'right';
+        this._keyLocations[side][this.lineOfInterest.number] = true;
+      }
+      this.$.diffBuilder.render(this._keyLocations, this._getBypassPrefs());
+    },
+
+    _handleRenderContent() {
+      this._incrementalNodeObserver = Polymer.dom(this).observeNodes(info => {
+        const addedThreadEls = info.addedNodes.filter(isThreadEl);
+        // In principle we should also handle removed nodes, but I have not
+        // figured out how to do that yet without also catching all the removals
+        // caused by further redistribution. Right now, comments are never
+        // removed by no longer slotting them in, so I decided to not handle
+        // this situation until it occurs.
+        for (const threadEl of addedThreadEls) {
+          const lineNumString = threadEl.getAttribute('line-num') || 'FILE';
+          const commentSide = threadEl.getAttribute('comment-side');
+          const lineEl = this.$.diffBuilder.getLineElByNumber(
+              lineNumString, commentSide);
+          const contentText = this.$.diffBuilder.getContentByLineEl(lineEl);
+          const contentEl = contentText.parentElement;
+          const threadGroupEl = this._getOrCreateThreadGroup(contentEl);
+          Polymer.dom(threadGroupEl).appendChild(threadEl);
+        }
+      });
+    },
+
+    _unobserveIncrementalNodes() {
+      if (this._incrementalNodeObserver) {
+        Polymer.dom(this).unobserveNodes(this._incrementalNodeObserver);
+      }
+    },
+
+    _unobserveNodes() {
+      if (this._nodeObserver) {
+        Polymer.dom(this).unobserveNodes(this._nodeObserver);
+      }
     },
 
     /**
@@ -659,16 +638,10 @@
     },
 
     clearDiffContent() {
+      this._unobserveIncrementalNodes();
       this.$.diffTable.innerHTML = null;
     },
 
-    _projectConfigChanged(projectConfig) {
-      const threadEls = this.getThreadEls();
-      for (let i = 0; i < threadEls.length; i++) {
-        threadEls[i].projectConfig = projectConfig;
-      }
-    },
-
     /** @return {!Array} */
     _computeDiffHeaderItems(diffInfoRecord) {
       const diffInfo = diffInfoRecord.base;
@@ -710,16 +683,6 @@
       return errorMessage ? 'showError' : '';
     },
 
-    /**
-     * @return {number|null}
-     */
-    _computeParentIndex(patchRangeRecord) {
-      if (!this.isMergeParent(patchRangeRecord.base.basePatchNum)) {
-        return null;
-      }
-      return this.getParentIndex(patchRangeRecord.base.basePatchNum);
-    },
-
     expandAllContext() {
       this._handleFullBypass();
     },
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html
index faf529b..99f2ded9 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html
@@ -192,118 +192,8 @@
             element.$$('.diffContainer').classList.contains('displayLine'));
       });
 
-      test('remove comment', () => {
-        element.comments = {
-          meta: {
-            changeNum: '42',
-            patchRange: {
-              basePatchNum: 'PARENT',
-              patchNum: 3,
-            },
-            path: '/path/to/foo',
-            projectConfig: {foo: 'bar'},
-          },
-          left: [
-            {id: 'bc1', side: 'PARENT', __commentSide: 'left'},
-            {id: 'bc2', side: 'PARENT', __commentSide: 'left'},
-            {id: 'bd1', __draft: true, side: 'PARENT', __commentSide: 'left'},
-            {id: 'bd2', __draft: true, side: 'PARENT', __commentSide: 'left'},
-          ],
-          right: [
-            {id: 'c1', __commentSide: 'right'},
-            {id: 'c2', __commentSide: 'right'},
-            {id: 'd1', __draft: true, __commentSide: 'right'},
-            {id: 'd2', __draft: true, __commentSide: 'right'},
-          ],
-        };
-
-        element._removeComment({});
-        // Using JSON.stringify because Safari 9.1 (11601.5.17.1) doesn’t seem
-        // to believe that one object deepEquals another even when they do :-/.
-        assert.equal(JSON.stringify(element.comments), JSON.stringify({
-          meta: {
-            changeNum: '42',
-            patchRange: {
-              basePatchNum: 'PARENT',
-              patchNum: 3,
-            },
-            path: '/path/to/foo',
-            projectConfig: {foo: 'bar'},
-          },
-          left: [
-            {id: 'bc1', side: 'PARENT', __commentSide: 'left'},
-            {id: 'bc2', side: 'PARENT', __commentSide: 'left'},
-            {id: 'bd1', __draft: true, side: 'PARENT', __commentSide: 'left'},
-            {id: 'bd2', __draft: true, side: 'PARENT', __commentSide: 'left'},
-          ],
-          right: [
-            {id: 'c1', __commentSide: 'right'},
-            {id: 'c2', __commentSide: 'right'},
-            {id: 'd1', __draft: true, __commentSide: 'right'},
-            {id: 'd2', __draft: true, __commentSide: 'right'},
-          ],
-        }));
-
-        element._removeComment({id: 'bc2', side: 'PARENT',
-          __commentSide: 'left'});
-        assert.deepEqual(element.comments, {
-          meta: {
-            changeNum: '42',
-            patchRange: {
-              basePatchNum: 'PARENT',
-              patchNum: 3,
-            },
-            path: '/path/to/foo',
-            projectConfig: {foo: 'bar'},
-          },
-          left: [
-            {id: 'bc1', side: 'PARENT', __commentSide: 'left'},
-            {id: 'bd1', __draft: true, side: 'PARENT', __commentSide: 'left'},
-            {id: 'bd2', __draft: true, side: 'PARENT', __commentSide: 'left'},
-          ],
-          right: [
-            {id: 'c1', __commentSide: 'right'},
-            {id: 'c2', __commentSide: 'right'},
-            {id: 'd1', __draft: true, __commentSide: 'right'},
-            {id: 'd2', __draft: true, __commentSide: 'right'},
-          ],
-        });
-
-        element._removeComment({id: 'd2', __commentSide: 'right'});
-        assert.deepEqual(element.comments, {
-          meta: {
-            changeNum: '42',
-            patchRange: {
-              basePatchNum: 'PARENT',
-              patchNum: 3,
-            },
-            path: '/path/to/foo',
-            projectConfig: {foo: 'bar'},
-          },
-          left: [
-            {id: 'bc1', side: 'PARENT', __commentSide: 'left'},
-            {id: 'bd1', __draft: true, side: 'PARENT', __commentSide: 'left'},
-            {id: 'bd2', __draft: true, side: 'PARENT', __commentSide: 'left'},
-          ],
-          right: [
-            {id: 'c1', __commentSide: 'right'},
-            {id: 'c2', __commentSide: 'right'},
-            {id: 'd1', __draft: true, __commentSide: 'right'},
-          ],
-        });
-      });
-
       test('thread groups', () => {
         const contentEl = document.createElement('div');
-        const commentSide = 'left';
-        const patchNum = 1;
-        const side = 'PARENT';
-        let range = {
-          startLine: 1,
-          startChar: 1,
-          endLine: 1,
-          endChar: 2,
-        };
 
         element.changeNum = 123;
         element.patchRange = {basePatchNum: 1, patchNum: 2};
@@ -311,36 +201,19 @@
 
         const mock = document.createElement('mock-diff-response');
         element.$.diffBuilder._builder = element.$.diffBuilder._getDiffBuilder(
-            mock.diffResponse, {}, {tab_size: 2, line_length: 80});
+            mock.diffResponse, {tab_size: 2, line_length: 80});
 
         // No thread groups.
         assert.isNotOk(element._getThreadGroupForLine(contentEl));
 
         // A thread group gets created.
-        assert.isOk(element._getOrCreateThread(contentEl,
-            patchNum, commentSide, side));
+        const threadGroupEl = element._getOrCreateThreadGroup(contentEl);
+        assert.isOk(threadGroupEl);
 
-        // Try to fetch a thread with a different range.
-        range = {
-          startLine: 1,
-          startChar: 1,
-          endLine: 1,
-          endChar: 3,
-        };
-
-        assert.isOk(element._getOrCreateThread(
-            contentEl, patchNum, commentSide, side, range));
         // The new thread group can be fetched.
         assert.isOk(element._getThreadGroupForLine(contentEl));
 
-        assert.equal(contentEl.querySelectorAll(
-            'gr-diff-comment-thread-group').length, 1);
-
-        const threadGroup = contentEl.querySelector(
-            'gr-diff-comment-thread-group');
-        const threadLength = Polymer.dom(threadGroup.root).
-              querySelectorAll('gr-diff-comment-thread').length;
-        assert.equal(threadLength, 2);
+        assert.equal(contentEl.querySelectorAll('.thread-group').length, 1);
       });
 
       suite('image diffs', () => {
@@ -359,7 +232,6 @@
           };
 
           element.patchRange = {basePatchNum: 'PARENT', patchNum: 1};
-          element.comments = {left: [], right: []};
           element.isImageDiff = true;
           element.prefs = {
             auto_hide_diff_table_header: true,
@@ -685,10 +557,6 @@
         const setupDiff = function() {
           const mock = document.createElement('mock-diff-response');
           element.diff = mock.diffResponse;
-          element.comments = {
-            left: [],
-            right: [],
-          };
           element.prefs = {
             context: 10,
             tab_size: 8,
@@ -787,29 +655,6 @@
             change_type: 'MODIFIED',
             content: [{skip: 66}],
           };
-          element.comments = {
-            meta: {
-              changeNum: '42',
-              patchRange: {
-                basePatchNum: 'PARENT',
-                patchNum: 3,
-              },
-              path: '/path/to/foo',
-              projectConfig: {foo: 'bar'},
-            },
-            left: [
-              {id: 'bc1', side: 'PARENT', __commentSide: 'left'},
-              {id: 'bc2', side: 'PARENT', __commentSide: 'left'},
-              {id: 'bd1', __draft: true, side: 'PARENT', __commentSide: 'left'},
-              {id: 'bd2', __draft: true, side: 'PARENT', __commentSide: 'left'},
-            ],
-            right: [
-              {id: 'c1', __commentSide: 'right'},
-              {id: 'c2', __commentSide: 'right'},
-              {id: 'd1', __draft: true, __commentSide: 'right'},
-              {id: 'd2', __draft: true, __commentSide: 'right'},
-            ],
-          };
         });
 
         test('change in preferences re-renders diff', () => {
@@ -828,86 +673,6 @@
           assert.isFalse(element._renderDiffTable.called);
         });
       });
-
-      suite('handle comment-update', () => {
-        setup(() => {
-          element.comments = {
-            meta: {
-              changeNum: '42',
-              patchRange: {
-                basePatchNum: 'PARENT',
-                patchNum: 3,
-              },
-              path: '/path/to/foo',
-              projectConfig: {foo: 'bar'},
-            },
-            left: [
-              {id: 'bc1', side: 'PARENT', __commentSide: 'left'},
-              {id: 'bc2', side: 'PARENT', __commentSide: 'left'},
-              {id: 'bd1', __draft: true, side: 'PARENT', __commentSide: 'left'},
-              {id: 'bd2', __draft: true, side: 'PARENT', __commentSide: 'left'},
-            ],
-            right: [
-              {id: 'c1', __commentSide: 'right'},
-              {id: 'c2', __commentSide: 'right'},
-              {id: 'd1', __draft: true, __commentSide: 'right'},
-              {id: 'd2', __draft: true, __commentSide: 'right'},
-            ],
-          };
-        });
-
-        test('creating a draft', () => {
-          const comment = {__draft: true, __draftID: 'tempID', side: 'PARENT',
-            __commentSide: 'left'};
-          element.fire('comment-update', {comment});
-          assert.include(element.comments.left, comment);
-        });
-
-        test('discarding a draft', () => {
-          const draftID = 'tempID';
-          const id = 'savedID';
-          const comment = {
-            __draft: true,
-            __draftID: draftID,
-            side: 'PARENT',
-            __commentSide: 'left',
-          };
-          const diffCommentsModifiedStub = sandbox.stub();
-          element.addEventListener('diff-comments-modified',
-              diffCommentsModifiedStub);
-          element.comments.left.push(comment);
-          comment.id = id;
-          element.fire('comment-discard', {comment});
-          const drafts = element.comments.left.filter(item => {
-            return item.__draftID === draftID;
-          });
-          assert.equal(drafts.length, 0);
-          assert.isTrue(diffCommentsModifiedStub.called);
-        });
-
-        test('saving a draft', () => {
-          const draftID = 'tempID';
-          const id = 'savedID';
-          const comment = {
-            __draft: true,
-            __draftID: draftID,
-            side: 'PARENT',
-            __commentSide: 'left',
-          };
-          const diffCommentsModifiedStub = sandbox.stub();
-          element.addEventListener('diff-comments-modified',
-              diffCommentsModifiedStub);
-          element.comments.left.push(comment);
-          comment.id = id;
-          element.fire('comment-save', {comment});
-          const drafts = element.comments.left.filter(item => {
-            return item.__draftID === draftID;
-          });
-          assert.equal(drafts.length, 1);
-          assert.equal(drafts[0].id, id);
-          assert.isTrue(diffCommentsModifiedStub.called);
-        });
-      });
     });
 
     suite('diff header', () => {
@@ -967,7 +732,6 @@
         const mock = document.createElement('mock-diff-response');
         sandbox.stub(element.$.diffBuilder, 'getDiffLength').returns(10000);
         element.diff = mock.diffResponse;
-        element.comments = {left: [], right: []};
         element.noRenderOnPrefsChange = true;
       });
 
@@ -1148,6 +912,57 @@
         assert.equal(element._computeNewlineWarningClass('foo', false), shown);
       });
     });
+
+    suite('key locations', () => {
+      let renderStub;
+
+      setup(() => {
+        element = fixture('basic');
+        element.prefs = {};
+        renderStub = sandbox.stub(element.$.diffBuilder, 'render');
+      });
+
+      test('lineOfInterest is a key location', () => {
+        element.lineOfInterest = {number: 789, leftSide: true};
+        element._renderDiffTable();
+        assert.isTrue(renderStub.called);
+        assert.deepEqual(renderStub.lastCall.args[0], {
+          left: {789: true},
+          right: {},
+        });
+      });
+
+      test('line comments are key locations', () => {
+        const threadEl = document.createElement('div');
+        threadEl.className = 'comment-thread';
+        threadEl.setAttribute('comment-side', 'right');
+        threadEl.setAttribute('line-num', 3);
+        Polymer.dom(element).appendChild(threadEl);
+        Polymer.dom.flush();
+
+        element._renderDiffTable();
+        assert.isTrue(renderStub.called);
+        assert.deepEqual(renderStub.lastCall.args[0], {
+          left: {},
+          right: {3: true},
+        });
+      });
+
+      test('file comments are key locations', () => {
+        const threadEl = document.createElement('div');
+        threadEl.className = 'comment-thread';
+        threadEl.setAttribute('comment-side', 'left');
+        Polymer.dom(element).appendChild(threadEl);
+        Polymer.dom.flush();
+
+        element._renderDiffTable();
+        assert.isTrue(renderStub.called);
+        assert.deepEqual(renderStub.lastCall.args[0], {
+          left: {FILE: true},
+          right: {},
+        });
+      });
+    });
   });
 
   a11ySuite('basic');
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 db14fc8..fa488f0 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
@@ -17,31 +17,34 @@
 (function() {
   'use strict';
 
-  const HOVER_PATH_PATTERN = /^comments\.(left|right)\.\#(\d+)\.__hovering$/;
-  const SPLICE_PATH_PATTERN = /^comments\.(left|right)\.splices$/;
+  const HOVER_PATH_PATTERN = /^commentRanges\.\#(\d+)\.hovering$/;
 
   const RANGE_HIGHLIGHT = 'range';
   const HOVER_HIGHLIGHT = 'rangeHighlight';
 
   const NORMALIZE_RANGE_EVENT = 'normalize-range';
 
+  /** @typedef {{side: string, range: Gerrit.Range, hovering: boolean}} */
+  Gerrit.HoveredRange;
+
   Polymer({
     is: 'gr-ranged-comment-layer',
 
     properties: {
-      comments: Object,
+      /** @type {!Array<!Gerrit.HoveredRange>} */
+      commentRanges: Array,
       _listeners: {
         type: Array,
         value() { return []; },
       },
-      _commentMap: {
+      _rangesMap: {
         type: Object,
-        value() { return {left: [], right: []}; },
+        value() { return {left: {}, right: {}}; },
       },
     },
 
     observers: [
-      '_handleCommentChange(comments.*)',
+      '_handleCommentRangesChange(commentRanges.*)',
     ],
 
     /**
@@ -93,97 +96,78 @@
     },
 
     /**
-     * Handle change in the comments by updating the comment maps and by
+     * Handle change in the ranges by updating the ranges maps and by
      * emitting appropriate update notifications.
      * @param {Object} record The change record.
      */
-    _handleCommentChange(record) {
-      if (!record.path) { return; }
+    _handleCommentRangesChange(record) {
+      if (!record) return;
 
       // If the entire set of comments was changed.
-      if (record.path === 'comments') {
-        this._commentMap.left = this._computeCommentMap(this.comments.left);
-        this._commentMap.right = this._computeCommentMap(this.comments.right);
-        return;
+      if (record.path === 'commentRanges') {
+        this._rangesMap = {left: {}, right: {}};
+        for (const {side, range, hovering} of record.value) {
+          this._updateRangesMap(
+              side, range, hovering, (forLine, start, end, hovering) => {
+                forLine.push({start, end, hovering});
+              });
+        }
       }
 
       // If the change only changed the `hovering` property of a comment.
-      let match = record.path.match(HOVER_PATH_PATTERN);
-      let side;
-
+      const match = record.path.match(HOVER_PATH_PATTERN);
       if (match) {
-        side = match[1];
-        const index = match[2];
-        const comment = this.comments[side][index];
-        if (comment && comment.range) {
-          this._commentMap[side] = this._computeCommentMap(this.comments[side]);
-          this._notifyUpdateRange(
-              comment.range.start_line, comment.range.end_line, side);
-        }
-        return;
+        const commentRangesIndex = match[1];
+        const {side, range, hovering} = this.commentRanges[commentRangesIndex];
+        this._updateRangesMap(
+            side, range, hovering, (forLine, start, end, hovering) => {
+              const index = forLine.findIndex(lineRange =>
+                  lineRange.start === start && lineRange.end === end);
+              forLine[index].hovering = hovering;
+            });
       }
 
       // If comments were spliced in or out.
-      match = record.path.match(SPLICE_PATH_PATTERN);
-      if (match) {
-        side = match[1];
-        this._commentMap[side] = this._computeCommentMap(this.comments[side]);
-        this._handleCommentSplice(record.value, side);
+      if (record.path === 'commentRanges.splices') {
+        for (const indexSplice of record.value.indexSplices) {
+          const removed = indexSplice.removed;
+          for (const {side, range, hovering} of removed) {
+            this._updateRangesMap(
+                side, range, hovering, (forLine, start, end) => {
+                  const index = forLine.findIndex(lineRange =>
+                      lineRange.start === start && lineRange.end === end);
+                  forLine.splice(index, 1);
+                });
+          }
+          const added = indexSplice.object.slice(
+              indexSplice.index, indexSplice.index + indexSplice.addedCount);
+          for (const {side, range, hovering} of added) {
+            this._updateRangesMap(
+                side, range, hovering, (forLine, start, end, hovering) => {
+                  forLine.push({start, end, hovering});
+                });
+          }
+        }
       }
     },
 
-    /**
-     * Take a list of comments and return a sparse list mapping line numbers to
-     * partial ranges. Uses an end-character-index of -1 to indicate the end of
-     * the line.
-     * @param {?} commentList The list of comments.
-     *    Getting this param to match closure requirements caused problems.
-     * @return {!Object} The sparse list.
-     */
-    _computeCommentMap(commentList) {
-      const result = {};
-      for (const comment of commentList) {
-        if (!comment.range) { continue; }
-        const range = comment.range;
-        for (let line = range.start_line; line <= range.end_line; line++) {
-          if (!result[line]) { result[line] = []; }
-          result[line].push({
-            comment,
-            start: line === range.start_line ? range.start_character : 0,
-            end: line === range.end_line ? range.end_character : -1,
-          });
-        }
+    _updateRangesMap(side, range, hovering, operation) {
+      const forSide = this._rangesMap[side] || (this._rangesMap[side] = {});
+      for (let line = range.start_line; line <= range.end_line; line++) {
+        const forLine = forSide[line] || (forSide[line] = []);
+        const start = line === range.start_line ? range.start_character : 0;
+        const end = line === range.end_line ? range.end_character : -1;
+        operation(forLine, start, end, hovering);
       }
-      return result;
-    },
-
-    /**
-     * Translate a splice record into range update notifications.
-     */
-    _handleCommentSplice(record, side) {
-      if (!record || !record.indexSplices) { return; }
-
-      for (const splice of record.indexSplices) {
-        const ranges = splice.removed.length ?
-            splice.removed.map(c => { return c.range; }) :
-            [splice.object[splice.index].range];
-        for (const range of ranges) {
-          if (!range) { continue; }
-          this._notifyUpdateRange(range.start_line, range.end_line, side);
-        }
-      }
+      this._notifyUpdateRange(range.start_line, range.end_line, side);
     },
 
     _getRangesForLine(line, side) {
       const lineNum = side === 'left' ? line.beforeNumber : line.afterNumber;
-      const ranges = this.get(['_commentMap', side, lineNum]) || [];
+      const ranges = this.get(['_rangesMap', side, lineNum]) || [];
       return ranges
           .map(range => {
-            range = {
-              start: range.start,
-              end: range.end === -1 ? line.text.length : range.end,
-              hovering: !!range.comment.__hovering,
-            };
+            range.end = range.end === -1 ? line.text.length : range.end;
 
             // Normalize invalid ranges where the start is after the end but the
             // start still makes sense. Set the end to the end of the line.
diff --git a/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer_test.html b/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer_test.html
index c541e26..c198ace 100644
--- a/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer_test.html
@@ -40,62 +40,48 @@
     let sandbox;
 
     setup(() => {
-      const initialComments = {
-        left: [
-          {
-            id: '12345',
-            line: 39,
-            message: 'range comment',
-            range: {
-              end_character: 9,
-              end_line: 39,
-              start_character: 6,
-              start_line: 36,
-            },
-          }, {
-            id: '23456',
-            line: 100,
-            message: 'non range comment',
+      const initialCommentRanges = [
+        {
+          side: 'left',
+          range: {
+            end_character: 9,
+            end_line: 39,
+            start_character: 6,
+            start_line: 36,
           },
-        ],
-        right: [
-          {
-            id: '34567',
-            line: 10,
-            message: 'range comment',
-            range: {
-              end_character: 22,
-              end_line: 12,
-              start_character: 10,
-              start_line: 10,
-            },
-          }, {
-            id: '45678',
-            line: 100,
-            message: 'single line range comment',
-            range: {
-              end_character: 15,
-              end_line: 100,
-              start_character: 5,
-              start_line: 100,
-            },
-          }, {
-            id: '8675309',
-            line: 55,
-            message: 'nonsense range',
-            range: {
-              end_character: 2,
-              end_line: 55,
-              start_character: 32,
-              start_line: 55,
-            },
+        },
+        {
+          side: 'right',
+          range: {
+            end_character: 22,
+            end_line: 12,
+            start_character: 10,
+            start_line: 10,
           },
-        ],
-      };
+        },
+        {
+          side: 'right',
+          range: {
+            end_character: 15,
+            end_line: 100,
+            start_character: 5,
+            start_line: 100,
+          },
+        },
+        {
+          side: 'right',
+          range: {
+            end_character: 2,
+            end_line: 55,
+            start_character: 32,
+            start_line: 55,
+          },
+        },
+      ];
 
       sandbox = sinon.sandbox.create();
       element = fixture('basic');
-      element.comments = initialComments;
+      element.commentRanges = initialCommentRanges;
     });
 
     teardown(() => {
@@ -149,7 +135,7 @@
       test('type=Remove has-comment hovering', () => {
         line.type = GrDiffLine.Type.REMOVE;
         line.beforeNumber = 36;
-        element.set(['comments', 'left', 0, '__hovering'], true);
+        element.set(['commentRanges', 0, 'hovering'], true);
 
         const expectedStart = 6;
         const expectedLength = line.text.length - expectedStart;
@@ -210,29 +196,18 @@
       });
     });
 
-    test('_handleCommentChange overwrite', () => {
-      const handlerSpy = sandbox.spy(element, '_handleCommentChange');
-      const mapSpy = sandbox.spy(element, '_computeCommentMap');
+    test('_handleCommentRangesChange overwrite', () => {
+      element.set('commentRanges', []);
 
-      element.set('comments', {left: [], right: []});
-
-      assert.isTrue(handlerSpy.called);
-      assert.equal(mapSpy.callCount, 2);
-
-      assert.equal(Object.keys(element._commentMap.left).length, 0);
-      assert.equal(Object.keys(element._commentMap.right).length, 0);
+      assert.equal(Object.keys(element._rangesMap.left).length, 0);
+      assert.equal(Object.keys(element._rangesMap.right).length, 0);
     });
 
-    test('_handleCommentChange hovering', () => {
-      const handlerSpy = sandbox.spy(element, '_handleCommentChange');
-      const mapSpy = sandbox.spy(element, '_computeCommentMap');
+    test('_handleCommentRangesChange hovering', () => {
       const notifyStub = sinon.stub();
       element.addListener(notifyStub);
 
-      element.set(['comments', 'right', 0, '__hovering'], true);
-
-      assert.isTrue(handlerSpy.called);
-      assert.isTrue(mapSpy.called);
+      element.set(['commentRanges', 1, 'hovering'], true);
 
       assert.isTrue(notifyStub.called);
       const lastCall = notifyStub.lastCall;
@@ -241,16 +216,11 @@
       assert.equal(lastCall.args[2], 'right');
     });
 
-    test('_handleCommentChange splice out', () => {
-      const handlerSpy = sandbox.spy(element, '_handleCommentChange');
-      const mapSpy = sandbox.spy(element, '_computeCommentMap');
+    test('_handleCommentRangesChange splice out', () => {
       const notifyStub = sinon.stub();
       element.addListener(notifyStub);
 
-      element.splice('comments.right', 0, 1);
-
-      assert.isTrue(handlerSpy.called);
-      assert.isTrue(mapSpy.called);
+      element.splice('commentRanges', 1, 1);
 
       assert.isTrue(notifyStub.called);
       const lastCall = notifyStub.lastCall;
@@ -259,16 +229,12 @@
       assert.equal(lastCall.args[2], 'right');
     });
 
-    test('_handleCommentChange splice in', () => {
-      const handlerSpy = sandbox.spy(element, '_handleCommentChange');
-      const mapSpy = sandbox.spy(element, '_computeCommentMap');
+    test('_handleCommentRangesChange splice in', () => {
       const notifyStub = sinon.stub();
       element.addListener(notifyStub);
 
-      element.splice('comments.left', element.comments.left.length, 0, {
-        id: '56123',
-        line: 250,
-        message: 'new range comment',
+      element.splice('commentRanges', 1, 0, {
+        side: 'left',
         range: {
           end_character: 15,
           end_line: 275,
@@ -277,9 +243,6 @@
         },
       });
 
-      assert.isTrue(handlerSpy.called);
-      assert.isTrue(mapSpy.called);
-
       assert.isTrue(notifyStub.called);
       const lastCall = notifyStub.lastCall;
       assert.equal(lastCall.args[0], 250);
@@ -291,48 +254,48 @@
       // There is only one ranged comment on the left, but it spans ll.36-39.
       const leftKeys = [];
       for (let i = 36; i <= 39; i++) { leftKeys.push('' + i); }
-      assert.deepEqual(Object.keys(element._commentMap.left).sort(),
+      assert.deepEqual(Object.keys(element._rangesMap.left).sort(),
           leftKeys.sort());
 
-      assert.equal(element._commentMap.left[36].length, 1);
-      assert.equal(element._commentMap.left[36][0].start, 6);
-      assert.equal(element._commentMap.left[36][0].end, -1);
+      assert.equal(element._rangesMap.left[36].length, 1);
+      assert.equal(element._rangesMap.left[36][0].start, 6);
+      assert.equal(element._rangesMap.left[36][0].end, -1);
 
-      assert.equal(element._commentMap.left[37].length, 1);
-      assert.equal(element._commentMap.left[37][0].start, 0);
-      assert.equal(element._commentMap.left[37][0].end, -1);
+      assert.equal(element._rangesMap.left[37].length, 1);
+      assert.equal(element._rangesMap.left[37][0].start, 0);
+      assert.equal(element._rangesMap.left[37][0].end, -1);
 
-      assert.equal(element._commentMap.left[38].length, 1);
-      assert.equal(element._commentMap.left[38][0].start, 0);
-      assert.equal(element._commentMap.left[38][0].end, -1);
+      assert.equal(element._rangesMap.left[38].length, 1);
+      assert.equal(element._rangesMap.left[38][0].start, 0);
+      assert.equal(element._rangesMap.left[38][0].end, -1);
 
-      assert.equal(element._commentMap.left[39].length, 1);
-      assert.equal(element._commentMap.left[39][0].start, 0);
-      assert.equal(element._commentMap.left[39][0].end, 9);
+      assert.equal(element._rangesMap.left[39].length, 1);
+      assert.equal(element._rangesMap.left[39][0].start, 0);
+      assert.equal(element._rangesMap.left[39][0].end, 9);
 
       // The right has two ranged comments, one spanning ll.10-12 and the other
       // on line 100.
       const rightKeys = [];
       for (let i = 10; i <= 12; i++) { rightKeys.push('' + i); }
       rightKeys.push('55', '100');
-      assert.deepEqual(Object.keys(element._commentMap.right).sort(),
+      assert.deepEqual(Object.keys(element._rangesMap.right).sort(),
           rightKeys.sort());
 
-      assert.equal(element._commentMap.right[10].length, 1);
-      assert.equal(element._commentMap.right[10][0].start, 10);
-      assert.equal(element._commentMap.right[10][0].end, -1);
+      assert.equal(element._rangesMap.right[10].length, 1);
+      assert.equal(element._rangesMap.right[10][0].start, 10);
+      assert.equal(element._rangesMap.right[10][0].end, -1);
 
-      assert.equal(element._commentMap.right[11].length, 1);
-      assert.equal(element._commentMap.right[11][0].start, 0);
-      assert.equal(element._commentMap.right[11][0].end, -1);
+      assert.equal(element._rangesMap.right[11].length, 1);
+      assert.equal(element._rangesMap.right[11][0].start, 0);
+      assert.equal(element._rangesMap.right[11][0].end, -1);
 
-      assert.equal(element._commentMap.right[12].length, 1);
-      assert.equal(element._commentMap.right[12][0].start, 0);
-      assert.equal(element._commentMap.right[12][0].end, 22);
+      assert.equal(element._rangesMap.right[12].length, 1);
+      assert.equal(element._rangesMap.right[12][0].start, 0);
+      assert.equal(element._rangesMap.right[12][0].end, 22);
 
-      assert.equal(element._commentMap.right[100].length, 1);
-      assert.equal(element._commentMap.right[100][0].start, 5);
-      assert.equal(element._commentMap.right[100][0].end, 15);
+      assert.equal(element._rangesMap.right[100].length, 1);
+      assert.equal(element._rangesMap.right[100][0].start, 5);
+      assert.equal(element._rangesMap.right[100][0].end, 15);
     });
 
     test('_getRangesForLine normalizes invalid ranges', () => {
diff --git a/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box.js b/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box.js
index 6349ab6..fa5c810 100644
--- a/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box.js
+++ b/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box.js
@@ -23,7 +23,7 @@
     /**
      * Fired when the comment creation action was taken (hotkey, click).
      *
-     * @event create-comment
+     * @event create-range-comment
      */
 
     properties: {
@@ -34,10 +34,10 @@
       range: {
         type: Object,
         value: {
-          startLine: NaN,
-          startChar: NaN,
-          endLine: NaN,
-          endChar: NaN,
+          start_line: NaN,
+          start_character: NaN,
+          end_line: NaN,
+          end_character: NaN,
         },
       },
       positionBelow: Boolean,
@@ -110,7 +110,7 @@
     },
 
     _fireCreateComment() {
-      this.fire('create-comment', {side: this.side, range: this.range});
+      this.fire('create-range-comment', {side: this.side, range: this.range});
     },
   });
 })();
diff --git a/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box_test.html b/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box_test.html
index 19155e4..dece366 100644
--- a/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box_test.html
@@ -89,16 +89,16 @@
     test('event fired contains playload', () => {
       const side = 'left';
       const range = {
-        startLine: 1,
-        startChar: 11,
-        endLine: 2,
-        endChar: 42,
+        start_line: 1,
+        start_character: 11,
+        end_line: 2,
+        end_character: 42,
       };
       element.side = 'left';
       element.range = range;
       MockInteractions.pressAndReleaseKeyOn(document.body, 67, null, 'c');
       assert(element.fire.calledWithExactly(
-          'create-comment',
+          'create-range-comment',
           {
             side,
             range,
diff --git a/polygerrit-ui/app/elements/gr-app-it_test.html b/polygerrit-ui/app/elements/gr-app-it_test.html
index 929156e..2601aeb 100644
--- a/polygerrit-ui/app/elements/gr-app-it_test.html
+++ b/polygerrit-ui/app/elements/gr-app-it_test.html
@@ -50,7 +50,6 @@
         getAccountCapabilities() { return Promise.resolve({}); },
         getConfig() {
           return Promise.resolve({
-            gerrit: {web_uis: ['GWT', 'POLYGERRIT']},
             plugin: {
               js_resource_paths: [],
               html_resource_paths: [
diff --git a/polygerrit-ui/app/elements/gr-app.html b/polygerrit-ui/app/elements/gr-app.html
index b34cd0a..533136c 100644
--- a/polygerrit-ui/app/elements/gr-app.html
+++ b/polygerrit-ui/app/elements/gr-app.html
@@ -220,10 +220,6 @@
         <a class="feedback"
             href$="[[_feedbackUrl]]"
             rel="noopener" target="_blank">Send feedback</a>
-        <template is="dom-if" if="[[_computeShowGwtUiLink(_serverConfig)]]">
-          |
-          <a id="gwtLink" href$="[[computeGwtUrl(_path)]]" rel="external">Switch to Old UI</a>
-        </template>
         | Press &ldquo;?&rdquo; for keyboard shortcuts
       </div>
     </footer>
diff --git a/polygerrit-ui/app/elements/gr-app.js b/polygerrit-ui/app/elements/gr-app.js
index 321dc58..f2f06d1 100644
--- a/polygerrit-ui/app/elements/gr-app.js
+++ b/polygerrit-ui/app/elements/gr-app.js
@@ -331,11 +331,6 @@
       this.$.header.unfloat();
     },
 
-    _computeShowGwtUiLink(config) {
-      return !window.DEPRECATE_GWT_UI &&
-          config.gerrit.web_uis && config.gerrit.web_uis.includes('GWT');
-    },
-
     _handlePageError(e) {
       const props = [
         '_showChangeListView',
diff --git a/polygerrit-ui/app/elements/gr-app_test.html b/polygerrit-ui/app/elements/gr-app_test.html
index 734d2fe..71ceab4 100644
--- a/polygerrit-ui/app/elements/gr-app_test.html
+++ b/polygerrit-ui/app/elements/gr-app_test.html
@@ -50,7 +50,6 @@
         getAccountCapabilities() { return Promise.resolve({}); },
         getConfig() {
           return Promise.resolve({
-            gerrit: {web_uis: ['GWT', 'POLYGERRIT']},
             plugin: {},
           });
         },
@@ -73,35 +72,6 @@
       assert.isTrue(element.$.reporting.appStarted.calledOnce);
     });
 
-    test('location change updates gwt footer', done => {
-      element._path = '/test/path';
-      flush(() => {
-        const gwtLink = element.$$('#gwtLink');
-        assert.equal(gwtLink.href, 'http://' + location.host +
-            element.getBaseUrl() + '/?polygerrit=0#/test/path');
-        done();
-      });
-    });
-
-    test('_handleLocationChange handles hashes', done => {
-      const curLocation = {
-        pathname: '/c/1/1/testfile.txt',
-        hash: '#2',
-        host: location.host,
-      };
-      element._handleLocationChange({detail: curLocation});
-
-      flush(() => {
-        const gwtLink = element.$$('#gwtLink');
-        assert.equal(
-            gwtLink.href,
-            'http://' + location.host + element.getBaseUrl() +
-            '/?polygerrit=0#/c/1/1/testfile.txt@2'
-        );
-        done();
-      });
-    });
-
     test('passes config to gr-plugin-host', () => {
       return element.$.restAPI.getConfig.lastCall.returnValue.then(config => {
         assert.deepEqual(element.$.plugins.config, config);
diff --git a/polygerrit-ui/app/embed/embed.html b/polygerrit-ui/app/embed/embed.html
index 948916f..1b2f20f 100644
--- a/polygerrit-ui/app/embed/embed.html
+++ b/polygerrit-ui/app/embed/embed.html
@@ -25,7 +25,6 @@
 <link rel="import" href="../elements/core/gr-search-bar/gr-search-bar.html">
 <link rel="import" href="../elements/diff/gr-diff-view/gr-diff-view.html">
 <link rel="import" href="../elements/change-list/gr-change-list-view/gr-change-list-view.html">
-<link rel="import" href="../elements/change-list/gr-change-list/gr-change-list.html">
-<link rel="import" href="../elements/change-list/gr-create-change-help/gr-create-change-help.html">
 <link rel="import" href="../elements/change-list/gr-dashboard-view/gr-dashboard-view.html">
+<link rel="import" href="../elements/change-list/gr-embed-dashboard/gr-embed-dashboard.html">
 <link rel="import" href="../styles/themes/app-theme.html">
diff --git a/polygerrit-ui/app/test/index.html b/polygerrit-ui/app/test/index.html
index 10d3e0d..20a4a1e 100644
--- a/polygerrit-ui/app/test/index.html
+++ b/polygerrit-ui/app/test/index.html
@@ -103,7 +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-group/gr-diff-comment-thread-group_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 --git a/resources/com/google/gerrit/server/change/ChangeMessages.properties b/resources/com/google/gerrit/server/change/ChangeMessages.properties
index b2bcde3..7c1dce3 100644
--- a/resources/com/google/gerrit/server/change/ChangeMessages.properties
+++ b/resources/com/google/gerrit/server/change/ChangeMessages.properties
@@ -1,5 +1,3 @@
-# Changes to this file should also be made in
-# gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeMessages.properties
 revertChangeDefaultMessage = Revert \"{0}\"\n\nThis reverts commit {1}.
 
 reviewerCantSeeChange = {0} does not have permission to see this change
diff --git a/tools/bzl/gwt.bzl b/tools/bzl/gwt.bzl
deleted file mode 100644
index b185214..0000000
--- a/tools/bzl/gwt.bzl
+++ /dev/null
@@ -1,312 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-load("//tools/bzl:genrule2.bzl", "genrule2")
-load("//tools/bzl:java.bzl", "java_library2")
-
-jar_filetype = [".jar"]
-
-BROWSERS = [
-    "chrome",
-    "firefox",
-    "gecko1_8",
-    "safari",
-    "msie",
-    "ie8",
-    "ie9",
-    "ie10",
-    "edge",
-]
-
-ALIASES = {
-    "chrome": "safari",
-    "firefox": "gecko1_8",
-    "msie": "ie10",
-    "edge": "gecko1_8",
-}
-
-MODULE = "com.google.gerrit.GerritGwtUI"
-
-GWT_COMPILER = "com.google.gwt.dev.Compiler"
-
-GWT_JVM_ARGS = ["-Xmx512m"]
-
-GWT_COMPILER_ARGS = [
-    "-XdisableClassMetadata",
-]
-
-GWT_COMPILER_ARGS_RELEASE_MODE = GWT_COMPILER_ARGS + [
-    "-XdisableCastChecking",
-]
-
-GWT_PLUGIN_DEPS_NEVERLINK = [
-    "//gerrit-plugin-gwtui:gwtui-api-lib-neverlink",
-    "//lib/gwt:user-neverlink",
-]
-
-GWT_PLUGIN_DEPS = [
-    "//gerrit-plugin-gwtui:gwtui-api-lib",
-]
-
-GWT_TRANSITIVE_DEPS = [
-    "//lib:jsr305",
-    "//lib/gwt:ant",
-    "//lib/gwt:colt",
-    "//lib/gwt:javax-validation",
-    "//lib/gwt:javax-validation_src",
-    "//lib/gwt:jsinterop-annotations",
-    "//lib/gwt:jsinterop-annotations_src",
-    "//lib/gwt:tapestry",
-    "//lib/gwt:w3c-css-sac",
-    "//lib/ow2:ow2-asm",
-    "//lib/ow2:ow2-asm-analysis",
-    "//lib/ow2:ow2-asm-commons",
-    "//lib/ow2:ow2-asm-tree",
-    "//lib/ow2:ow2-asm-util",
-]
-
-DEPS = GWT_TRANSITIVE_DEPS + [
-    "//java/com/google/gwtexpui/css",
-    "//lib:gwtjsonrpc",
-    "//lib/gwt:dev",
-    "//lib/jgit/org.eclipse.jgit:jgit-source",
-]
-
-USER_AGENT_XML = """<module rename-to='gerrit_ui'>
-<inherits name='%s'/>
-<set-property name='user.agent' value='%s'/>
-<set-property name='locale' value='default'/>
-</module>
-"""
-
-def gwt_module(gwt_xml = None, resources = [], srcs = [], **kwargs):
-    if gwt_xml:
-        resources = resources + [gwt_xml]
-
-    java_library2(
-        srcs = srcs,
-        resources = resources,
-        **kwargs
-    )
-
-def _gwt_user_agent_module(ctx):
-    """Generate user agent specific GWT module."""
-    if not ctx.attr.user_agent:
-        return None
-
-    ua = ctx.attr.user_agent
-    impl = ua
-    if ua in ALIASES:
-        impl = ALIASES[ua]
-
-    # intermediate artifact: user agent speific GWT xml file
-    gwt_user_agent_xml = ctx.new_file(ctx.label.name + "_gwt.xml")
-    ctx.file_action(
-        output = gwt_user_agent_xml,
-        content = USER_AGENT_XML % (MODULE, impl),
-    )
-
-    # intermediate artifact: user agent specific zip with GWT module
-    gwt_user_agent_zip = ctx.new_file(ctx.label.name + "_gwt.zip")
-    gwt = "%s_%s.gwt.xml" % (MODULE.replace(".", "/"), ua)
-    dir = gwt_user_agent_zip.path + ".dir"
-    cmd = " && ".join([
-        "p=$PWD",
-        "mkdir -p %s" % dir,
-        "cd %s" % dir,
-        "mkdir -p $(dirname %s)" % gwt,
-        "cp $p/%s %s" % (gwt_user_agent_xml.path, gwt),
-        "$p/%s cC $p/%s $(find . | sed 's|^./||')" % (ctx.executable._zip.path, gwt_user_agent_zip.path),
-    ])
-    ctx.actions.run_shell(
-        inputs = [gwt_user_agent_xml] + ctx.files._zip,
-        outputs = [gwt_user_agent_zip],
-        command = cmd,
-        mnemonic = "GenerateUserAgentGWTModule",
-    )
-
-    return struct(
-        zip = gwt_user_agent_zip,
-        module = MODULE + "_" + ua,
-    )
-
-def _gwt_binary_impl(ctx):
-    module = ctx.attr.module[0]
-    output_zip = ctx.outputs.output
-    output_dir = output_zip.path + ".gwt_output"
-    deploy_dir = output_zip.path + ".gwt_deploy"
-
-    deps = _get_transitive_closure(ctx)
-
-    paths = []
-    for dep in deps:
-        paths.append(dep.path)
-
-    gwt_user_agent_modules = []
-    ua = _gwt_user_agent_module(ctx)
-    if ua:
-        paths.append(ua.zip.path)
-        gwt_user_agent_modules.append(ua.zip)
-        module = ua.module
-
-    cmd = "%s %s -Dgwt.normalizeTimestamps=true -cp %s %s -war %s -deploy %s " % (
-        ctx.attr._jdk[java_common.JavaRuntimeInfo].java_executable_exec_path,
-        " ".join(ctx.attr.jvm_args),
-        ":".join(paths),
-        GWT_COMPILER,
-        output_dir,
-        deploy_dir,
-    )
-
-    # TODO(davido): clean up command concatenation
-    cmd += " ".join([
-        "-style %s" % ctx.attr.style,
-        "-optimize %s" % ctx.attr.optimize,
-        "-strict",
-        " ".join(ctx.attr.compiler_args),
-        module + "\n",
-        "rm -rf %s/gwt-unitCache\n" % output_dir,
-        "root=`pwd`\n",
-        "cd %s; $root/%s Cc ../%s $(find .)\n" % (
-            output_dir,
-            ctx.executable._zip.path,
-            output_zip.basename,
-        ),
-    ])
-
-    ctx.actions.run_shell(
-        inputs = list(deps) + gwt_user_agent_modules,
-        outputs = [output_zip],
-        tools = ctx.files._jdk + ctx.files._zip,
-        mnemonic = "GwtBinary",
-        progress_message = "GWT compiling " + output_zip.short_path,
-        command = "set -e\n" + cmd,
-    )
-
-def _get_transitive_closure(ctx):
-    deps = depset()
-    for dep in ctx.attr.module_deps:
-        deps += dep.java.transitive_runtime_deps
-        deps += dep.java.transitive_source_jars
-    for dep in ctx.attr.deps:
-        if hasattr(dep, "java"):
-            deps += dep.java.transitive_runtime_deps
-        elif hasattr(dep, "files"):
-            deps += dep.files
-
-    return deps
-
-gwt_binary = rule(
-    attrs = {
-        "user_agent": attr.string(),
-        "style": attr.string(default = "OBF"),
-        "optimize": attr.string(default = "9"),
-        "deps": attr.label_list(allow_files = jar_filetype),
-        "module": attr.string_list(default = [MODULE]),
-        "module_deps": attr.label_list(allow_files = jar_filetype),
-        "compiler_args": attr.string_list(),
-        "jvm_args": attr.string_list(),
-        "_jdk": attr.label(
-            default = Label("@bazel_tools//tools/jdk:current_java_runtime"),
-            cfg = "host",
-        ),
-        "_zip": attr.label(
-            default = Label("@bazel_tools//tools/zip:zipper"),
-            cfg = "host",
-            executable = True,
-            allow_single_file = True,
-        ),
-    },
-    outputs = {
-        "output": "%{name}.zip",
-    },
-    implementation = _gwt_binary_impl,
-)
-
-def gwt_genrule(suffix = ""):
-    dbg = "ui_dbg" + suffix
-    opt = "ui_opt" + suffix
-    module_dep = ":ui_module" + suffix
-    args = GWT_COMPILER_ARGS_RELEASE_MODE if suffix == "_r" else GWT_COMPILER_ARGS
-
-    genrule2(
-        name = "ui_optdbg" + suffix,
-        srcs = [
-            ":" + dbg,
-            ":" + opt,
-        ],
-        cmd = "cd $$TMP;" +
-              "unzip -q $$ROOT/$(location :%s);" % dbg +
-              "mv" +
-              " gerrit_ui/gerrit_ui.nocache.js" +
-              " gerrit_ui/dbg_gerrit_ui.nocache.js;" +
-              "unzip -qo $$ROOT/$(location :%s);" % opt +
-              "mkdir -p $$(dirname $@);" +
-              "zip -qrD $$ROOT/$@ .",
-        outs = ["ui_optdbg" + suffix + ".zip"],
-        visibility = ["//visibility:public"],
-    )
-
-    gwt_binary(
-        name = opt,
-        module = [MODULE],
-        module_deps = [module_dep],
-        deps = DEPS,
-        compiler_args = args,
-        jvm_args = GWT_JVM_ARGS,
-    )
-
-    gwt_binary(
-        name = dbg,
-        style = "PRETTY",
-        optimize = "0",
-        module_deps = [module_dep],
-        deps = DEPS,
-        compiler_args = GWT_COMPILER_ARGS,
-        jvm_args = GWT_JVM_ARGS,
-    )
-
-def gen_ui_module(name, suffix = ""):
-    gwt_module(
-        name = name + suffix,
-        srcs = native.glob(["src/main/java/**/*.java"]),
-        gwt_xml = "src/main/java/%s.gwt.xml" % MODULE.replace(".", "/"),
-        resources = native.glob(
-            ["src/main/java/**/*"],
-            exclude = ["src/main/java/**/*.java"] +
-                      ["src/main/java/%s.gwt.xml" % MODULE.replace(".", "/")],
-        ),
-        deps = [
-            "//gerrit-gwtui-common:diffy_logo",
-            "//gerrit-gwtui-common:client",
-            "//java/com/google/gwtexpui/css",
-            "//lib/codemirror:codemirror" + suffix,
-            "//lib/gwt:user",
-        ],
-        visibility = ["//visibility:public"],
-    )
-
-def gwt_user_agent_permutations():
-    for ua in BROWSERS:
-        gwt_binary(
-            name = "ui_%s" % ua,
-            user_agent = ua,
-            style = "PRETTY",
-            optimize = "0",
-            module = [MODULE],
-            module_deps = [":ui_module"],
-            deps = DEPS,
-            compiler_args = GWT_COMPILER_ARGS,
-            jvm_args = GWT_JVM_ARGS,
-        )
diff --git a/tools/bzl/junit.bzl b/tools/bzl/junit.bzl
index 08d5045..ccde467 100644
--- a/tools/bzl/junit.bzl
+++ b/tools/bzl/junit.bzl
@@ -68,7 +68,6 @@
     # Enforce JDK 8 compatibility on Java 9, see
     # https://docs.oracle.com/javase/9/intl/internationalization-enhancements-jdk-9.htm#JSINT-GUID-AF5AECA7-07C1-4E7D-BC10-BC7E73DC6C7F
     "-Djava.locale.providers=COMPAT,CLDR,SPI",
-    "--add-modules java.activation",
     "--add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED",
 ]
 
@@ -82,7 +81,7 @@
     jvm_flags = kwargs.get("jvm_flags", [])
     jvm_flags = jvm_flags + select({
         "//:java9": POST_JDK8_OPTS,
-        "//:java10": POST_JDK8_OPTS,
+        "//:java_next": POST_JDK8_OPTS,
         "//conditions:default": [],
     })
     native.java_test(
diff --git a/tools/bzl/pkg_war.bzl b/tools/bzl/pkg_war.bzl
index 40dd769..72de14b 100644
--- a/tools/bzl/pkg_war.bzl
+++ b/tools/bzl/pkg_war.bzl
@@ -133,14 +133,12 @@
     implementation = _war_impl,
 )
 
-def pkg_war(name, ui = "ui_optdbg", context = [], doc = False, **kwargs):
+def pkg_war(name, ui = "polygerrit", context = [], doc = False, **kwargs):
     doc_ctx = []
     doc_lib = []
     ui_deps = []
-    if ui == "polygerrit" or ui == "ui_optdbg" or ui == "ui_optdbg_r":
+    if ui == "polygerrit":
         ui_deps.append("//polygerrit-ui/app:polygerrit_ui")
-    if ui and ui != "polygerrit":
-        ui_deps.append("//gerrit-gwtui:%s" % ui)
     if doc:
         doc_ctx.append("//Documentation:html")
         doc_lib.append("//Documentation:index")
diff --git a/tools/bzl/plugin.bzl b/tools/bzl/plugin.bzl
index 5ae7dd9..066fe43 100644
--- a/tools/bzl/plugin.bzl
+++ b/tools/bzl/plugin.bzl
@@ -1,13 +1,4 @@
 load("//tools/bzl:genrule2.bzl", "genrule2")
-load(
-    "//tools/bzl:gwt.bzl",
-    "GWT_COMPILER_ARGS",
-    "GWT_JVM_ARGS",
-    "GWT_PLUGIN_DEPS",
-    "GWT_PLUGIN_DEPS_NEVERLINK",
-    "GWT_TRANSITIVE_DEPS",
-    "gwt_binary",
-)
 
 PLUGIN_DEPS = ["//plugins:plugin-lib"]
 
@@ -25,7 +16,6 @@
         deps = [],
         provided_deps = [],
         srcs = [],
-        gwt_module = [],
         resources = [],
         manifest_entries = [],
         dir_name = None,
@@ -35,14 +25,12 @@
         name = name + "__plugin",
         srcs = srcs,
         resources = resources,
-        deps = provided_deps + deps + GWT_PLUGIN_DEPS_NEVERLINK + PLUGIN_DEPS_NEVERLINK,
+        deps = provided_deps + deps + PLUGIN_DEPS_NEVERLINK,
         visibility = ["//visibility:public"],
         **kwargs
     )
 
     static_jars = []
-    if gwt_module:
-        static_jars = [":%s-static" % name]
 
     if not dir_name:
         dir_name = name
@@ -58,34 +46,6 @@
         **kwargs
     )
 
-    if gwt_module:
-        native.java_library(
-            name = name + "__gwt_module",
-            resources = depset(srcs + resources).to_list(),
-            runtime_deps = deps + GWT_PLUGIN_DEPS,
-            visibility = ["//visibility:public"],
-            **kwargs
-        )
-        genrule2(
-            name = "%s-static" % name,
-            cmd = " && ".join([
-                "mkdir -p $$TMP/static",
-                "unzip -qd $$TMP/static $(location %s__gwt_application)" % name,
-                "cd $$TMP",
-                "zip -qr $$ROOT/$@ .",
-            ]),
-            tools = [":%s__gwt_application" % name],
-            outs = ["%s-static.jar" % name],
-        )
-        gwt_binary(
-            name = name + "__gwt_application",
-            module = [gwt_module],
-            deps = GWT_PLUGIN_DEPS + GWT_TRANSITIVE_DEPS + ["//lib/gwt:dev"],
-            module_deps = [":%s__gwt_module" % name],
-            compiler_args = GWT_COMPILER_ARGS,
-            jvm_args = GWT_JVM_ARGS,
-        )
-
     # TODO(davido): Remove manual merge of manifest file when this feature
     # request is implemented: https://github.com/bazelbuild/bazel/issues/2009
     genrule2(
diff --git a/tools/eclipse/BUILD b/tools/eclipse/BUILD
index 0c9d023..8b03b66 100644
--- a/tools/eclipse/BUILD
+++ b/tools/eclipse/BUILD
@@ -8,28 +8,16 @@
 )
 
 TEST_DEPS = [
-    "//gerrit-gwtui:ui_tests",
     "//javatests/com/google/gerrit/elasticsearch:elasticsearch_test_utils",
     "//javatests/com/google/gerrit/server:server_tests",
 ]
 
 DEPS = [
-    "//gerrit-gwtdebug:gwtdebug",
-    "//gerrit-gwtui:ui_module",
-    "//gerrit-plugin-gwtui:gwtui-api-lib",
     "//java/com/google/gerrit/acceptance:lib",
     "//java/com/google/gerrit/server",
     "//java/com/google/gerrit/asciidoctor:asciidoc_lib",
     "//java/com/google/gerrit/asciidoctor:doc_indexer_lib",
     "//lib/auto:auto-value",
-    "//lib/gwt:ant",
-    "//lib/gwt:colt",
-    "//lib/gwt:javax-validation",
-    "//lib/gwt:javax-validation_src",
-    "//lib/gwt:jsinterop-annotations",
-    "//lib/gwt:jsinterop-annotations_src",
-    "//lib/gwt:tapestry",
-    "//lib/gwt:w3c-css-sac",
     "//lib/jetty:servlets",
     "//lib/prolog:compiler-lib",
     "//proto:reviewdb_java_proto",
@@ -50,11 +38,6 @@
 )
 
 classpath_collector(
-    name = "gwt_classpath_collect",
-    deps = ["//gerrit-gwtui:ui_module"],
-)
-
-classpath_collector(
     name = "autovalue_classpath_collect",
     deps = ["//lib/auto:auto-value"],
 )
diff --git a/tools/eclipse/gerrit_gwt_debug.launch b/tools/eclipse/gerrit_gwt_debug.launch
deleted file mode 100644
index 593837a..0000000
--- a/tools/eclipse/gerrit_gwt_debug.launch
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
-<listEntry value="/gerrit/gerrit-gwtdebug/src/main/java/com/google/gerrit/gwtdebug/GerritGwtDebugLauncher.java"/>
-</listAttribute>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
-<listEntry value="1"/>
-</listAttribute>
-<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
-<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
-</listAttribute>
-<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/>
-<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7&quot; javaProject=&quot;gerrit&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#10;"/>
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;gerrit&quot;/&gt;&#10;&lt;/runtimeClasspathEntry&gt;&#10;"/>
-</listAttribute>
-<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
-<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gerrit.gwtdebug.GerritGwtDebugLauncher"/>
-<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-strict -noprecompile -src ${resource_loc:/gerrit}/java -workDir ${resource_loc:/gerrit}/.gwt_work_dir com.google.gerrit.GerritGwtUI -src ${resource_loc:/gerrit}/gerrit-plugin-gwtui/src/main/java -- --console-log --show-stack-trace -d ${resource_loc:/gerrit}/../gerrit_testsite"/>
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="gerrit"/>
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx1024M&#10;-XX:MaxPermSize=256M&#10;-Dgerrit.disable-gwtui-recompile=true"/>
-</launchConfiguration>
diff --git a/tools/eclipse/project.py b/tools/eclipse/project.py
index ce4baf9..e9e249f 100755
--- a/tools/eclipse/project.py
+++ b/tools/eclipse/project.py
@@ -27,7 +27,6 @@
 import sys
 
 MAIN = '//tools/eclipse:classpath'
-GWT = '//gerrit-gwtui:ui_module'
 AUTO = '//lib/auto:auto-value'
 JRE = '/'.join([
     'org.eclipse.jdt.launching.JRE_CONTAINER',
@@ -37,7 +36,6 @@
 # Map of targets to corresponding classpath collector rules
 cp_targets = {
     AUTO: '//tools/eclipse:autovalue_classpath_collect',
-    GWT: '//tools/eclipse:gwt_classpath_collect',
     MAIN: '//tools/eclipse:main_classpath_collect',
 }
 
@@ -176,8 +174,6 @@
     src = set()
     lib = set()
     proto = set()
-    gwt_src = set()
-    gwt_lib = set()
     plugins = set()
 
     # Classpath entries are absolute for cross-cell support
@@ -185,10 +181,6 @@
     srcs = re.compile('(.*/external/[^/]+)/jar/(.*)[.]jar')
     for p in _query_classpath(MAIN):
         if p.endswith('-src.jar'):
-            # gwt_module() depends on -src.jar for Java to JavaScript compiles.
-            if p.startswith("external"):
-                p = path.join(ext, p)
-            gwt_lib.add(p)
             continue
 
         m = java_library.match(p)
@@ -214,11 +206,6 @@
                 p = path.join(ext, p)
             lib.add(p)
 
-    for p in _query_classpath(GWT):
-        m = java_library.match(p)
-        if m:
-            gwt_src.add(m.group(1))
-
     classpathentry('src', 'java')
     classpathentry('src', 'javatests', out='eclipse-out/test')
     classpathentry('src', 'resources')
@@ -250,7 +237,7 @@
                 if path.exists(p):
                     classpathentry('src', p, out=o)
 
-    for libs in [lib, gwt_lib]:
+    for libs in [lib]:
         for j in sorted(libs):
             s = None
             m = srcs.match(j)
@@ -263,16 +250,6 @@
             if args.plugins:
                 classpathentry('lib', j, s, exported=True)
             else:
-                # Filter out the source JARs that we pull through transitive
-                # closure of GWT plugin API (we add source directories
-                # themselves).  Exception is libEdit-src.jar, that is needed
-                # for GWT SDM to work.
-                m = java_library.match(j)
-                if m:
-                    if m.group(1).startswith("gerrit-") and \
-                       j.endswith("-src.jar") and \
-                       not j.endswith("libEdit-src.jar"):
-                        continue
                 classpathentry('lib', j, s)
 
     for p in sorted(proto):
@@ -280,11 +257,6 @@
         s = s.replace('.jar', '-src.jar')
         classpathentry('lib', p, s)
 
-    for s in sorted(gwt_src):
-        p = path.join(ROOT, s, 'src', 'main', 'java')
-        if path.exists(p):
-            classpathentry('lib', p, out='eclipse-out/gwtsrc')
-
     classpathentry('con', JRE)
     classpathentry('output', 'eclipse-out/classes')
 
@@ -326,14 +298,8 @@
     gen_factorypath(ext_location)
     gen_bazel_path(ext_location)
 
-    # TODO(davido): Remove this when GWT gone
-    gwt_working_dir = ".gwt_work_dir"
-    if not path.isdir(gwt_working_dir):
-        makedirs(path.join(ROOT, gwt_working_dir))
-
     try:
-        check_call(_build_bazel_cmd('build', MAIN, GWT,
-                                    '//java/org/eclipse/jgit:libEdit-src.jar'))
+        check_call(_build_bazel_cmd('build', MAIN))
     except CalledProcessError:
         exit(1)
 except KeyboardInterrupt:
diff --git a/tools/maven/BUILD b/tools/maven/BUILD
index 10ed27d..6cbd219 100644
--- a/tools/maven/BUILD
+++ b/tools/maven/BUILD
@@ -10,19 +10,16 @@
         "gerrit-acceptance-framework": "//java/com/google/gerrit/acceptance:libframework-lib-src.jar",
         "gerrit-extension-api": "//java/com/google/gerrit/extensions:libapi-src.jar",
         "gerrit-plugin-api": "//plugins:plugin-api-sources_deploy.jar",
-        "gerrit-plugin-gwtui": "//gerrit-plugin-gwtui:gwtui-api-source_deploy.jar",
     },
     doc = {
         "gerrit-acceptance-framework": "//java/com/google/gerrit/acceptance:framework-javadoc",
         "gerrit-extension-api": "//java/com/google/gerrit/extensions:extension-api-javadoc",
         "gerrit-plugin-api": "//plugins:plugin-api-javadoc",
-        "gerrit-plugin-gwtui": "//gerrit-plugin-gwtui:gwtui-api-javadoc",
     },
     jar = {
         "gerrit-acceptance-framework": "//java/com/google/gerrit/acceptance:framework_deploy.jar",
         "gerrit-extension-api": "//java/com/google/gerrit/extensions:extension-api_deploy.jar",
         "gerrit-plugin-api": "//plugins:plugin-api_deploy.jar",
-        "gerrit-plugin-gwtui": "//gerrit-plugin-gwtui:gwtui-api_deploy.jar",
     },
     repository = MAVEN_REPOSITORY,
     url = URL,
diff --git a/tools/maven/gerrit-acceptance-framework_pom.xml b/tools/maven/gerrit-acceptance-framework_pom.xml
index 57f0d52..75f632d 100644
--- a/tools/maven/gerrit-acceptance-framework_pom.xml
+++ b/tools/maven/gerrit-acceptance-framework_pom.xml
@@ -2,7 +2,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.gerrit</groupId>
   <artifactId>gerrit-acceptance-framework</artifactId>
-  <version>2.16.1-SNAPSHOT</version>
+  <version>3.0-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>Gerrit Code Review - Acceptance Test Framework</name>
   <description>Framework for Gerrit's acceptance tests</description>
diff --git a/tools/maven/gerrit-extension-api_pom.xml b/tools/maven/gerrit-extension-api_pom.xml
index 872b09b..cb8494b 100644
--- a/tools/maven/gerrit-extension-api_pom.xml
+++ b/tools/maven/gerrit-extension-api_pom.xml
@@ -2,7 +2,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.gerrit</groupId>
   <artifactId>gerrit-extension-api</artifactId>
-  <version>2.16.1-SNAPSHOT</version>
+  <version>3.0-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>Gerrit Code Review - Extension API</name>
   <description>API for Gerrit Extensions</description>
diff --git a/tools/maven/gerrit-plugin-api_pom.xml b/tools/maven/gerrit-plugin-api_pom.xml
index 47c2587..f58a6c7 100644
--- a/tools/maven/gerrit-plugin-api_pom.xml
+++ b/tools/maven/gerrit-plugin-api_pom.xml
@@ -2,7 +2,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.gerrit</groupId>
   <artifactId>gerrit-plugin-api</artifactId>
-  <version>2.16.1-SNAPSHOT</version>
+  <version>3.0-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>Gerrit Code Review - Plugin API</name>
   <description>API for Gerrit Plugins</description>
diff --git a/tools/maven/gerrit-plugin-gwtui_pom.xml b/tools/maven/gerrit-plugin-gwtui_pom.xml
deleted file mode 100644
index 375f5ea..0000000
--- a/tools/maven/gerrit-plugin-gwtui_pom.xml
+++ /dev/null
@@ -1,92 +0,0 @@
-<project>
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>com.google.gerrit</groupId>
-  <artifactId>gerrit-plugin-gwtui</artifactId>
-  <version>2.16.1-SNAPSHOT</version>
-  <packaging>jar</packaging>
-  <name>Gerrit Code Review - Plugin GWT UI</name>
-  <description>Common Classes for Gerrit GWT UI Plugins</description>
-  <url>https://www.gerritcodereview.com/</url>
-
-  <licenses>
-    <license>
-      <name>The Apache Software License, Version 2.0</name>
-      <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
-      <distribution>repo</distribution>
-    </license>
-  </licenses>
-
-  <scm>
-    <url>https://gerrit.googlesource.com/gerrit</url>
-    <connection>https://gerrit.googlesource.com/gerrit</connection>
-  </scm>
-
-  <developers>
-    <developer>
-      <name>Alice Kober-Sotzek</name>
-    </developer>
-    <developer>
-      <name>Andrew Bonventre</name>
-    </developer>
-    <developer>
-      <name>Becky Siegel</name>
-    </developer>
-    <developer>
-      <name>Dave Borowitz</name>
-    </developer>
-    <developer>
-      <name>David Ostrovsky</name>
-    </developer>
-    <developer>
-      <name>David Pursehouse</name>
-    </developer>
-    <developer>
-      <name>Edwin Kempin</name>
-    </developer>
-    <developer>
-      <name>Hugo Arès</name>
-    </developer>
-    <developer>
-      <name>Kasper Nilsson</name>
-    </developer>
-    <developer>
-      <name>Logan Hanks</name>
-    </developer>
-    <developer>
-      <name>Luca Milanesio</name>
-    </developer>
-    <developer>
-      <name>Marco Miller</name>
-    </developer>
-    <developer>
-      <name>Martin Fick</name>
-    </developer>
-    <developer>
-      <name>Saša Živkov</name>
-    </developer>
-    <developer>
-      <name>Shawn Pearce</name>
-    </developer>
-    <developer>
-      <name>Viktar Donich</name>
-    </developer>
-    <developer>
-      <name>Wyatt Allen</name>
-    </developer>
-  </developers>
-
-  <mailingLists>
-    <mailingList>
-      <name>Repo and Gerrit Discussion</name>
-      <post>repo-discuss@googlegroups.com</post>
-      <subscribe>https://groups.google.com/forum/#!forum/repo-discuss</subscribe>
-      <unsubscribe>https://groups.google.com/forum/#!forum/repo-discuss</unsubscribe>
-      <archive>https://groups.google.com/forum/#!forum/repo-discuss</archive>
-    </mailingList>
-  </mailingLists>
-
-  <issueManagement>
-    <url>https://bugs.chromium.org/p/gerrit/issues/list</url>
-    <system>Gerrit Issue Tracker</system>
-  </issueManagement>
-</project>
diff --git a/tools/maven/gerrit-war_pom.xml b/tools/maven/gerrit-war_pom.xml
index 53ba70d..9849237 100644
--- a/tools/maven/gerrit-war_pom.xml
+++ b/tools/maven/gerrit-war_pom.xml
@@ -2,7 +2,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.gerrit</groupId>
   <artifactId>gerrit-war</artifactId>
-  <version>2.16.1-SNAPSHOT</version>
+  <version>3.0-SNAPSHOT</version>
   <packaging>war</packaging>
   <name>Gerrit Code Review - WAR</name>
   <description>Gerrit WAR</description>
diff --git a/tools/version.py b/tools/version.py
index 4aafcb0..bb3b560 100755
--- a/tools/version.py
+++ b/tools/version.py
@@ -46,8 +46,7 @@
 src_pattern = re.compile(r'^(\s*<version>)([-.\w]+)(</version>\s*)$',
                          re.MULTILINE)
 for project in ['gerrit-acceptance-framework', 'gerrit-extension-api',
-                'gerrit-plugin-api', 'gerrit-plugin-gwtui',
-                'gerrit-war']:
+                'gerrit-plugin-api', 'gerrit-war']:
     pom = os.path.join('tools', 'maven', '%s_pom.xml' % project)
     replace_in_file(pom, src_pattern)
 
diff --git a/version.bzl b/version.bzl
index e0182e7..20fd8a7 100644
--- a/version.bzl
+++ b/version.bzl
@@ -2,4 +2,4 @@
 # Used by :api_install and :api_deploy targets
 # when talking to the destination repository.
 #
-GERRIT_VERSION = "2.16.1-SNAPSHOT"
+GERRIT_VERSION = "3.0-SNAPSHOT"