Fetch splash image earlier during web app installs.

This changes ShortcutHelper to download the splash image for a webapp
while the webapp is being installed, rather than after. If the splash
image is downloaded before the webapp installation process finishes,
the splash image will be stored in a local map until it can be
transferred to the WebappDataStorage object.

This simplifies the code and fixes a potential UAF.

Bug: 1147913
Change-Id: I9405ee9cc304eaf8b9ff2bbaca17c1c63cfd6e65
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2533031
Commit-Queue: Evan Stade <[email protected]>
Reviewed-by: Dominick Ng <[email protected]>
Cr-Commit-Position: refs/heads/master@{#826837}
diff --git a/chrome/browser/android/shortcut_helper.cc b/chrome/browser/android/shortcut_helper.cc
index b0a680f..768e612 100644
--- a/chrome/browser/android/shortcut_helper.cc
+++ b/chrome/browser/android/shortcut_helper.cc
@@ -74,15 +74,11 @@
 }
 
 // Adds a shortcut which opens in a fullscreen window to the launcher.
-// |splash_image_callback| will be invoked once the Java-side operation has
-// completed. This is necessary as Java will asynchronously create and
-// populate a WebappDataStorage object for standalone-capable sites. This must
-// exist before the splash image can be stored.
-void AddWebappWithSkBitmap(const ShortcutInfo& info,
+void AddWebappWithSkBitmap(content::WebContents* web_contents,
+                           const ShortcutInfo& info,
                            const std::string& webapp_id,
                            const SkBitmap& icon_bitmap,
-                           bool is_icon_maskable,
-                           base::OnceClosure splash_image_callback) {
+                           bool is_icon_maskable) {
   // Send the data to the Java side to create the shortcut.
   JNIEnv* env = base::android::AttachCurrentThread();
   ScopedJavaLocalRef<jstring> java_webapp_id =
@@ -104,25 +100,23 @@
   if (!icon_bitmap.drawsNothing())
     java_bitmap = gfx::ConvertToJavaBitmap(icon_bitmap);
 
-  // The callback will need to be run after shortcut creation completes in order
-  // to download the splash image and save it to the WebappDataStorage. Create a
-  // copy of the callback here and send the pointer to Java, which will send it
-  // back once the asynchronous shortcut creation process finishes.
-  uintptr_t callback_pointer = reinterpret_cast<uintptr_t>(
-      new base::OnceClosure(std::move(splash_image_callback)));
-
   Java_ShortcutHelper_addWebapp(
       env, java_webapp_id, java_url, java_scope_url, java_user_title, java_name,
       java_short_name, java_best_primary_icon_url, java_bitmap,
       is_icon_maskable, static_cast<int>(info.display),
       static_cast<int>(info.orientation), info.source,
       OptionalSkColorToJavaColor(info.theme_color),
-      OptionalSkColorToJavaColor(info.background_color), callback_pointer);
+      OptionalSkColorToJavaColor(info.background_color));
+
+  // Start downloading the splash image in parallel with the app install.
+  content::ManifestIconDownloader::Download(
+      web_contents, info.splash_image_url, info.ideal_splash_image_size_in_px,
+      info.minimum_splash_image_size_in_px,
+      base::BindOnce(&ShortcutHelper::StoreWebappSplashImage, webapp_id));
 }
 
 // Adds a shortcut which opens in a browser tab to the launcher.
