blob: 56d60b66aec4e5d5fb8152e23c2a2faad63e9769 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// 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/web_app_shortcut_manager.h"
#include <vector>
#include "base/bind.h"
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/web_applications/components/app_registrar.h"
#include "chrome/browser/web_applications/components/file_handler_manager.h"
#include "chrome/browser/web_applications/components/protocol_handler_manager.h"
#include "chrome/browser/web_applications/components/web_app_shortcut.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/browser/web_applications/web_app_icon_manager.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/services/app_service/public/cpp/file_handler.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_rep_default.h"
namespace web_app {
WebAppShortcutManager::WebAppShortcutManager(
Profile* profile,
WebAppIconManager* icon_manager,
FileHandlerManager* file_handler_manager,
ProtocolHandlerManager* protocol_handler_manager)
: AppShortcutManager(profile),
icon_manager_(icon_manager),
file_handler_manager_(file_handler_manager),
protocol_handler_manager_(protocol_handler_manager) {}
WebAppShortcutManager::~WebAppShortcutManager() = default;
std::unique_ptr<ShortcutInfo> WebAppShortcutManager::BuildShortcutInfo(
const AppId& app_id) {
const WebApp* app = GetWebAppRegistrar().GetAppById(app_id);
DCHECK(app);
return BuildShortcutInfoForWebApp(app);
}
void WebAppShortcutManager::GetShortcutInfoForApp(
const AppId& app_id,
GetShortcutInfoCallback callback) {
const WebApp* app = GetWebAppRegistrar().GetAppById(app_id);
// app could be nullptr if registry profile is being deleted.
if (!app) {
std::move(callback).Run(nullptr);
return;
}
// Build a common intersection between desired and downloaded icons.
auto icon_sizes_in_px = base::STLSetIntersection<std::vector<SquareSizePx>>(
app->downloaded_icon_sizes(IconPurpose::ANY),
GetDesiredIconSizesForShortcut());
DCHECK(icon_manager_);
if (!icon_sizes_in_px.empty()) {
icon_manager_->ReadIcons(app_id, IconPurpose::ANY, icon_sizes_in_px,
base::BindOnce(&WebAppShortcutManager::OnIconsRead,
weak_ptr_factory_.GetWeakPtr(),
app_id, std::move(callback)));
return;
}
// If there is no single icon at the desired sizes, we will resize what we can
// get.
SquareSizePx desired_icon_size = GetDesiredIconSizesForShortcut().back();
icon_manager_->ReadIconAndResize(
app_id, IconPurpose::ANY, desired_icon_size,
base::BindOnce(&WebAppShortcutManager::OnIconsRead,
weak_ptr_factory_.GetWeakPtr(), app_id,
std::move(callback)));
}
void WebAppShortcutManager::OnIconsRead(
const AppId& app_id,
GetShortcutInfoCallback callback,
std::map<SquareSizePx, SkBitmap> icon_bitmaps) {
// |icon_bitmaps| can be empty here if no icon found.
const WebApp* app = GetWebAppRegistrar().GetAppById(app_id);
if (!app) {
std::move(callback).Run(nullptr);
return;
}
gfx::ImageFamily image_family;
for (auto& size_and_bitmap : icon_bitmaps) {
image_family.Add(gfx::ImageSkia(
gfx::ImageSkiaRep(size_and_bitmap.second, /*scale=*/0.0f)));
}
// If the image failed to load, use the standard application icon.
if (image_family.empty()) {
SquareSizePx icon_size_in_px = GetDesiredIconSizesForShortcut().back();
gfx::ImageSkia image_skia = CreateDefaultApplicationIcon(icon_size_in_px);
image_family.Add(gfx::Image(image_skia));
}
std::unique_ptr<ShortcutInfo> shortcut_info = BuildShortcutInfoForWebApp(app);
shortcut_info->favicon = std::move(image_family);
std::move(callback).Run(std::move(shortcut_info));
}
std::unique_ptr<ShortcutInfo> WebAppShortcutManager::BuildShortcutInfoForWebApp(
const WebApp* app) {
auto shortcut_info = std::make_unique<ShortcutInfo>();
shortcut_info->extension_id = app->app_id();
shortcut_info->url = app->start_url();
shortcut_info->title = base::UTF8ToUTF16(app->name());
shortcut_info->description = base::UTF8ToUTF16(app->description());
shortcut_info->profile_path = profile()->GetPath();
shortcut_info->profile_name =
profile()->GetPrefs()->GetString(prefs::kProfileName);
shortcut_info->is_multi_profile = true;
if (const apps::FileHandlers* file_handlers =
file_handler_manager_->GetEnabledFileHandlers(app->app_id())) {
shortcut_info->file_handler_extensions =
GetFileExtensionsFromFileHandlers(*file_handlers);
shortcut_info->file_handler_mime_types =
GetMimeTypesFromFileHandlers(*file_handlers);
}
std::vector<apps::ProtocolHandlerInfo> protocol_handlers =
protocol_handler_manager_->GetAppProtocolHandlerInfos(app->app_id());
for (const auto& protocol_handler : protocol_handlers) {
if (!protocol_handler.protocol.empty()) {
shortcut_info->protocol_handlers.emplace(protocol_handler.protocol);
}
}
return shortcut_info;
}
WebAppRegistrar& WebAppShortcutManager::GetWebAppRegistrar() {
WebAppRegistrar* web_app_registrar = registrar()->AsWebAppRegistrar();
DCHECK(web_app_registrar);
return *web_app_registrar;
}
} // namespace web_app