blob: 062e027aa835dc4e6b42da8e26190666164b689a [file] [log] [blame]
[email protected]51208252013-08-19 21:05:301// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/android/shortcut_helper.h"
6
7#include <jni.h>
gonzalon87192d772017-02-07 22:31:108#include <utility>
[email protected]51208252013-08-19 21:05:309
10#include "base/android/jni_android.h"
lalitm45a03c72015-09-16 13:00:4311#include "base/android/jni_array.h"
[email protected]51208252013-08-19 21:05:3012#include "base/android/jni_string.h"
dominickn6509a4de2016-04-06 08:29:0613#include "base/bind.h"
14#include "base/callback.h"
pkotwiczd0d459e2017-03-01 22:55:1015#include "base/guid.h"
Daniel Cheng8fedab22018-05-17 00:39:2716#include "base/optional.h"
[email protected]51208252013-08-19 21:05:3017#include "base/strings/string16.h"
mlamouric679bbf2014-09-24 21:24:4918#include "base/strings/utf_string_conversions.h"
Etienne Pierre-doray4f2e41bed2018-09-24 22:10:1119#include "base/threading/thread_restrictions.h"
Andrew Grieve4a42c22e2019-06-24 16:14:2920#include "chrome/android/chrome_jni_headers/ShortcutHelper_jni.h"
Daniel Cheng8fedab22018-05-17 00:39:2721#include "chrome/browser/android/color_helpers.h"
Michael Thiessene01199c942019-06-25 16:32:5322#include "chrome/browser/android/tab_android.h"
hanxi563f3532016-08-19 20:09:0123#include "chrome/browser/android/webapk/chrome_webapk_host.h"
hanxi070d10a2017-01-09 15:56:5024#include "chrome/browser/android/webapk/webapk_install_service.h"
pkotwiczf4dddb32017-02-25 01:21:5525#include "chrome/browser/android/webapk/webapk_metrics.h"
pkotwicz206673142016-07-19 19:13:3026#include "chrome/common/chrome_switches.h"
dfalcantaraaec56da2015-05-06 03:33:5627#include "content/public/browser/browser_thread.h"
jinho.bang84cadc82017-06-14 16:59:3428#include "content/public/browser/manifest_icon_downloader.h"
[email protected]51208252013-08-19 21:05:3029#include "content/public/browser/web_contents.h"
Dmitry Gozman88ca5a992018-05-18 00:13:3330#include "third_party/blink/public/common/manifest/manifest.h"
Mugdha Lakhani62db8de2018-07-10 16:00:4831#include "third_party/blink/public/common/manifest/manifest_icon_selector.h"
Daniel Cheng8fedab22018-05-17 00:39:2732#include "third_party/skia/include/core/SkColor.h"
[email protected]51208252013-08-19 21:05:3033#include "ui/gfx/android/java_bitmap.h"
mlamouribc6e8792015-10-22 20:41:1334#include "ui/gfx/color_analysis.h"
[email protected]51208252013-08-19 21:05:3035#include "url/gurl.h"
36
torne86560112016-08-04 15:59:0437using base::android::JavaParamRef;
38using base::android::ScopedJavaLocalRef;
mlamouric679bbf2014-09-24 21:24:4939
lalitm45a03c72015-09-16 13:00:4340namespace {
41
zpenge33ba852017-02-01 20:54:4242int g_ideal_homescreen_icon_size = -1;
43int g_minimum_homescreen_icon_size = -1;
44int g_ideal_splash_image_size = -1;
45int g_minimum_splash_image_size = -1;
46int g_ideal_badge_icon_size = -1;
lalitm45a03c72015-09-16 13:00:4347
zpenge33ba852017-02-01 20:54:4248int g_default_rgb_icon_value = 145;
mlamouribc6e8792015-10-22 20:41:1349
lalitm45a03c72015-09-16 13:00:4350// Retrieves and caches the ideal and minimum sizes of the Home screen icon
51// and the splash screen image.
52void GetHomescreenIconAndSplashImageSizes() {
53 JNIEnv* env = base::android::AttachCurrentThread();
54 ScopedJavaLocalRef<jintArray> java_size_array =
pkotwicz45fc42b62016-06-07 00:07:1055 Java_ShortcutHelper_getHomeScreenIconAndSplashImageSizes(env);
lalitm45a03c72015-09-16 13:00:4356 std::vector<int> sizes;
Torne (Richard Coles)3c22e8302018-10-12 18:34:2257 base::android::JavaIntArrayToIntVector(env, java_size_array, &sizes);
lalitm45a03c72015-09-16 13:00:4358
59 // Check that the size returned is what is expected.
zpenge33ba852017-02-01 20:54:4260 DCHECK(sizes.size() == 5);
lalitm45a03c72015-09-16 13:00:4361
62 // This ordering must be kept up to date with the Java ShortcutHelper.
zpenge33ba852017-02-01 20:54:4263 g_ideal_homescreen_icon_size = sizes[0];
64 g_minimum_homescreen_icon_size = sizes[1];
65 g_ideal_splash_image_size = sizes[2];
66 g_minimum_splash_image_size = sizes[3];
67 g_ideal_badge_icon_size = sizes[4];
lalitm45a03c72015-09-16 13:00:4368
69 // Try to ensure that the data returned is sane.
zpenge33ba852017-02-01 20:54:4270 DCHECK(g_minimum_homescreen_icon_size <= g_ideal_homescreen_icon_size);
71 DCHECK(g_minimum_splash_image_size <= g_ideal_splash_image_size);
lalitm45a03c72015-09-16 13:00:4372}
73
pkotwicz97478712017-03-01 03:39:5474// Adds a shortcut which opens in a fullscreen window to the launcher.
75// |splash_image_callback| will be invoked once the Java-side operation has
76// completed. This is necessary as Java will asynchronously create and
77// populate a WebappDataStorage object for standalone-capable sites. This must
78// exist before the splash image can be stored.
79void AddWebappWithSkBitmap(const ShortcutInfo& info,
80 const std::string& webapp_id,
81 const SkBitmap& icon_bitmap,
Peter E Connb955ae4a2018-12-03 13:02:0982 bool is_icon_maskable,
Dominick Ng40be8182019-03-11 23:21:0383 base::OnceClosure splash_image_callback) {
[email protected]51208252013-08-19 21:05:3084 // Send the data to the Java side to create the shortcut.
85 JNIEnv* env = base::android::AttachCurrentThread();
lalitmd93c2ed2015-09-04 16:22:1286 ScopedJavaLocalRef<jstring> java_webapp_id =
87 base::android::ConvertUTF8ToJavaString(env, webapp_id);
[email protected]51208252013-08-19 21:05:3088 ScopedJavaLocalRef<jstring> java_url =
dfalcantara16e84de2015-02-03 22:07:4089 base::android::ConvertUTF8ToJavaString(env, info.url.spec());
pkotwicz6bdfbe1b2016-07-08 00:26:4390 ScopedJavaLocalRef<jstring> java_scope_url =
91 base::android::ConvertUTF8ToJavaString(env, info.scope.spec());
lalitmf3ee51852015-07-21 18:13:1192 ScopedJavaLocalRef<jstring> java_user_title =
93 base::android::ConvertUTF16ToJavaString(env, info.user_title);
94 ScopedJavaLocalRef<jstring> java_name =
95 base::android::ConvertUTF16ToJavaString(env, info.name);
96 ScopedJavaLocalRef<jstring> java_short_name =
97 base::android::ConvertUTF16ToJavaString(env, info.short_name);
zpenga7856eef2017-02-07 11:42:4498 ScopedJavaLocalRef<jstring> java_best_primary_icon_url =
99 base::android::ConvertUTF8ToJavaString(env,
100 info.best_primary_icon_url.spec());
[email protected]51208252013-08-19 21:05:30101 ScopedJavaLocalRef<jobject> java_bitmap;
zpengfebce7612017-06-07 14:29:04102 if (!icon_bitmap.drawsNothing())
mlamouric679bbf2014-09-24 21:24:49103 java_bitmap = gfx::ConvertToJavaBitmap(&icon_bitmap);
[email protected]51208252013-08-19 21:05:30104
pkotwicz206673142016-07-19 19:13:30105 // The callback will need to be run after shortcut creation completes in order
106 // to download the splash image and save it to the WebappDataStorage. Create a
107 // copy of the callback here and send the pointer to Java, which will send it
108 // back once the asynchronous shortcut creation process finishes.
Dominick Ng40be8182019-03-11 23:21:03109 uintptr_t callback_pointer = reinterpret_cast<uintptr_t>(
110 new base::OnceClosure(std::move(splash_image_callback)));
dominickn6509a4de2016-04-06 08:29:06111
zpenga7856eef2017-02-07 11:42:44112 Java_ShortcutHelper_addWebapp(
113 env, java_webapp_id, java_url, java_scope_url, java_user_title, java_name,
Peter E Connb955ae4a2018-12-03 13:02:09114 java_short_name, java_best_primary_icon_url, java_bitmap,
115 is_icon_maskable, info.display, info.orientation, info.source,
Daniel Cheng8fedab22018-05-17 00:39:27116 OptionalSkColorToJavaColor(info.theme_color),
Michael Thiessene01199c942019-06-25 16:32:53117 OptionalSkColorToJavaColor(info.background_color), callback_pointer,
118 false /* isShortcutAsWebapp */);
[email protected]51208252013-08-19 21:05:30119}
benwells840ae902015-02-17 21:13:28120
pkotwicz97478712017-03-01 03:39:54121// Adds a shortcut which opens in a browser tab to the launcher.
Michael Thiessene01199c942019-06-25 16:32:53122void AddShortcutWithSkBitmap(content::WebContents* web_contents,
123 const ShortcutInfo& info,
pkotwicz97478712017-03-01 03:39:54124 const std::string& id,
Peter E Connb955ae4a2018-12-03 13:02:09125 const SkBitmap& icon_bitmap,
126 bool is_icon_maskable) {
pkotwicz206673142016-07-19 19:13:30127 JNIEnv* env = base::android::AttachCurrentThread();
martiw12166f52017-02-20 03:05:45128 ScopedJavaLocalRef<jstring> java_id =
129 base::android::ConvertUTF8ToJavaString(env, id);
pkotwicz206673142016-07-19 19:13:30130 ScopedJavaLocalRef<jstring> java_url =
131 base::android::ConvertUTF8ToJavaString(env, info.url.spec());
132 ScopedJavaLocalRef<jstring> java_user_title =
133 base::android::ConvertUTF16ToJavaString(env, info.user_title);
Michael Thiessene01199c942019-06-25 16:32:53134 ScopedJavaLocalRef<jstring> java_best_primary_icon_url =
135 base::android::ConvertUTF8ToJavaString(env,
136 info.best_primary_icon_url.spec());
pkotwicz206673142016-07-19 19:13:30137 ScopedJavaLocalRef<jobject> java_bitmap;
zpengfebce7612017-06-07 14:29:04138 if (!icon_bitmap.drawsNothing())
pkotwicz206673142016-07-19 19:13:30139 java_bitmap = gfx::ConvertToJavaBitmap(&icon_bitmap);
Michael Thiessene01199c942019-06-25 16:32:53140 TabAndroid* tab = TabAndroid::FromWebContents(web_contents);
141 Java_ShortcutHelper_addShortcut(env, tab ? tab->GetJavaObject() : nullptr,
142 java_id, java_url, java_user_title,
143 java_bitmap, is_icon_maskable, info.source,
144 java_best_primary_icon_url);
pkotwicz206673142016-07-19 19:13:30145}
146
pkotwicz97478712017-03-01 03:39:54147} // anonymous namespace
148
149// static
Dominick Ng203b4932018-02-02 05:32:45150std::unique_ptr<ShortcutInfo> ShortcutHelper::CreateShortcutInfo(
151 const GURL& manifest_url,
Dmitry Gozman88ca5a992018-05-18 00:13:33152 const blink::Manifest& manifest,
Dominick Ng203b4932018-02-02 05:32:45153 const GURL& primary_icon_url,
154 const GURL& badge_icon_url) {
155 auto shortcut_info = std::make_unique<ShortcutInfo>(GURL());
156 if (!manifest.IsEmpty()) {
157 shortcut_info->UpdateFromManifest(manifest);
158 shortcut_info->manifest_url = manifest_url;
159 shortcut_info->best_primary_icon_url = primary_icon_url;
160 shortcut_info->best_badge_icon_url = badge_icon_url;
161 }
162
163 shortcut_info->ideal_splash_image_size_in_px = GetIdealSplashImageSizeInPx();
164 shortcut_info->minimum_splash_image_size_in_px =
165 GetMinimumSplashImageSizeInPx();
166 shortcut_info->splash_image_url =
Sahel Sharifyc067b74f2019-04-17 23:19:07167 blink::ManifestIconSelector::FindBestMatchingSquareIcon(
Dominick Ng203b4932018-02-02 05:32:45168 manifest.icons, shortcut_info->ideal_splash_image_size_in_px,
169 shortcut_info->minimum_splash_image_size_in_px,
Rayan Kanso393cb2232018-06-06 09:34:05170 blink::Manifest::ImageResource::Purpose::ANY);
Dominick Ng203b4932018-02-02 05:32:45171
172 return shortcut_info;
173}
174
175// static
pkotwicz97478712017-03-01 03:39:54176void ShortcutHelper::AddToLauncherWithSkBitmap(
pkotwiczd0d459e2017-03-01 22:55:10177 content::WebContents* web_contents,
pkotwicz97478712017-03-01 03:39:54178 const ShortcutInfo& info,
Peter E Connb955ae4a2018-12-03 13:02:09179 const SkBitmap& icon_bitmap,
180 bool is_icon_maskable) {
pkotwiczd0d459e2017-03-01 22:55:10181 std::string webapp_id = base::GenerateGUID();
Blink Reformat1c4d759e2017-04-09 16:34:54182 if (info.display == blink::kWebDisplayModeStandalone ||
Piotr Swigon549c0432017-08-16 02:48:41183 info.display == blink::kWebDisplayModeFullscreen ||
Piotr Swigon57e79c5c2017-12-29 01:11:15184 info.display == blink::kWebDisplayModeMinimalUi) {
pkotwiczd0d459e2017-03-01 22:55:10185 AddWebappWithSkBitmap(
Peter E Connb955ae4a2018-12-03 13:02:09186 info, webapp_id, icon_bitmap, is_icon_maskable,
Dominick Ng40be8182019-03-11 23:21:03187 base::BindOnce(&ShortcutHelper::FetchSplashScreenImage, web_contents,
188 info.splash_image_url,
189 info.ideal_splash_image_size_in_px,
190 info.minimum_splash_image_size_in_px, webapp_id));
pkotwicz97478712017-03-01 03:39:54191 return;
192 }
Michael Thiessene01199c942019-06-25 16:32:53193 AddShortcutWithSkBitmap(web_contents, info, webapp_id, icon_bitmap,
194 is_icon_maskable);
pkotwicz97478712017-03-01 03:39:54195}
196
hanxi070d10a2017-01-09 15:56:50197void ShortcutHelper::ShowWebApkInstallInProgressToast() {
198 Java_ShortcutHelper_showWebApkInstallInProgressToast(
199 base::android::AttachCurrentThread());
200}
201
zpeng5d8fdfc2017-01-05 15:45:06202int ShortcutHelper::GetIdealHomescreenIconSizeInPx() {
zpenge33ba852017-02-01 20:54:42203 if (g_ideal_homescreen_icon_size == -1)
lalitm45a03c72015-09-16 13:00:43204 GetHomescreenIconAndSplashImageSizes();
zpenge33ba852017-02-01 20:54:42205 return g_ideal_homescreen_icon_size;
lalitm45a03c72015-09-16 13:00:43206}
207
zpeng5d8fdfc2017-01-05 15:45:06208int ShortcutHelper::GetMinimumHomescreenIconSizeInPx() {
zpenge33ba852017-02-01 20:54:42209 if (g_minimum_homescreen_icon_size == -1)
lalitm45a03c72015-09-16 13:00:43210 GetHomescreenIconAndSplashImageSizes();
zpenge33ba852017-02-01 20:54:42211 return g_minimum_homescreen_icon_size;
lalitm45a03c72015-09-16 13:00:43212}
213
zpeng5d8fdfc2017-01-05 15:45:06214int ShortcutHelper::GetIdealSplashImageSizeInPx() {
zpenge33ba852017-02-01 20:54:42215 if (g_ideal_splash_image_size == -1)
lalitm45a03c72015-09-16 13:00:43216 GetHomescreenIconAndSplashImageSizes();
zpenge33ba852017-02-01 20:54:42217 return g_ideal_splash_image_size;
lalitm45a03c72015-09-16 13:00:43218}
219
zpeng5d8fdfc2017-01-05 15:45:06220int ShortcutHelper::GetMinimumSplashImageSizeInPx() {
zpenge33ba852017-02-01 20:54:42221 if (g_minimum_splash_image_size == -1)
lalitm45a03c72015-09-16 13:00:43222 GetHomescreenIconAndSplashImageSizes();
zpenge33ba852017-02-01 20:54:42223 return g_minimum_splash_image_size;
224}
225
226int ShortcutHelper::GetIdealBadgeIconSizeInPx() {
227 if (g_ideal_badge_icon_size == -1)
228 GetHomescreenIconAndSplashImageSizes();
229 return g_ideal_badge_icon_size;
lalitm45a03c72015-09-16 13:00:43230}
231
lalitmd93c2ed2015-09-04 16:22:12232// static
233void ShortcutHelper::FetchSplashScreenImage(
234 content::WebContents* web_contents,
235 const GURL& image_url,
zpeng5d8fdfc2017-01-05 15:45:06236 const int ideal_splash_image_size_in_px,
237 const int minimum_splash_image_size_in_px,
dominickn6509a4de2016-04-06 08:29:06238 const std::string& webapp_id) {
lalitmd93c2ed2015-09-04 16:22:12239 // This is a fire and forget task. It is not vital for the splash screen image
240 // to be downloaded so if the downloader returns false there is no fallback.
jinho.bang84cadc82017-06-14 16:59:34241 content::ManifestIconDownloader::Download(
zpeng5d8fdfc2017-01-05 15:45:06242 web_contents, image_url, ideal_splash_image_size_in_px,
243 minimum_splash_image_size_in_px,
Dominick Ng40be8182019-03-11 23:21:03244 base::BindOnce(&ShortcutHelper::StoreWebappSplashImage, webapp_id));
lalitmd93c2ed2015-09-04 16:22:12245}
246
247// static
zpenga7856eef2017-02-07 11:42:44248void ShortcutHelper::StoreWebappSplashImage(const std::string& webapp_id,
249 const SkBitmap& splash_image) {
lalitmd93c2ed2015-09-04 16:22:12250 if (splash_image.drawsNothing())
251 return;
252
253 JNIEnv* env = base::android::AttachCurrentThread();
254 ScopedJavaLocalRef<jstring> java_webapp_id =
255 base::android::ConvertUTF8ToJavaString(env, webapp_id);
256 ScopedJavaLocalRef<jobject> java_splash_image =
257 gfx::ConvertToJavaBitmap(&splash_image);
258
torne948f3662016-08-16 15:10:44259 Java_ShortcutHelper_storeWebappSplashImage(env, java_webapp_id,
260 java_splash_image);
lalitmd93c2ed2015-09-04 16:22:12261}
262
mlamouribc6e8792015-10-22 20:41:13263// static
pkotwicz5774087e2016-08-10 17:36:40264SkBitmap ShortcutHelper::FinalizeLauncherIconInBackground(
265 const SkBitmap& bitmap,
Peter E Connb955ae4a2018-12-03 13:02:09266 bool is_icon_maskable,
pkotwicz5774087e2016-08-10 17:36:40267 const GURL& url,
268 bool* is_generated) {
Etienne Pierre-doray4f2e41bed2018-09-24 22:10:11269 base::AssertLongCPUWorkAllowed();
mlamouribc6e8792015-10-22 20:41:13270
271 JNIEnv* env = base::android::AttachCurrentThread();
272 ScopedJavaLocalRef<jobject> result;
273 *is_generated = false;
274
275 if (!bitmap.isNull()) {
pkotwicz45fc42b62016-06-07 00:07:10276 if (Java_ShortcutHelper_isIconLargeEnoughForLauncher(env, bitmap.width(),
277 bitmap.height())) {
newta584b9e2015-10-29 22:29:43278 ScopedJavaLocalRef<jobject> java_bitmap =
279 gfx::ConvertToJavaBitmap(&bitmap);
Peter E Connb955ae4a2018-12-03 13:02:09280 result = Java_ShortcutHelper_createHomeScreenIconFromWebIcon(
281 env, java_bitmap, is_icon_maskable);
mlamouribc6e8792015-10-22 20:41:13282 }
283 }
284
285 if (result.is_null()) {
286 ScopedJavaLocalRef<jstring> java_url =
287 base::android::ConvertUTF8ToJavaString(env, url.spec());
zpenge33ba852017-02-01 20:54:42288 SkColor mean_color =
289 SkColorSetRGB(g_default_rgb_icon_value, g_default_rgb_icon_value,
290 g_default_rgb_icon_value);
mlamouribc6e8792015-10-22 20:41:13291
292 if (!bitmap.isNull())
293 mean_color = color_utils::CalculateKMeanColorOfBitmap(bitmap);
294
295 *is_generated = true;
newta584b9e2015-10-29 22:29:43296 result = Java_ShortcutHelper_generateHomeScreenIcon(
torne948f3662016-08-16 15:10:44297 env, java_url, SkColorGetR(mean_color), SkColorGetG(mean_color),
mlamouribc6e8792015-10-22 20:41:13298 SkColorGetB(mean_color));
299 }
300
pkotwicz964382b2016-08-04 01:24:55301 return result.obj()
torned64eb5132016-10-24 12:51:28302 ? gfx::CreateSkBitmapFromJavaBitmap(gfx::JavaBitmap(result))
pkotwicz964382b2016-08-04 01:24:55303 : SkBitmap();
mlamouribc6e8792015-10-22 20:41:13304}
305
pkotwiczcda82fe2016-07-08 18:56:54306// static
Peter Kotwicz4b358c162019-01-03 01:10:58307std::string ShortcutHelper::QueryFirstWebApkPackage(const GURL& url) {
zpeng4bb58962016-10-04 02:42:29308 JNIEnv* env = base::android::AttachCurrentThread();
309 ScopedJavaLocalRef<jstring> java_url =
310 base::android::ConvertUTF8ToJavaString(env, url.spec());
311 ScopedJavaLocalRef<jstring> java_webapk_package_name =
Peter Kotwicz4b358c162019-01-03 01:10:58312 Java_ShortcutHelper_queryFirstWebApkPackage(env, java_url);
zpeng4bb58962016-10-04 02:42:29313
314 std::string webapk_package_name = "";
315 if (java_webapk_package_name.obj()) {
zpenga7856eef2017-02-07 11:42:44316 webapk_package_name =
317 base::android::ConvertJavaStringToUTF8(env, java_webapk_package_name);
zpeng4bb58962016-10-04 02:42:29318 }
319 return webapk_package_name;
320}
321
322// static
zpenga7856eef2017-02-07 11:42:44323bool ShortcutHelper::IsWebApkInstalled(content::BrowserContext* browser_context,
324 const GURL& start_url,
325 const GURL& manifest_url) {
Peter Kotwicz4b358c162019-01-03 01:10:58326 return !QueryFirstWebApkPackage(start_url).empty() ||
zpenga7856eef2017-02-07 11:42:44327 WebApkInstallService::Get(browser_context)
328 ->IsInstallInProgress(manifest_url);
pkotwiczcda82fe2016-07-08 18:56:54329}
330
ckitagawa1fa69c02019-07-24 19:20:44331void ShortcutHelper::SetForceWebApkUpdate(const std::string& id) {
332 JNIEnv* env = base::android::AttachCurrentThread();
333 Java_ShortcutHelper_setForceWebApkUpdate(
334 env, base::android::ConvertUTF8ToJavaString(env, id));
gonzalon87192d772017-02-07 22:31:10335}
336
dominickn6509a4de2016-04-06 08:29:06337// Callback used by Java when the shortcut has been created.
Dominick Ng40be8182019-03-11 23:21:03338// |splash_image_callback| is a pointer to a base::OnceClosure allocated in
pkotwiczc67e6ac2016-08-12 19:56:44339// AddShortcutWithSkBitmap, so reinterpret_cast it back and run it.
dominickn6509a4de2016-04-06 08:29:06340//
341// This callback should only ever be called when the shortcut was for a
342// webapp-capable site; otherwise, |splash_image_callback| will have never been
343// allocated and doesn't need to be run or deleted.
Daniel Bratell7aacf952017-11-21 17:51:25344void JNI_ShortcutHelper_OnWebappDataStored(JNIEnv* env,
Daniel Bratell7aacf952017-11-21 17:51:25345 jlong jsplash_image_callback) {
dominickn6509a4de2016-04-06 08:29:06346 DCHECK(jsplash_image_callback);
Dominick Ng40be8182019-03-11 23:21:03347 base::OnceClosure* splash_image_callback =
348 reinterpret_cast<base::OnceClosure*>(jsplash_image_callback);
349 std::move(*splash_image_callback).Run();
dominickn6509a4de2016-04-06 08:29:06350 delete splash_image_callback;
351}
352