-void AddShortcutWithSkBitmap(content::WebContents* web_contents,
-                             const ShortcutInfo& info,
+void AddShortcutWithSkBitmap(const ShortcutInfo& info,
                              const std::string& id,
                              const SkBitmap& icon_bitmap,
                              bool is_icon_maskable) {
@@ -180,16 +174,11 @@
   if (info.display == blink::mojom::DisplayMode::kStandalone ||
       info.display == blink::mojom::DisplayMode::kFullscreen ||
       info.display == blink::mojom::DisplayMode::kMinimalUi) {
-    AddWebappWithSkBitmap(
-        info, webapp_id, icon_bitmap, is_icon_maskable,
-        base::BindOnce(&ShortcutHelper::FetchSplashScreenImage, web_contents,
-                       info.splash_image_url,
-                       info.ideal_splash_image_size_in_px,
-                       info.minimum_splash_image_size_in_px, webapp_id));
+    AddWebappWithSkBitmap(web_contents, info, webapp_id, icon_bitmap,
+                          is_icon_maskable);
     return;
   }
-  AddShortcutWithSkBitmap(web_contents, info, webapp_id, icon_bitmap,
-                          is_icon_maskable);
+  AddShortcutWithSkBitmap(info, webapp_id, icon_bitmap, is_icon_maskable);
 }
 
 void ShortcutHelper::ShowWebApkInstallInProgressToast() {
@@ -234,21 +223,6 @@
 }
 
 // static
-void ShortcutHelper::FetchSplashScreenImage(
-    content::WebContents* web_contents,
-    const GURL& image_url,
-    const int ideal_splash_image_size_in_px,
-    const int minimum_splash_image_size_in_px,
-    const std::string& webapp_id) {
-  // This is a fire and forget task. It is not vital for the splash screen image
-  // to be downloaded so if the downloader returns false there is no fallback.
-  content::ManifestIconDownloader::Download(
-      web_contents, image_url, ideal_splash_image_size_in_px,
-      minimum_splash_image_size_in_px,
-      base::BindOnce(&ShortcutHelper::StoreWebappSplashImage, webapp_id));
-}
-
-// static
 void ShortcutHelper::StoreWebappSplashImage(const std::string& webapp_id,
                                             const SkBitmap& splash_image) {
   if (splash_image.drawsNothing())
@@ -382,19 +356,3 @@
 void ShortcutHelper::SetIdealShortcutSizeForTesting(int size) {
   g_ideal_shortcut_icon_size = size;
 }
-
-// Callback used by Java when the shortcut has been created.
-// |splash_image_callback| is a pointer to a base::OnceClosure allocated in
-// AddShortcutWithSkBitmap, so reinterpret_cast it back and run it.
-//
-// This callback should only ever be called when the shortcut was for a
-// webapp-capable site; otherwise, |splash_image_callback| will have never been
-// allocated and doesn't need to be run or deleted.
-void JNI_ShortcutHelper_OnWebappDataStored(JNIEnv* env,
-                                           jlong jsplash_image_callback) {
-  DCHECK(jsplash_image_callback);
-  base::OnceClosure* splash_image_callback =
-      reinterpret_cast<base::OnceClosure*>(jsplash_image_callback);
-  std::move(*splash_image_callback).Run();
-  delete splash_image_callback;
-}
diff --git a/chrome/browser/android/shortcut_helper.h b/chrome/browser/android/shortcut_helper.h
index c7dedb54..9d4f1703 100644
--- a/chrome/browser/android/shortcut_helper.h
+++ b/chrome/browser/android/shortcut_helper.h
@@ -66,16 +66,6 @@
   // Returns the ideal size for a shortcut icon of a WebAPK.
   static int GetIdealShortcutIconSizeInPx();
 
-  // Fetches the splash screen image and stores it inside the WebappDataStorage
-  // of the webapp. The WebappDataStorage object *must* have been previously
-  // created by AddToLauncherWithSkBitmap(); this method should be passed as a
-  // closure to that method.
-  static void FetchSplashScreenImage(content::WebContents* web_contents,
-                                     const GURL& image_url,
-                                     const int ideal_splash_image_size_in_px,
-                                     const int minimum_splash_image_size_in_px,
-                                     const std::string& webapp_id);
-
   // Stores the webapp splash screen in the WebappDataStorage associated with
   // |webapp_id|.
   static void StoreWebappSplashImage(const std::string& webapp_id,