Merge changes I338df11c,I3d1bf717,Id9c8c438

* changes:
  Mark getRemoteHead as @Nullable
  Push group operations down into leaf test classes.
  Use new test API for group creation in AbstractDaemonTest
diff --git a/.gitignore b/.gitignore
index e544356..319b3cf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,3 +31,4 @@
 /test_site
 /tools/format
 /.vscode
+/.ijwb
diff --git a/BUILD b/BUILD
index d924417..a104dd5 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"],
diff --git a/Documentation/dev-bazel.txt b/Documentation/dev-bazel.txt
index a68c3ac..aa8609a 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]]
diff --git a/Documentation/replace_macros.py b/Documentation/replace_macros.py
index 6f90697..309a135 100755
--- a/Documentation/replace_macros.py
+++ b/Documentation/replace_macros.py
@@ -89,7 +89,7 @@
 </button>
 <script type="text/javascript">
 var f = function() {
-  window.location = '../#/Documentation/' +
+  window.location = '../#/Documentation/q/' +
     encodeURIComponent(document.getElementById("docSearch").value);
 }
 document.getElementById("searchBox").onclick = f;
diff --git a/WORKSPACE b/WORKSPACE
index a5dbbaf..a98c42e 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1127,6 +1127,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-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java
index c9346f4..4b84864 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java
@@ -236,7 +236,7 @@
     if (matchPrefix(QUERY, token)) {
       query(token);
 
-    } else if (matchPrefix("/Documentation/", token)) {
+    } else if (matchPrefix("/Documentation/q/", token)) {
       docSearch(token);
 
     } else if (matchPrefix("/c/", token)) {
diff --git a/java/com/google/gerrit/extensions/api/changes/ChangeApi.java b/java/com/google/gerrit/extensions/api/changes/ChangeApi.java
index dfa2128..eb27260 100644
--- a/java/com/google/gerrit/extensions/api/changes/ChangeApi.java
+++ b/java/com/google/gerrit/extensions/api/changes/ChangeApi.java
@@ -176,7 +176,7 @@
 
   /** Publishes a draft change. */
   @Deprecated
-  default void publish() throws RestApiException {
+  default void publish() {
     throw new UnsupportedOperationException("draft workflow is discontinued");
   }
 
diff --git a/java/com/google/gerrit/extensions/api/changes/RevisionApi.java b/java/com/google/gerrit/extensions/api/changes/RevisionApi.java
index 14dc589..a6df45f 100644
--- a/java/com/google/gerrit/extensions/api/changes/RevisionApi.java
+++ b/java/com/google/gerrit/extensions/api/changes/RevisionApi.java
@@ -35,7 +35,7 @@
 
 public interface RevisionApi {
   @Deprecated
-  default void delete() throws RestApiException {
+  default void delete() {
     throw new UnsupportedOperationException("draft workflow is discontinued");
   }
 
@@ -59,7 +59,7 @@
   BinaryResult submitPreview(String format) throws RestApiException;
 
   @Deprecated
-  default void publish() throws RestApiException {
+  default void publish() {
     throw new UnsupportedOperationException("draft workflow is discontinued");
   }
 
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/httpd/raw/StaticModule.java b/java/com/google/gerrit/httpd/raw/StaticModule.java
index 124ad1c..062d776 100644
--- a/java/com/google/gerrit/httpd/raw/StaticModule.java
+++ b/java/com/google/gerrit/httpd/raw/StaticModule.java
@@ -71,7 +71,15 @@
    */
   public static final ImmutableList<String> POLYGERRIT_INDEX_PATHS =
       ImmutableList.of(
-          "/", "/c/*", "/p/*", "/q/*", "/x/*", "/admin/*", "/dashboard/*", "/settings/*");
+          "/",
+          "/c/*",
+          "/p/*",
+          "/q/*",
+          "/x/*",
+          "/admin/*",
+          "/dashboard/*",
+          "/settings/*",
+          "/Documentation/q/*");
   // TODO(dborowitz): These fragments conflict with the REST API
   // namespace, so they will need to use a different path.
   // "/groups/*",
diff --git a/java/com/google/gerrit/index/project/ProjectSchemaDefinitions.java b/java/com/google/gerrit/index/project/ProjectSchemaDefinitions.java
index 6229041..cefc13c 100644
--- a/java/com/google/gerrit/index/project/ProjectSchemaDefinitions.java
+++ b/java/com/google/gerrit/index/project/ProjectSchemaDefinitions.java
@@ -38,7 +38,9 @@
 
   public static final ProjectSchemaDefinitions INSTANCE = new ProjectSchemaDefinitions();
 
+  public static final String NAME = "projects";
+
   private ProjectSchemaDefinitions() {
-    super("projects", ProjectData.class);
+    super(NAME, ProjectData.class);
   }
 }
diff --git a/java/com/google/gerrit/pgm/BUILD b/java/com/google/gerrit/pgm/BUILD
index b34aec0..0bebad4 100644
--- a/java/com/google/gerrit/pgm/BUILD
+++ b/java/com/google/gerrit/pgm/BUILD
@@ -24,6 +24,7 @@
         "//java/com/google/gerrit/httpd/auth/oauth",
         "//java/com/google/gerrit/httpd/auth/openid",
         "//java/com/google/gerrit/index",
+        "//java/com/google/gerrit/index/project",
         "//java/com/google/gerrit/launcher",
         "//java/com/google/gerrit/lifecycle",
         "//java/com/google/gerrit/lucene",
diff --git a/java/com/google/gerrit/pgm/Init.java b/java/com/google/gerrit/pgm/Init.java
index a93e64c..1739de9 100644
--- a/java/com/google/gerrit/pgm/Init.java
+++ b/java/com/google/gerrit/pgm/Init.java
@@ -14,11 +14,15 @@
 
 package com.google.gerrit.pgm;
 
+import static java.util.stream.Collectors.joining;
+
 import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Sets;
 import com.google.gerrit.common.IoUtil;
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.common.PluginData;
+import com.google.gerrit.index.project.ProjectSchemaDefinitions;
 import com.google.gerrit.pgm.init.BaseInit;
 import com.google.gerrit.pgm.init.Browser;
 import com.google.gerrit.pgm.init.InitPlugins;
@@ -55,6 +59,9 @@
   @Option(name = "--no-auto-start", usage = "Don't automatically start daemon after init")
   private boolean noAutoStart;
 
+  @Option(name = "--no-reindex", usage = "Don't automatically reindex any entities")
+  private boolean noReindex;
+
   @Option(name = "--skip-plugins", usage = "Don't install plugins")
   private boolean skipPlugins;
 
@@ -137,6 +144,7 @@
         });
     modules.add(new GerritServerConfigModule());
     Guice.createInjector(modules).injectMembers(this);
+    reindexProjects();
     start(run);
   }
 
