about summary refs log tree commit diff
path: root/third_party
diff options
context:
space:
mode:
authorLuke Granger-Brown <hg@lukegb.com>2020-06-14T18·38+0100
committerlukegb <lukegb@tvl.fyi>2020-06-14T20·26+0000
commit62f42300b8ba1b1af6ca0da024172df5fbe31bf2 (patch)
treed438324997f4839d415ec1639ad3c405fc1b1cd1 /third_party
parenta4b3f9af9364d6e39a0f93ddbb5135dbff056b09 (diff)
feat(gerrit): Add CL titles to title tags if accessing a CL or patchset. r/956
Fine, puck, you win.

Change-Id: I47fe8ea6662132f5c337e1e73281dbeca19a414c
Reviewed-on: https://cl.tvl.fyi/c/depot/+/321
Reviewed-by: tazjin <mail@tazj.in>
Diffstat (limited to 'third_party')
-rw-r--r--third_party/gerrit/add_titles_to_cls.patch200
-rw-r--r--third_party/gerrit/default.nix1
2 files changed, 201 insertions, 0 deletions
diff --git a/third_party/gerrit/add_titles_to_cls.patch b/third_party/gerrit/add_titles_to_cls.patch
new file mode 100644
index 000000000000..1a17e6dbb7df
--- /dev/null
+++ b/third_party/gerrit/add_titles_to_cls.patch
@@ -0,0 +1,200 @@
+diff --git a/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java b/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java
+index 41d2f83975..323567b4a4 100644
+--- a/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java
++++ b/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java
+@@ -42,6 +42,7 @@ import java.util.Arrays;
+ import java.util.Collections;
+ import java.util.HashMap;
+ import java.util.Map;
++import java.util.Optional;
+ import java.util.Set;
+ import java.util.function.Function;
+ import java.util.regex.Matcher;
+@@ -110,7 +111,8 @@ public class IndexHtmlUtil {
+       String faviconPath,
+       Map<String, String[]> urlParameterMap,
+       Function<String, SanitizedContent> urlInScriptTagOrdainer,
+-      String requestedURL)
++      String requestedURL,
++      TitleComputer titleComputer)
+       throws URISyntaxException, RestApiException {
+     ImmutableMap.Builder<String, Object> data = ImmutableMap.builder();
+     data.putAll(
+@@ -121,7 +123,7 @@ public class IndexHtmlUtil {
+                 urlParameterMap,
+                 urlInScriptTagOrdainer,
+                 requestedURL))
+-        .putAll(dynamicTemplateData(gerritApi));
++        .putAll(dynamicTemplateData(gerritApi, requestedURL, titleComputer));
+ 
+     Set<String> enabledExperiments = experimentData(urlParameterMap);
+     if (!enabledExperiments.isEmpty()) {
+@@ -131,7 +133,9 @@ public class IndexHtmlUtil {
+   }
+ 
+   /** Returns dynamic parameters of {@code index.html}. */
+-  public static ImmutableMap<String, Object> dynamicTemplateData(GerritApi gerritApi)
++  public static ImmutableMap<String, Object> dynamicTemplateData(GerritApi gerritApi,
++                                                                 String requestedURL,
++                                                                 TitleComputer titleComputer)
+       throws RestApiException {
+     ImmutableMap.Builder<String, Object> data = ImmutableMap.builder();
+     Map<String, SanitizedContent> initialData = new HashMap<>();
+@@ -159,6 +163,10 @@ public class IndexHtmlUtil {
+     }
+ 
+     data.put("gerritInitialData", initialData);
++
++    Optional<String> title = titleComputer.computeTitle(requestedURL);
++    title.ifPresent(s -> data.put("title", s));
++
+     return data.build();
+   }
+ 
+diff --git a/java/com/google/gerrit/httpd/raw/IndexServlet.java b/java/com/google/gerrit/httpd/raw/IndexServlet.java
+index 97d22701de..089ef4725f 100644
+--- a/java/com/google/gerrit/httpd/raw/IndexServlet.java
++++ b/java/com/google/gerrit/httpd/raw/IndexServlet.java
+@@ -44,12 +44,14 @@ public class IndexServlet extends HttpServlet {
+   private final GerritApi gerritApi;
+   private final SoySauce soySauce;
+   private final Function<String, SanitizedContent> urlOrdainer;
++  private TitleComputer titleComputer;
+ 
+   IndexServlet(
+       @Nullable String canonicalUrl,
+       @Nullable String cdnPath,
+       @Nullable String faviconPath,
+-      GerritApi gerritApi) {
++      GerritApi gerritApi,
++      TitleComputer titleComputer) {
+     this.canonicalUrl = canonicalUrl;
+     this.cdnPath = cdnPath;
+     this.faviconPath = faviconPath;
+@@ -63,6 +65,7 @@ public class IndexServlet extends HttpServlet {
+         (s) ->
+             UnsafeSanitizedContentOrdainer.ordainAsSafe(
+                 s, SanitizedContent.ContentKind.TRUSTED_RESOURCE_URI);
++    this.titleComputer = titleComputer;
+   }
+ 
+   @Override
+@@ -74,7 +77,7 @@ public class IndexServlet extends HttpServlet {
+       // TODO(hiesel): Remove URL ordainer as parameter once Soy is consistent
+       ImmutableMap<String, Object> templateData =
+           IndexHtmlUtil.templateData(
+-              gerritApi, canonicalUrl, cdnPath, faviconPath, parameterMap, urlOrdainer, requestUrl);
++              gerritApi, canonicalUrl, cdnPath, faviconPath, parameterMap, urlOrdainer, requestUrl, titleComputer);
+       renderer = soySauce.renderTemplate("com.google.gerrit.httpd.raw.Index").setData(templateData);
+     } catch (URISyntaxException | RestApiException e) {
+       throw new IOException(e);
+diff --git a/java/com/google/gerrit/httpd/raw/StaticModule.java b/java/com/google/gerrit/httpd/raw/StaticModule.java
+index 414a120194..e1b6fb082d 100644
+--- a/java/com/google/gerrit/httpd/raw/StaticModule.java
++++ b/java/com/google/gerrit/httpd/raw/StaticModule.java
+@@ -220,11 +220,12 @@ public class StaticModule extends ServletModule {
+     HttpServlet getPolyGerritUiIndexServlet(
+         @CanonicalWebUrl @Nullable String canonicalUrl,
+         @GerritServerConfig Config cfg,
+-        GerritApi gerritApi) {
++        GerritApi gerritApi,
++        TitleComputer titleComputer) {
+       String cdnPath =
+           options.useDevCdn() ? options.devCdn() : cfg.getString("gerrit", null, "cdnPath");
+       String faviconPath = cfg.getString("gerrit", null, "faviconPath");
+-      return new IndexServlet(canonicalUrl, cdnPath, faviconPath, gerritApi);
++      return new IndexServlet(canonicalUrl, cdnPath, faviconPath, gerritApi, titleComputer);
+     }
+ 
+     @Provides
+diff --git a/java/com/google/gerrit/httpd/raw/TitleComputer.java b/java/com/google/gerrit/httpd/raw/TitleComputer.java
+new file mode 100644
+index 0000000000..efee24607c
+--- /dev/null
++++ b/java/com/google/gerrit/httpd/raw/TitleComputer.java
+@@ -0,0 +1,67 @@
++package com.google.gerrit.httpd.raw;
++
++import com.google.common.flogger.FluentLogger;
++import com.google.gerrit.entities.Change;
++import com.google.gerrit.extensions.restapi.ResourceConflictException;
++import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
++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.inject.Inject;
++import com.google.inject.Provider;
++import com.google.inject.Singleton;
++
++import java.net.MalformedURLException;
++import java.net.URL;
++import java.util.Optional;
++import java.util.regex.Matcher;
++import java.util.regex.Pattern;
++
++@Singleton
++public class TitleComputer {
++  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
++
++  @Inject
++  public TitleComputer(Provider<ChangesCollection> changes) {
++    this.changes = changes;
++  }
++
++  public Optional<String> computeTitle(String requestedURI) {
++    URL url = null;
++    try {
++      url = new URL(requestedURI);
++    } catch (MalformedURLException e) {
++      logger.atWarning().log("Failed to turn %s into a URL.", requestedURI);
++      return Optional.empty();
++    }
++
++    // Try to turn this into a change.
++    Optional<Change.Id> changeId = tryExtractChange(url.getPath());
++    if (changeId.isPresent()) {
++      return titleFromChangeId(changeId.get());
++    }
++
++    return Optional.empty();
++  }
++
++  private static final Pattern extractChangeIdRegex = Pattern.compile("^/(?:c/.*/\\+/)?(?<changeId>[0-9]+)(?:/[0-9]+)?$");
++  private final Provider<ChangesCollection> changes;
++
++  private Optional<Change.Id> tryExtractChange(String path) {
++    Matcher m = extractChangeIdRegex.matcher(path);
++    if (!m.matches()) {
++      return Optional.empty();
++    }
++    return Change.Id.tryParse(m.group("changeId"));
++  }
++
++  private Optional<String> titleFromChangeId(Change.Id changeId) {
++    ChangesCollection changesCollection = changes.get();
++    try {
++      ChangeResource changeResource = changesCollection.parse(changeId);
++      return Optional.of(changeResource.getChange().getSubject());
++    } catch (ResourceConflictException | ResourceNotFoundException | PermissionBackendException e) {
++      return Optional.empty();
++    }
++  }
++}
+diff --git a/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy b/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
+index d162714399..0ba228ad00 100644
+--- a/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
++++ b/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
+@@ -33,10 +33,12 @@
+   {@param? preloadChangePage: ?}
+   {@param? preloadDiffPage: ?}
+   {@param? userIsAuthenticated: ?}
++  {@param? title: ?}
+   <!DOCTYPE html>{\n}
+   <html lang="en">{\n}
+   <meta charset="utf-8">{\n}
+-  <meta name="description" content="Gerrit Code Review">{\n}
++  {if $title}<title>{$title} · Gerrit Code Review</title>{\n}{/if}
++  <meta name="description" content="{if $title}{$title} · {/if}Gerrit Code Review">{\n}
+   <meta name="referrer" content="never">{\n}
+   <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">{\n}
+ 
diff --git a/third_party/gerrit/default.nix b/third_party/gerrit/default.nix
index 98373582b049..d5350d3ed825 100644
--- a/third_party/gerrit/default.nix
+++ b/third_party/gerrit/default.nix
@@ -43,6 +43,7 @@ pkgs.buildBazelPackage {
     ./use_detzip.patch
     ./syntax_highlight_nix.patch
     ./syntax_highlight_rules_pl.patch
+    ./add_titles_to_cls.patch
   ];
 
   bazelTarget = "release";