blob: 038d2420f87e702e063d1b31747e2578c9eb0709 [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "weblayer/browser/webapps/webapk_install_scheduler.h"
#include <utility>
#include "base/functional/bind.h"
#include "base/task/thread_pool.h"
#include "components/webapps/browser/android/shortcut_info.h"
#include "components/webapps/browser/android/webapk/webapk_icon_hasher.h"
#include "components/webapps/browser/android/webapk/webapk_proto_builder.h"
#include "components/webapps/browser/android/webapk/webapk_types.h"
#include "components/webapps/browser/android/webapps_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "url/gurl.h"
#include "weblayer/browser/webapps/webapk_install_scheduler_bridge.h"
namespace weblayer {
WebApkInstallScheduler::WebApkInstallScheduler(
const webapps::ShortcutInfo& shortcut_info,
const SkBitmap& primary_icon,
bool is_primary_icon_maskable,
WebApkInstallFinishedCallback callback)
: webapps_client_callback_(std::move(callback)),
primary_icon_(primary_icon),
is_primary_icon_maskable_(is_primary_icon_maskable) {
shortcut_info_ = std::make_unique<webapps::ShortcutInfo>(shortcut_info);
}
WebApkInstallScheduler::~WebApkInstallScheduler() = default;
// static
void WebApkInstallScheduler::FetchProtoAndScheduleInstall(
content::WebContents* web_contents,
const webapps::ShortcutInfo& shortcut_info,
const SkBitmap& primary_icon,
bool is_primary_icon_maskable,
WebApkInstallFinishedCallback callback) {
// Self owned WebApkInstallScheduler that destroys itself as soon as its
// OnResult function is called when the scheduled installation failed or
// finished.
WebApkInstallScheduler* scheduler =
new WebApkInstallScheduler(shortcut_info, primary_icon,
is_primary_icon_maskable, std::move(callback));
scheduler->FetchMurmur2Hashes(web_contents);
}
void WebApkInstallScheduler::FetchProtoAndScheduleInstallForTesting(
content::WebContents* web_contents) {
FetchMurmur2Hashes(web_contents);
}
void WebApkInstallScheduler::FetchMurmur2Hashes(
content::WebContents* web_contents) {
// We need to take the hash of the bitmap at the icon URL prior to any
// transformations being applied to the bitmap (such as encoding/decoding
// the bitmap). The icon hash is used to determine whether the icon that
// the user sees matches the icon of a WebAPK that the WebAPK server
// generated for another user. (The icon can be dynamically generated.)
//
// We redownload the icon in order to take the Murmur2 hash. The redownload
// should be fast because the icon should be in the HTTP cache.
std::set<GURL> icons = shortcut_info_->GetWebApkIcons();
webapps::WebApkIconHasher::DownloadAndComputeMurmur2Hash(
web_contents->GetBrowserContext()
->GetDefaultStoragePartition()
->GetURLLoaderFactoryForBrowserProcess()
.get(),
web_contents->GetWeakPtr(), url::Origin::Create(shortcut_info_->url),
icons,
base::BindOnce(&WebApkInstallScheduler::OnGotIconMurmur2HashesBuildProto,
weak_ptr_factory_.GetWeakPtr()));
}
void WebApkInstallScheduler::OnGotIconMurmur2HashesBuildProto(
absl::optional<std::map<std::string, webapps::WebApkIconHasher::Icon>>
hashes) {
if (!hashes) {
OnResult(webapps::WebApkInstallResult::ICON_HASHER_ERROR);
return;
}
webapps::BuildProto(
*shortcut_info_.get(), shortcut_info_->manifest_id,
std::string() /* primary_icon_data */, is_primary_icon_maskable_,
std::string() /* splash_icon_data */, "" /* package_name */,
"" /* version */, std::move(*hashes), false /* is_manifest_stale */,
false /* is_app_identity_update_supported */,
base::BindOnce(&WebApkInstallScheduler::ScheduleWithChrome,
weak_ptr_factory_.GetWeakPtr()));
}
void WebApkInstallScheduler::ScheduleWithChrome(
std::unique_ptr<std::string> serialized_proto) {
WebApkInstallSchedulerBridge::ScheduleWebApkInstallWithChrome(
std::move(serialized_proto), primary_icon_, is_primary_icon_maskable_,
base::BindOnce(&WebApkInstallScheduler::OnResult,
weak_ptr_factory_.GetWeakPtr()));
}
void WebApkInstallScheduler::OnResult(webapps::WebApkInstallResult result) {
// Toasts have to be called on the UI thread, but the
// WebApkInstallSchedulerClient already makes sure that the callback, which is
// triggered by the Chrome-service, is invoked on the UI thread.
webapps::WebappsUtils::ShowWebApkInstallResultToast(result);
std::move(webapps_client_callback_).Run(shortcut_info_->manifest_id);
delete this;
}
// static
bool WebApkInstallScheduler::IsInstallServiceAvailable() {
return WebApkInstallSchedulerBridge::IsInstallServiceAvailable();
}
} // namespace weblayer