@@ -194,7 +202,6 @@
     if (run.flags.autoStart) {
       if (HostPlatform.isWin32()) {
         System.err.println("Automatic startup not supported on Win32.");
-
       } else {
         startDaemon(run);
         if (!run.ui.isBatch()) {
@@ -249,6 +256,25 @@
     }
   }
 
+  private void reindexProjects() throws Exception {
+    if (noReindex) {
+      return;
+    }
+    // Reindex all projects, so that we bootstrap the project index for new installations
+    List<String> reindexArgs =
+        ImmutableList.of(
+            "--site-path",
+            getSitePath().toString(),
+            "--threads",
+            Integer.toString(1),
+            "--index",
+            ProjectSchemaDefinitions.NAME);
+    getConsoleUI().message("Init complete, reindexing projects with:");
+    getConsoleUI().message(" reindex " + reindexArgs.stream().collect(joining(" ")));
+    Reindex reindexPgm = new Reindex();
+    reindexPgm.main(reindexArgs.stream().toArray(String[]::new));
+  }
+
   private static boolean nullOrEmpty(List<?> list) {
     return list == null || list.isEmpty();
   }
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/javatests/com/google/gerrit/acceptance/pgm/BUILD b/javatests/com/google/gerrit/acceptance/pgm/BUILD
index a91b815..e0d2f86 100644
--- a/javatests/com/google/gerrit/acceptance/pgm/BUILD
+++ b/javatests/com/google/gerrit/acceptance/pgm/BUILD
@@ -13,6 +13,8 @@
     vm_args = ["-Xmx512m"],
     deps = [
         ":util",
+        "//java/com/google/gerrit/index",
+        "//java/com/google/gerrit/index/project",
         "//java/com/google/gerrit/server/schema",
     ],
 )
