Add thumbnail_aspect_ratio variation flags

This CL adopts the aspect ratio from Finch to thumbnail size. If the
JPEG has different aspect ratio, regenerate the JPEG file from the ETC1
file.

Integration with tab_grid_layout_android_new_tab_tile variation is also
added.

Everything introduced in this CL is gated by field trail under the
enable-tab-grid-layout flag. And most of the Java part is verified to be
behind the gating functions
FeatureUtilities.isTabThumbnailAspectRatioNotOne() and
FeatureUtilities.isAllowToRefetchTabThumbnail() by formal equivalence
checking tool here: http://crrev.com/c/1934235. Note: the tool does not
support native yet.

[email protected]

This is based on http://crrev.com/c/1990214/14.

Bug: 1041536
Change-Id: I5db65a72b7c56a4546491a13d43872b46ee6e55b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2003825
Commit-Queue: Wei-Yin Chen (陳威尹) <[email protected]>
Reviewed-by: Wei-Yin Chen (陳威尹) <[email protected]>
Cr-Commit-Position: refs/heads/master@{#732324}
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index d005c70c..fb2eedd 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1206,17 +1206,49 @@
 };
 
 const FeatureEntry::FeatureParam kTabGridLayoutAndroid_NewTabVariation[] = {
-    {"tab_grid_layout_android_new_tab", "NewTabVariation"}};
+    {"tab_grid_layout_android_new_tab", "NewTabVariation"},
+    {"allow_to_refetch", "true"}};
 
 const FeatureEntry::FeatureParam kTabGridLayoutAndroid_NewTabTile[] = {
     {"tab_grid_layout_android_new_tab_tile", "NewTabTile"}};
 
+const FeatureEntry::FeatureParam
+    kTabGridLayoutAndroid_ThumbnailAspectRatio_2[] = {
+        {"thumbnail_aspect_ratio", "2.0"},
+        {"allow_to_refetch", "true"}};
+
+const FeatureEntry::FeatureParam
+    kTabGridLayoutAndroid_ThumbnailAspectRatio_three_quarter[] = {
+        {"thumbnail_aspect_ratio", "0.75"},
+        {"allow_to_refetch", "true"}};
+
+const FeatureEntry::FeatureParam
+    kTabGridLayoutAndroid_ThumbnailAspectRatio_half[] = {
+        {"thumbnail_aspect_ratio", "0.5"},
+        {"allow_to_refetch", "true"}};
+
+const FeatureEntry::FeatureParam kTabGridLayoutAndroid_DisableRefetch[] = {
+    {"allow_to_refetch", "false"}};
+
 const FeatureEntry::FeatureVariation kTabGridLayoutAndroidVariations[] = {
     {"New Tab Variation", kTabGridLayoutAndroid_NewTabVariation,
      base::size(kTabGridLayoutAndroid_NewTabVariation), nullptr},
     {"New Tab Tile", kTabGridLayoutAndroid_NewTabTile,
      base::size(kTabGridLayoutAndroid_NewTabTile), nullptr},
+    {"thumbnail aspect ratio - 2:1",
+     kTabGridLayoutAndroid_ThumbnailAspectRatio_2,
+     base::size(kTabGridLayoutAndroid_ThumbnailAspectRatio_2), nullptr},
+    {"thumbnail aspect ratio - 1:2",
+     kTabGridLayoutAndroid_ThumbnailAspectRatio_half,
+     base::size(kTabGridLayoutAndroid_ThumbnailAspectRatio_half), nullptr},
+    {"thumbnail aspect ratio - 3:4",
+     kTabGridLayoutAndroid_ThumbnailAspectRatio_three_quarter,
+     base::size(kTabGridLayoutAndroid_ThumbnailAspectRatio_three_quarter),
+     nullptr},
+    {"Disable refetch", kTabGridLayoutAndroid_DisableRefetch,
+     base::size(kTabGridLayoutAndroid_DisableRefetch), nullptr},
 };
+
 const FeatureEntry::FeatureParam kStartSurfaceAndroid_SingleSurface[] = {
     {"start_surface_variation", "single"}};
 
diff --git a/chrome/browser/android/compositor/tab_content_manager.cc b/chrome/browser/android/compositor/tab_content_manager.cc
index 75ef317..878e6b3 100644
--- a/chrome/browser/android/compositor/tab_content_manager.cc
+++ b/chrome/browser/android/compositor/tab_content_manager.cc
@@ -7,6 +7,7 @@
 #include <android/bitmap.h>
 #include <stddef.h>
 
+#include <algorithm>
 #include <memory>
 #include <utility>
 
@@ -17,8 +18,10 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/macros.h"
+#include "base/metrics/field_trial_params.h"
 #include "cc/layers/layer.h"
 #include "chrome/android/chrome_jni_headers/TabContentManager_jni.h"
+#include "chrome/browser/android/chrome_feature_list.h"
 #include "chrome/browser/android/compositor/layer/thumbnail_layer.h"
 #include "chrome/browser/android/tab_android.h"
 #include "chrome/browser/android/thumbnail/thumbnail.h"
