blob: c9a9713c9ced702157bd46c17f1123742dcb11b9 [file] [log] [blame]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/android/shortcut_helper.h"
#include <jni.h>
#include <limits>
#include <string>
#include <utility>
#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/functional/bind.h"
#include "base/uuid.h"
#include "chrome/android/chrome_jni_headers/ShortcutHelper_jni.h"
#include "components/webapps/browser/android/shortcut_info.h"
#include "content/public/browser/manifest_icon_downloader.h"
#include "content/public/browser/web_contents.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "ui/android/color_utils_android.h"
#include "ui/gfx/android/java_bitmap.h"
#include "url/gurl.h"
#include "url/origin.h"
using base::android::JavaParamRef;
using base::android::ScopedJavaLocalRef;
namespace {
// Adds a shortcut which opens in a fullscreen window to the launcher.
void AddWebappWithSkBitmap(content::WebContents* web_contents,
const webapps::ShortcutInfo& info,
const std::string& webapp_id,
const SkBitmap& icon_bitmap) {
// Send the data to the Java side to create the shortcut.
JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jstring> java_webapp_id =
base::android::ConvertUTF8ToJavaString(env, webapp_id);
ScopedJavaLocalRef<jstring> java_url =
base::android::ConvertUTF8ToJavaString(env, info.url.spec());
ScopedJavaLocalRef<jstring> java_scope_url =
base::android::ConvertUTF8ToJavaString(env, info.scope.spec());
ScopedJavaLocalRef<jstring> java_user_title =
base::android::ConvertUTF16ToJavaString(env, info.user_title);
ScopedJavaLocalRef<jstring> java_name =
base::android::ConvertUTF16ToJavaString(env, info.name);
ScopedJavaLocalRef<jstring> java_short_name =
base::android::ConvertUTF16ToJavaString(env, info.short_name);
ScopedJavaLocalRef<jstring> java_best_primary_icon_url =
base::android::ConvertUTF8ToJavaString(env,
info.best_primary_icon_url.spec());
ScopedJavaLocalRef<jobject> java_bitmap;
if (!icon_bitmap.drawsNothing())
java_bitmap = gfx::ConvertToJavaBitmap(icon_bitmap);
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,
info.is_primary_icon_maskable, static_cast<int>(info.display),
static_cast<int>(info.orientation),
ui::OptionalSkColorToJavaColor(info.theme_color),
ui::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,
/* maximum_icon_size_in_px= */ std::numeric_limits<int>::max(),
base::BindOnce(&ShortcutHelper::StoreWebappSplashImage, webapp_id));
}
// Adds a shortcut which opens in a browser tab to the launcher.
void AddShortcutWithSkBitmap(const webapps::ShortcutInfo& info,
const std::string& id,
const SkBitmap& icon_bitmap) {
JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jstring> java_id =
base::android::ConvertUTF8ToJavaString(env, id);
ScopedJavaLocalRef<jstring> java_url =
base::android::ConvertUTF8ToJavaString(env, info.url.spec());
ScopedJavaLocalRef<jstring> java_user_title =
base::android::ConvertUTF16ToJavaString(env, info.user_title);
ScopedJavaLocalRef<jstring> java_best_primary_icon_url =
base::android::ConvertUTF8ToJavaString(env,
info.best_primary_icon_url.spec());
ScopedJavaLocalRef<jobject> java_bitmap;
if (!icon_bitmap.drawsNothing())
java_bitmap = gfx::ConvertToJavaBitmap(icon_bitmap);
Java_ShortcutHelper_addShortcut(env, java_id, java_url, java_user_title,
java_bitmap, info.is_primary_icon_maskable,
java_best_primary_icon_url);
}
void RecordAddToHomeScreenUKM(
content::WebContents* web_contents,
const webapps::ShortcutInfo& info,
webapps::InstallableStatusCode installable_status) {
if (!web_contents)
return;
ukm::SourceId source_id =
web_contents->GetPrimaryMainFrame()->GetPageUkmSourceId();
ukm::builders::Webapp_AddToHomeScreen(source_id)
.SetDisplayMode(static_cast<int>(info.display))
.SetShortcutReason(static_cast<int>(installable_status))
.SetSameAsManifestStartUrl(info.url.spec() ==
web_contents->GetLastCommittedURL().spec())
.Record(ukm::UkmRecorder::Get());
}
} // anonymous namespace
// static
void ShortcutHelper::AddToLauncherWithSkBitmap(
content::WebContents* web_contents,
const webapps::ShortcutInfo& info,
const SkBitmap& icon_bitmap,
webapps::InstallableStatusCode installable_status) {
RecordAddToHomeScreenUKM(web_contents, info, installable_status);
std::string webapp_id = base::Uuid::GenerateRandomV4().AsLowercaseString();
if (info.display == blink::mojom::DisplayMode::kStandalone ||
info.display == blink::mojom::DisplayMode::kFullscreen ||
info.display == blink::mojom::DisplayMode::kMinimalUi) {
AddWebappWithSkBitmap(web_contents, info, webapp_id, icon_bitmap);
return;
}
AddShortcutWithSkBitmap(info, webapp_id, icon_bitmap);
}
// static
void ShortcutHelper::StoreWebappSplashImage(const std::string& webapp_id,
const SkBitmap& splash_image) {
if (splash_image.drawsNothing())
return;
JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jstring> java_webapp_id =
base::android::ConvertUTF8ToJavaString(env, webapp_id);
ScopedJavaLocalRef<jobject> java_splash_image =
gfx::ConvertToJavaBitmap(splash_image);
Java_ShortcutHelper_storeWebappSplashImage(env, java_webapp_id,
java_splash_image);
}
// static
bool ShortcutHelper::DoesOriginContainAnyInstalledWebApk(const GURL& origin) {
DCHECK_EQ(origin, origin.DeprecatedGetOriginAsURL());
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jstring> java_origin =
base::android::ConvertUTF8ToJavaString(
env, url::Origin::Create(origin).Serialize());
return Java_ShortcutHelper_doesOriginContainAnyInstalledWebApk(env,
java_origin);
}
bool ShortcutHelper::DoesOriginContainAnyInstalledTrustedWebActivity(
const GURL& origin) {
DCHECK_EQ(origin, origin.DeprecatedGetOriginAsURL());
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jstring> java_origin =
base::android::ConvertUTF8ToJavaString(
env, url::Origin::Create(origin).Serialize());
return Java_ShortcutHelper_doesOriginContainAnyInstalledTwa(env, java_origin);
}
std::set<GURL> ShortcutHelper::GetOriginsWithInstalledWebApksOrTwas() {
std::set<GURL> installed_origins;
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jobjectArray> j_installed_origins =
Java_ShortcutHelper_getOriginsWithInstalledWebApksOrTwas(env);
if (j_installed_origins) {
std::vector<std::string> installed_origins_list;
base::android::AppendJavaStringArrayToStringVector(env, j_installed_origins,
&installed_origins_list);
for (auto& origin : installed_origins_list)
installed_origins.emplace(GURL(origin));
}
return installed_origins;
}
void ShortcutHelper::SetForceWebApkUpdate(const std::string& id) {
JNIEnv* env = base::android::AttachCurrentThread();
Java_ShortcutHelper_setForceWebApkUpdate(
env, base::android::ConvertUTF8ToJavaString(env, id));
}