diff --git a/javatests/com/google/gerrit/acceptance/pgm/InitIT.java b/javatests/com/google/gerrit/acceptance/pgm/InitIT.java
new file mode 100644
index 0000000..a573e35
--- /dev/null
+++ b/javatests/com/google/gerrit/acceptance/pgm/InitIT.java
@@ -0,0 +1,51 @@
+// 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.acceptance.pgm;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.gerrit.acceptance.NoHttpd;
+import com.google.gerrit.acceptance.StandaloneSiteTest;
+import com.google.gerrit.index.IndexConfig;
+import com.google.gerrit.index.QueryOptions;
+import com.google.gerrit.index.project.ProjectData;
+import com.google.gerrit.index.project.ProjectIndexCollection;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.config.AllUsersName;
+import java.util.Optional;
+import org.junit.Test;
+
+@NoHttpd
+public class InitIT extends StandaloneSiteTest {
+
+  @Test
+  public void indexesAllProjectsAndAllUsers() throws Exception {
+    runGerrit("init", "-d", sitePaths.site_path.toString(), "--show-stack-trace");
+    try (ServerContext ctx = startServer()) {
+      ProjectIndexCollection projectIndex =
+          ctx.getInjector().getInstance(ProjectIndexCollection.class);
+      Project.NameKey allProjects = ctx.getInjector().getInstance(AllProjectsName.class);
+      Project.NameKey allUsers = ctx.getInjector().getInstance(AllUsersName.class);
+      QueryOptions opts =
+          QueryOptions.create(IndexConfig.createDefault(), 0, 1, ImmutableSet.of("name"));
+      Optional<ProjectData> allProjectsData = projectIndex.getSearchIndex().get(allProjects, opts);
+      assertThat(allProjectsData.isPresent()).isTrue();
+      Optional<ProjectData> allUsersData = projectIndex.getSearchIndex().get(allUsers, opts);
+      assertThat(allUsersData.isPresent()).isTrue();
+    }
+  }
+}
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/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list.js b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list.js
index f2cfe87..39f4d8d 100644
--- a/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list.js
+++ b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list.js
@@ -82,7 +82,7 @@
     ],
 
     observers: [
-      '_resultsChanged(_relatedResponse.changes, _submittedTogether, ' +
+      '_resultsChanged(_relatedResponse, _submittedTogether, ' +
           '_conflicts, _cherryPicks, _sameTopic)',
     ],
 
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 5be259c..7278c5a 100644
--- a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.html
+++ b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.html
@@ -166,6 +166,7 @@
         CHANGE: 'change',
         DASHBOARD: 'dashboard',
         DIFF: 'diff',
+        DOCUMENTATION_SEARCH: 'documentation-search',
         EDIT: 'edit',
         GROUP: 'group',
         PLUGIN_SCREEN: 'plugin-screen',
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 2ea7e37..0f2bbff 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router.js
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.js
@@ -148,6 +148,10 @@
     IMPROPERLY_ENCODED_PLUS: /^\/c\/(.+)\/\ \/(.+)$/,
 
     PLUGIN_SCREEN: /^\/x\/([\w-]+)\/([\w-]+)\/?/,
