Change-Id: Ib6f4fd5817fb5415cff5ea1d8c75c8c9a08d56b4 Reviewed-on: https://cl.tvl.fyi/c/depot/+/7185 Tested-by: BuildkiteCI Reviewed-by: tazjin <tazjin@tvl.su>
		
			
				
	
	
		
			215 lines
		
	
	
	
		
			8.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			215 lines
		
	
	
	
		
			8.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From f49c50ca9a84ca374b7bd91c171bbea0457f2c7a Mon Sep 17 00:00:00 2001
 | 
						|
From: Luke Granger-Brown <git@lukegb.com>
 | 
						|
Date: Thu, 2 Jul 2020 23:03:02 +0100
 | 
						|
Subject: [PATCH 3/3] Add titles to CLs over HTTP
 | 
						|
 | 
						|
---
 | 
						|
 .../gerrit/httpd/raw/IndexHtmlUtil.java       | 13 +++-
 | 
						|
 .../google/gerrit/httpd/raw/IndexServlet.java |  8 ++-
 | 
						|
 .../google/gerrit/httpd/raw/StaticModule.java |  5 +-
 | 
						|
 .../gerrit/httpd/raw/TitleComputer.java       | 67 +++++++++++++++++++
 | 
						|
 .../gerrit/httpd/raw/PolyGerritIndexHtml.soy  |  4 +-
 | 
						|
 5 files changed, 89 insertions(+), 8 deletions(-)
 | 
						|
 create mode 100644 java/com/google/gerrit/httpd/raw/TitleComputer.java
 | 
						|
 | 
						|
diff --git a/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java b/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java
 | 
						|
index 72bfe40c3b..439bd73b44 100644
 | 
						|
--- a/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java
 | 
						|
+++ b/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java
 | 
						|
@@ -41,6 +41,7 @@ import java.util.Collections;
 | 
						|
 import java.util.HashMap;
 | 
						|
 import java.util.HashSet;
 | 
						|
 import java.util.Map;
 | 
						|
+import java.util.Optional;
 | 
						|
 import java.util.Set;
 | 
						|
 import java.util.function.Function;
 | 
						|
 
 | 
						|
@@ -62,13 +63,14 @@ 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(
 | 
						|
             staticTemplateData(
 | 
						|
                 canonicalURL, cdnPath, faviconPath, urlParameterMap, urlInScriptTagOrdainer))
 | 
						|
-        .putAll(dynamicTemplateData(gerritApi, requestedURL));
 | 
						|
+        .putAll(dynamicTemplateData(gerritApi, requestedURL, titleComputer));
 | 
						|
     Set<String> enabledExperiments = new HashSet<>();
 | 
						|
     enabledExperiments.addAll(experimentFeatures.getEnabledExperimentFeatures());
 | 
						|
     // Add all experiments enabled through url
 | 
						|
@@ -81,7 +83,8 @@ public class IndexHtmlUtil {
 | 
						|
 
 | 
						|
   /** Returns dynamic parameters of {@code index.html}. */
 | 
						|
   public static ImmutableMap<String, Object> dynamicTemplateData(
 | 
						|
-      GerritApi gerritApi, String requestedURL) throws RestApiException, URISyntaxException {
 | 
						|
+      GerritApi gerritApi, String requestedURL, TitleComputer titleComputer)
 | 
						|
+                throws RestApiException, URISyntaxException {
 | 
						|
     ImmutableMap.Builder<String, Object> data = ImmutableMap.builder();
 | 
						|
     Map<String, SanitizedContent> initialData = new HashMap<>();
 | 
						|
     Server serverApi = gerritApi.config().server();
 | 
						|
@@ -129,6 +132,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 fcb821e5ae..e1464b992b 100644
 | 
						|
--- a/java/com/google/gerrit/httpd/raw/IndexServlet.java
 | 
						|
+++ b/java/com/google/gerrit/httpd/raw/IndexServlet.java
 | 
						|
@@ -48,13 +48,15 @@ public class IndexServlet extends HttpServlet {
 | 
						|
   private final ExperimentFeatures experimentFeatures;
 | 
						|
   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,
 | 
						|
-      ExperimentFeatures experimentFeatures) {
 | 
						|
+      ExperimentFeatures experimentFeatures,
 | 
						|
+      TitleComputer titleComputer) {
 | 
						|
     this.canonicalUrl = canonicalUrl;
 | 
						|
     this.cdnPath = cdnPath;
 | 
						|
     this.faviconPath = faviconPath;
 | 
						|
@@ -69,6 +71,7 @@ public class IndexServlet extends HttpServlet {
 | 
						|
         (s) ->
 | 
						|
             UnsafeSanitizedContentOrdainer.ordainAsSafe(
 | 
						|
                 s, SanitizedContent.ContentKind.TRUSTED_RESOURCE_URI);
 | 
						|
+    this.titleComputer = titleComputer;
 | 
						|
   }
 | 
						|
 
 | 
						|
   @Override
 | 
						|
@@ -86,7 +89,8 @@ public class IndexServlet extends HttpServlet {
 | 
						|
               faviconPath,
 | 
						|
               parameterMap,
 | 
						|
               urlOrdainer,
 | 
						|
-              getRequestUrl(req));
 | 
						|
+              getRequestUrl(req),
 | 
						|
+              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 15dcf42e0e..9f56bf33ce 100644
 | 
						|
--- a/java/com/google/gerrit/httpd/raw/StaticModule.java
 | 
						|
+++ b/java/com/google/gerrit/httpd/raw/StaticModule.java
 | 
						|
@@ -241,10 +241,11 @@ public class StaticModule extends ServletModule {
 | 
						|
         @CanonicalWebUrl @Nullable String canonicalUrl,
 | 
						|
         @GerritServerConfig Config cfg,
 | 
						|
         GerritApi gerritApi,
 | 
						|
-        ExperimentFeatures experimentFeatures) {
 | 
						|
+        ExperimentFeatures experimentFeatures,
 | 
						|
+        TitleComputer titleComputer) {
 | 
						|
       String cdnPath = options.devCdn().orElse(cfg.getString("gerrit", null, "cdnPath"));
 | 
						|
       String faviconPath = cfg.getString("gerrit", null, "faviconPath");
 | 
						|
-      return new IndexServlet(canonicalUrl, cdnPath, faviconPath, gerritApi, experimentFeatures);
 | 
						|
+      return new IndexServlet(canonicalUrl, cdnPath, faviconPath, gerritApi, experimentFeatures, 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..8fd2053ad0
 | 
						|
--- /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 dbfef44dfe..347ee75aab 100644
 | 
						|
--- a/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
 | 
						|
+++ b/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
 | 
						|
@@ -33,10 +33,12 @@
 | 
						|
   {@param? defaultDashboardHex: ?}
 | 
						|
   {@param? dashboardQuery: ?}
 | 
						|
   {@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}
 | 
						|
 
 | 
						|
-- 
 | 
						|
2.37.3
 | 
						|
 |