@@ -51,7 +54,7 @@
  public:
   TabReadbackRequest(content::RenderWidgetHostView* rwhv,
                      float thumbnail_scale,
-                     bool crop_to_square,
+                     bool crop_to_match_aspect_ratio,
                      TabReadbackCallback end_callback)
       : thumbnail_scale_(thumbnail_scale),
         end_callback_(std::move(end_callback)),
@@ -67,9 +70,14 @@
       std::move(result_callback).Run(SkBitmap());
       return;
     }
-    if (crop_to_square) {
-      view_size_in_pixels.set_height(
-          std::min(view_size_in_pixels.height(), view_size_in_pixels.width()));
+    if (crop_to_match_aspect_ratio) {
+      double aspect_ratio = base::GetFieldTrialParamByFeatureAsDouble(
+          chrome::android::kTabGridLayoutAndroid, "thumbnail_aspect_ratio",
+          1.0);
+      aspect_ratio = ThumbnailCache::clampAspectRatio(aspect_ratio, 0.5, 2.0);
+      int height = std::min(view_size_in_pixels.height(),
+                            (int)(view_size_in_pixels.width() / aspect_ratio));
+      view_size_in_pixels.set_height(height);
     }
     gfx::Rect source_rect = gfx::Rect(view_size_in_pixels);
     gfx::Size thumbnail_size(
@@ -392,8 +400,13 @@
     // It's fine to horizontally center-align thumbnail saved in landscape
     // mode.
     int scale = need_downsampling ? 2 : 1;
-    SkIRect dest_subset = {0, 0, bitmap.width() / scale,
-                           std::min(bitmap.width(), bitmap.height()) / scale};
+    double aspect_ratio = base::GetFieldTrialParamByFeatureAsDouble(
+        chrome::android::kTabGridLayoutAndroid, "thumbnail_aspect_ratio", 1.0);
+    aspect_ratio = ThumbnailCache::clampAspectRatio(aspect_ratio, 0.5, 2.0);
+    SkIRect dest_subset = {
+        0, 0, bitmap.width() / scale,
+        std::min(bitmap.height() / scale,
+                 (int)(bitmap.width() / aspect_ratio / scale))};
     SkBitmap result_bitmap = skia::ImageOperations::Resize(
         bitmap, skia::ImageOperations::RESIZE_BETTER, bitmap.width() / scale,
         bitmap.height() / scale, dest_subset);
diff --git a/chrome/browser/android/thumbnail/thumbnail_cache.cc b/chrome/browser/android/thumbnail/thumbnail_cache.cc
index 683e93a..2c13982 100644
--- a/chrome/browser/android/thumbnail/thumbnail_cache.cc
+++ b/chrome/browser/android/thumbnail/thumbnail_cache.cc
@@ -14,11 +14,13 @@
 #include "base/files/file.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
+#include "base/metrics/field_trial_params.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/task/post_task.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "chrome/browser/android/chrome_feature_list.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "gpu/config/gpu_finch_features.h"
@@ -268,6 +270,10 @@
   return GetFilePath(tab_id).AddExtension(".jpeg");
 }
 
+double ThumbnailCache::clampAspectRatio(double value, double min, double max) {
+  return std::max(std::min(value, max), min);
+}
+
 bool ThumbnailCache::CheckAndUpdateThumbnailMetaData(TabId tab_id,
                                                      const GURL& url) {
   base::Time current_time = base::Time::Now();
@@ -719,8 +725,13 @@
   // It's fine to horizontally center-align thumbnail saved in landscape
   // mode.
   int scale = 2;
-  SkIRect dest_subset = {0, 0, bitmap.width() / scale,
-                         std::min(bitmap.width(), bitmap.height()) / scale};
+  double aspect_ratio = base::GetFieldTrialParamByFeatureAsDouble(
+      chrome::android::kTabGridLayoutAndroid, "thumbnail_aspect_ratio", 1.0);
+  aspect_ratio = clampAspectRatio(aspect_ratio, 0.5, 2.0);
+  SkIRect dest_subset = {
+      0, 0, bitmap.width() / scale,
+      std::min(bitmap.height() / scale,
+               (int)(bitmap.width() / scale / aspect_ratio))};
   SkBitmap result_bitmap = skia::ImageOperations::Resize(
       bitmap, skia::ImageOperations::RESIZE_BETTER, bitmap.width() / scale,
       bitmap.height() / scale, dest_subset);
diff --git a/chrome/browser/android/thumbnail/thumbnail_cache.h b/chrome/browser/android/thumbnail/thumbnail_cache.h
index 5c12260..343c2d9 100644
--- a/chrome/browser/android/thumbnail/thumbnail_cache.h
+++ b/chrome/browser/android/thumbnail/thumbnail_cache.h
@@ -81,6 +81,7 @@
   static base::FilePath GetCacheDirectory();
   static base::FilePath GetFilePath(TabId tab_id);
   static base::FilePath GetJpegFilePath(TabId tab_id);
+  static double clampAspectRatio(double value, double min, double max);
 
  private:
   class ThumbnailMetaData {