+
+    DOCUMENTATION_SEARCH_FILTER: '/Documentation/q/filter::filter',
+    DOCUMENTATION_SEARCH: /^\/Documentation\/q\/(.*)$/,
+    DOCUMENTATION: /^\/Documentation(\/)?(.+)?/,
   };
 
   /**
@@ -848,6 +852,17 @@
 
       this._mapRoute(RoutePattern.PLUGIN_SCREEN, '_handlePluginScreen');
 
+      this._mapRoute(RoutePattern.DOCUMENTATION_SEARCH_FILTER,
+          '_handleDocumentationSearchRoute');
+
+      // redirects /Documentation/q/* to /Documentation/q/filter:*
+      this._mapRoute(RoutePattern.DOCUMENTATION_SEARCH,
+          '_handleDocumentationSearchRedirectRoute');
+
+      // Makes sure /Documentation/* links work (doin't return 404)
+      this._mapRoute(RoutePattern.DOCUMENTATION,
+          '_handleDocumentationRedirectRoute');
+
       // Note: this route should appear last so it only catches URLs unmatched
       // by other patterns.
       this._mapRoute(RoutePattern.DEFAULT, '_handleDefaultRoute');
@@ -1425,6 +1440,27 @@
       this._setParams({view, plugin, screen});
     },
 
+    _handleDocumentationSearchRoute(data) {
+      this._setParams({
+        view: Gerrit.Nav.View.DOCUMENTATION_SEARCH,
+        filter: data.params.filter || null,
+      });
+    },
+
+    _handleDocumentationSearchRedirectRoute(data) {
+      this._redirect('/Documentation/q/filter:' +
+          encodeURIComponent(data.params[0]));
+    },
+
+    _handleDocumentationRedirectRoute(data) {
+      if (data.params[1]) {
+        location.reload();
+      } else {
+        // Redirect /Documentation to /Documentation/index.html
+        this._redirect('/Documentation/index.html');
+      }
+    },
+
     /**
      * Catchall route for when no other route is matched.
      */
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 7d4f9ba..b9eaa18 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
@@ -157,6 +157,9 @@
         '_handleDefaultRoute',
         '_handleChangeLegacyRoute',
         '_handleDiffLegacyRoute',
+        '_handleDocumentationRedirectRoute',
+        '_handleDocumentationSearchRoute',
+        '_handleDocumentationSearchRedirectRoute',
         '_handleLegacyLinenum',
         '_handleImproperlyEncodedPlusRoute',
         '_handlePassThroughRoute',
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 33e2a19..e26201a 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
@@ -156,10 +156,6 @@
           }
 
           this._layers = layers;
