blob: 23e6a0867ecdc0bac59a15e5c4474eae74ed13bb [file] [log] [blame]
// Copyright 2023 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/web_applications/commands/generated_icon_fix_command.h"
#include <memory>
#include <string>
#include "base/check.h"
#include "base/functional/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/browser/web_applications/web_app_command_manager.h"
#include "chrome/browser/web_applications/web_app_icon_generator.h"
#include "chrome/browser/web_applications/web_app_install_manager.h"
#include "chrome/browser/web_applications/web_app_install_utils.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/browser/web_applications/web_app_registry_update.h"
#include "chrome/browser/web_applications/web_app_sync_bridge.h"
#include "chrome/browser/web_applications/web_contents/web_app_icon_downloader.h"
#include "chrome/browser/web_applications/web_contents/web_contents_manager.h"
#include "chrome/common/chrome_features.h"
namespace web_app {
GeneratedIconFixCommand::GeneratedIconFixCommand(
AppId app_id,
base::OnceCallback<void(GeneratedIconFixResult)> callback)
: WebAppCommandTemplate<SharedWebContentsWithAppLock>(
"GeneratedIconFixCommand"),
app_id_(std::move(app_id)),
callback_(std::move(callback)),
lock_description_({app_id_}) {
CHECK(base::FeatureList::IsEnabled(
features::kWebAppSyncGeneratedIconBackgroundFix));
}
GeneratedIconFixCommand::~GeneratedIconFixCommand() = default;
void GeneratedIconFixCommand::StartWithLock(
std::unique_ptr<SharedWebContentsWithAppLock> lock) {
lock_ = std::move(lock);
const WebApp* app = lock_->registrar().GetAppById(app_id_);
if (!app) {
Stop(GeneratedIconFixResult::kAppUninstalled, FROM_HERE);
return;
}
icon_downloader_ = lock_->web_contents_manager().CreateIconDownloader();
base::flat_set<GURL> icon_urls;
install_info_.manifest_icons = app->manifest_icons();
// Set title and start_url for PopulateProductIcons() in case it tries to
// generate icons again.
install_info_.title = base::UTF8ToUTF16(app->untranslated_name());
install_info_.start_url = app->start_url();
for (const apps::IconInfo& icon_info : install_info_.manifest_icons) {
icon_urls.insert(icon_info.url);
}
icon_downloader_->Start(
&lock_->shared_web_contents(), icon_urls,
base::BindOnce(&GeneratedIconFixCommand::OnIconsDownloaded,
weak_factory_.GetWeakPtr()));
}
void GeneratedIconFixCommand::OnShutdown() {
Stop(GeneratedIconFixResult::kShutdown, FROM_HERE);
}
const LockDescription& GeneratedIconFixCommand::lock_description() const {
return lock_description_;
}
base::Value GeneratedIconFixCommand::ToDebugValue() const {
return base::Value(
base::Value::Dict().Set("stop_location", stop_location_.ToString()));
}
void GeneratedIconFixCommand::OnIconsDownloaded(
IconsDownloadedResult result,
IconsMap icons_map,
DownloadedIconsHttpResults icons_http_results) {
if (result != IconsDownloadedResult::kCompleted) {
Stop(GeneratedIconFixResult::kDownloadFailure, FROM_HERE);
return;
}
PopulateProductIcons(&install_info_, &icons_map);
if (install_info_.is_generated_icon) {
Stop(GeneratedIconFixResult::kStillGenerated, FROM_HERE);
return;
}
// Note: Empty params are noops, WriteData() never deletes icons.
lock_->icon_manager().WriteData(
app_id_, install_info_.icon_bitmaps, /*shortcuts_menu_icons=*/{},
/*other_icons_map=*/{},
base::BindOnce(&GeneratedIconFixCommand::OnIconsWritten,
weak_factory_.GetWeakPtr()));
}
void GeneratedIconFixCommand::OnIconsWritten(bool success) {
if (!success) {
Stop(GeneratedIconFixResult::kWriteFailure, FROM_HERE);
return;
}
{
ScopedRegistryUpdate update = lock_->sync_bridge().BeginUpdate();
SetWebAppProductIconFields(install_info_, *update->UpdateApp(app_id_));
}
lock_->install_manager().NotifyWebAppManifestUpdated(app_id_);
Stop(GeneratedIconFixResult::kSuccess, FROM_HERE);
}
void GeneratedIconFixCommand::Stop(GeneratedIconFixResult result,
base::Location location) {
CHECK(callback_);
stop_location_ = std::move(location);
// TODO(crbug.com/1216965): Record the attempt and call
// GeneratedIconFixManager::MaybeScheduleNextFix() if !success.
SignalCompletionAndSelfDestruct(
[&] {
switch (result) {
case GeneratedIconFixResult::kAppUninstalled:
case GeneratedIconFixResult::kDownloadFailure:
case GeneratedIconFixResult::kStillGenerated:
case GeneratedIconFixResult::kWriteFailure:
return CommandResult::kFailure;
case GeneratedIconFixResult::kShutdown:
return CommandResult::kShutdown;
case GeneratedIconFixResult::kSuccess:
return CommandResult::kSuccess;
}
}(),
base::BindOnce(std::move(callback_), result));
}
} // namespace web_app