-
-          this.async(() => {
-            this._preRenderThread();
-          });
         },
 
         render(comments, prefs) {
@@ -449,25 +445,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/gr-diff.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
index 8f327aa..7f7ec72 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
@@ -35,7 +35,7 @@
       :host(.no-left) .sideBySide ::content .right:not([data-value]) + td {
         display: none;
       }
-      ::slotted(*) .thread-group {
+      .thread-group, ::slotted(*) .thread-group {
         display: block;
         max-width: var(--content-width, 80ch);
         white-space: normal;
diff --git a/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search.html b/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search.html
new file mode 100644
index 0000000..720f353
--- /dev/null
+++ b/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search.html
@@ -0,0 +1,62 @@
+<!--
+@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="../../../behaviors/base-url-behavior/base-url-behavior.html">
+<link rel="import" href="../../../behaviors/gr-list-view-behavior/gr-list-view-behavior.html">
+<link rel="import" href="../../../bower_components/iron-input/iron-input.html">
+<link rel="import" href="../../../styles/gr-table-styles.html">
+<link rel="import" href="../../../styles/shared-styles.html">
+<link rel="import" href="../../shared/gr-list-view/gr-list-view.html">
+<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
+
+<dom-module id="gr-documentation-search">
+  <template>
+    <style include="shared-styles"></style>
+    <style include="gr-table-styles"></style>
+    <gr-list-view
+        filter="[[_filter]]"
+        items=false
+        offset=0
+        loading="[[_loading]]"
+        path="[[_path]]">
+      <table id="list" class="genericList">
+        <tr class="headerRow">
+          <th class="name topHeader">Name</th>
+          <th class="name topHeader"></th>
+          <th class="name topHeader"></th>
+        </tr>
+        <tr id="loading" class$="loadingMsg [[computeLoadingClass(_loading)]]">
+          <td>Loading...</td>
+        </tr>
+        <tbody class$="[[computeLoadingClass(_loading)]]">
+          <template is="dom-repeat" items="[[_documentationSearches]]">
+            <tr class="table">
+              <td class="name">
+                <a href$="[[_computeSearchUrl(item.url)]]">[[item.title]]</a>
+              </td>
+              <td></td>
+              <td></td>
+            </tr>
+          </template>
+        </tbody>
+      </table>
+    </gr-list-view>
+    <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
+  </template>
+  <script src="gr-documentation-search.js"></script>
+</dom-module>
diff --git a/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search.js b/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search.js
new file mode 100644
index 0000000..f850b9d
--- /dev/null
+++ b/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search.js
@@ -0,0 +1,81 @@
+/**
+ * @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-documentation-search',
+
+    properties: {
+      /**
+       * URL params passed from the router.
+       */
+      params: {
+        type: Object,
+        observer: '_paramsChanged',
+      },
+
+      _path: {
+        type: String,
+        readOnly: true,
+        value: '/Documentation',
+      },
+      _documentationSearches: Array,
+
+      _loading: {
+        type: Boolean,
+        value: true,
+      },
+      _filter: {
+        type: String,
+        value: '',
+      },
+    },
+
+    behaviors: [
+      Gerrit.ListViewBehavior,
+    ],
+
+    attached() {
+      this.dispatchEvent(
+          new CustomEvent('title-change', {title: 'Documentation Search'}));
+    },
+
+    _paramsChanged(params) {
+      this._loading = true;
+      this._filter = this.getFilterValue(params);
+
+      return this._getDocumentationSearches(this._filter);
+    },
+
+    _getDocumentationSearches(filter) {
+      this._documentationSearches = [];
+      return this.$.restAPI.getDocumentationSearches(filter)
+          .then(searches => {
+            // Late response.
+            if (filter !== this._filter || !searches) { return; }
+            this._documentationSearches = searches;
+            this._loading = false;
+          });
+    },
+
+    _computeSearchUrl(url) {
+      if (!url) { return ''; }
+      return this.getBaseUrl() + '/' + url;
+    },
+  });
+})();
diff --git a/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search_test.html b/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search_test.html
new file mode 100644
index 0000000..84addb0
--- /dev/null
+++ b/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search_test.html
@@ -0,0 +1,120 @@
+<!DOCTYPE html>
+<!--
+@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.
+-->
+
+<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
+<title>gr-documentation-search</title>
+
+<script src="../../../bower_components/page/page.js"></script>
+<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"/>
+<link rel="import" href="gr-documentation-search.html">
+
+<script>void(0);</script>
+
+<test-fixture id="basic">
+  <template>
+    <gr-documentation-search></gr-documentation-search>
+  </template>
+</test-fixture>
+
+<script>
+  let counter;
+  const documentationGenerator = () => {
+    return {
+      title: `Gerrit Code Review - REST API Developers Notes${++counter}`,
+      url: 'Documentation/dev-rest-api.html',
+    };
+  };
+
+  suite('gr-documentation-search tests', () => {
+    let element;
+    let documentationSearches;
+    let sandbox;
+    let value;
+
+    setup(() => {
+      sandbox = sinon.sandbox.create();
+      sandbox.stub(page, 'show');
+      element = fixture('basic');
+      counter = 0;
+    });
+
+    teardown(() => {
+      sandbox.restore();
+    });
+
+    suite('list with searches for documentation', () => {
+      setup(done => {
+        documentationSearches = _.times(26, documentationGenerator);
+        stub('gr-rest-api-interface', {
+          getDocumentationSearches() {
+            return Promise.resolve(documentationSearches);
+          },
+        });
+        element._paramsChanged(value).then(() => { flush(done); });
+      });
+
+      test('test for test repo in the list', done => {
+        flush(() => {
+          assert.equal(element._documentationSearches[0].title,
+              'Gerrit Code Review - REST API Developers Notes1');
+          assert.equal(element._documentationSearches[0].url,
+              'Documentation/dev-rest-api.html');
+          done();
+        });
+      });
+    });
+
+    suite('filter', () => {
+      setup(() => {
+        documentationSearches = _.times(25, documentationGenerator);
+        documentationSearchesFiltered = _.times(1, documentationSearches);
+      });
+
+      test('_paramsChanged', done => {
+        sandbox.stub(element.$.restAPI, 'getDocumentationSearches', () => {
+          return Promise.resolve(documentationSearches);
+        });
+        const value = {
+          filter: 'test',
+        };
+        element._paramsChanged(value).then(() => {
+          assert.isTrue(element.$.restAPI.getDocumentationSearches.lastCall
+              .calledWithExactly('test'));
+          done();
+        });
+      });
+    });
+
+    suite('loading', () => {
+      test('correct contents are displayed', () => {
+        assert.isTrue(element._loading);
+        assert.equal(element.computeLoadingClass(element._loading), 'loading');
+        assert.equal(getComputedStyle(element.$.loading).display, 'block');
+
+        element._loading = false;
+        element._repos = _.times(25, documentationGenerator);
+
+        flushAsynchronousOperations();
+        assert.equal(element.computeLoadingClass(element._loading), '');
+        assert.equal(getComputedStyle(element.$.loading).display, 'none');
+      });
+    });
+  });
+</script>
diff --git a/polygerrit-ui/app/elements/gr-app.html b/polygerrit-ui/app/elements/gr-app.html
index 787a1c6..b34cd0a 100644
--- a/polygerrit-ui/app/elements/gr-app.html
+++ b/polygerrit-ui/app/elements/gr-app.html
@@ -48,6 +48,7 @@
 <link rel="import" href="../styles/shared-styles.html">
 <link rel="import" href="../styles/themes/app-theme.html">
 <link rel="import" href="./admin/gr-admin-view/gr-admin-view.html">
+<link rel="import" href="./documentation/gr-documentation-search/gr-documentation-search.html">
 <link rel="import" href="./change-list/gr-change-list-view/gr-change-list-view.html">
 <link rel="import" href="./change-list/gr-dashboard-view/gr-dashboard-view.html">
 <link rel="import" href="./change/gr-change-view/gr-change-view.html">
@@ -198,6 +199,11 @@
       <template is="dom-if" if="[[_showCLAView]]" restamp="true">
         <gr-cla-view></gr-cla-view>
       </template>
+      <template is="dom-if" if="[[_showDocumentationSearch]]" restamp="true">
+        <gr-documentation-search
+            params="[[params]]">
+        </gr-documentation-search>
+      </template>
       <div id="errorView" class="errorView">
         <div class="errorEmoji">[[_lastError.emoji]]</div>
         <div class="errorText">[[_lastError.text]]</div>
diff --git a/polygerrit-ui/app/elements/gr-app.js b/polygerrit-ui/app/elements/gr-app.js
index b0cc514..9c465f0 100644
--- a/polygerrit-ui/app/elements/gr-app.js
+++ b/polygerrit-ui/app/elements/gr-app.js
@@ -72,6 +72,7 @@
       _showCLAView: Boolean,
       _showEditorView: Boolean,
       _showPluginScreen: Boolean,
+      _showDocumentationSearch: Boolean,
       /** @type {?} */
       _viewState: Object,
       /** @type {?} */
@@ -315,6 +316,8 @@
       if (isPluginScreen) {
         this.async(() => this.set('_showPluginScreen', true), 1);
       }
+      this.set('_showDocumentationSearch',
+          view === Gerrit.Nav.View.DOCUMENTATION_SEARCH);
       if (this.params.justRegistered) {
         this.$.registrationOverlay.open();
         this.$.registrationDialog.loadData().then(() => {
diff --git a/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences.html b/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences.html
index 782100e..b3e6990 100644
--- a/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences.html
+++ b/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences.html
@@ -35,6 +35,7 @@
               prevent-invalid-input
               allowed-pattern="[0-9]"
               bind-value="{{editPrefs.tab_size}}"
+              on-keypress="_handleEditPrefsChanged"
               on-change="_handleEditPrefsChanged">
         </span>
       </section>
@@ -47,6 +48,7 @@
               prevent-invalid-input
               allowed-pattern="[0-9]"
               bind-value="{{editPrefs.line_length}}"
+              on-keypress="_handleEditPrefsChanged"
               on-change="_handleEditPrefsChanged">
         </span>
       </section>
@@ -59,6 +61,7 @@
               prevent-invalid-input
               allowed-pattern="[0-9]"
               bind-value="{{editPrefs.indent_unit}}"
+              on-keypress="_handleEditPrefsChanged"
               on-change="_handleEditPrefsChanged">
         </span>
       </section>
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.js b/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.js
index dcb428f..3d9d36b 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.js
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.js
@@ -229,7 +229,7 @@
       if (typeof link.url === 'undefined') {
         return '';
       }
-      if (link.target) {
+      if (link.target || !link.url.startsWith('/')) {
         return link.url;
       }
       return this._computeRelativeURL(link.url);
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown_test.html b/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown_test.html
index 456f235..7bb4dce 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown_test.html
@@ -73,6 +73,12 @@
 
     test('link URLs', () => {
       assert.equal(
+          element._computeLinkURL({url: 'http://example.com/test'}),
+          'http://example.com/test');
+      assert.equal(
+          element._computeLinkURL({url: 'https://example.com/test'}),
+          'https://example.com/test');
+      assert.equal(
           element._computeLinkURL({url: '/test'}),
           '//' + window.location.host + '/test');
       assert.equal(
diff --git a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.js b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.js
index 2fe5f7b1..40edc28 100644
--- a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.js
+++ b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.js
@@ -127,27 +127,8 @@
           this.$.restAPI.deleteVote(this.change._number, accountID, this.label)
           .then(response => {
             target.disabled = false;
-            if (!response.ok) { return response; }
-
-            const label = this.change.labels[this.label];
-            const labels = label.all || [];
-            let wasChanged = false;
-            for (let i = 0; i < labels.length; i++) {
-              if (labels[i]._account_id === accountID) {
-                for (const key in label) {
-                  if (label.hasOwnProperty(key) &&
-                      label[key]._account_id === accountID) {
-                    // Remove special label field, keeping change label values
-                    // in sync with the backend.
-                    this.change.labels[this.label][key] = null;
-                  }
-                }
-                this.change.labels[this.label].all.splice(i, 1);
-                wasChanged = true;
-                break;
-              }
-            }
-            if (wasChanged) { this.notifySplices('change.labels'); }
+            if (!response.ok) { return; }
+            Gerrit.Nav.navigateToChange(this.change);
           }).catch(err => {
             target.disabled = false;
             return;
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
index c0078e9..2a1ad9e 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
@@ -2981,6 +2981,22 @@
       });
     },
 
+    /**
+     * @param {string} filter
+     * @return {!Promise<?Object>}
+     */
+    getDocumentationSearches(filter) {
+      filter = filter.trim();
+      const encodedFilter = encodeURIComponent(filter);
+
+      // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
+      // supports it.
+      return this._fetchSharedCacheURL({
+        url: `/Documentation/?q=${encodedFilter}`,
+        anonymizedUrl: '/Documentation/?*',
+      });
+    },
+
     getMergeable(changeNum) {
       return this._getChangeURLAndFetch({
         changeNum,
diff --git a/polygerrit-ui/app/test/index.html b/polygerrit-ui/app/test/index.html
index fa44a74..20a4a1e 100644
--- a/polygerrit-ui/app/test/index.html
+++ b/polygerrit-ui/app/test/index.html
@@ -119,6 +119,7 @@
     'diff/gr-ranged-comment-layer/gr-ranged-comment-layer_test.html',
     'diff/gr-selection-action-box/gr-selection-action-box_test.html',
     'diff/gr-syntax-layer/gr-syntax-layer_test.html',
+    'documentation/gr-documentation-search/gr-documentation-search_test.html',
     'edit/gr-default-editor/gr-default-editor_test.html',
     'edit/gr-edit-controls/gr-edit-controls_test.html',
     'edit/gr-edit-file-controls/gr-edit-file-controls_test.html',
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(