#ifndef CHROME_BROWSER_ASH_GUEST_OS_GUEST_OS_REGISTRY_SERVICE_H_
#define CHROME_BROWSER_ASH_GUEST_OS_GUEST_OS_REGISTRY_SERVICE_H_
#include <map>
#include <set>
#include <string>
#include <string_view>
#include <vector>
#include "base/files/file_path.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/values.h"
#include "chrome/browser/apps/app_service/app_icon/app_icon_factory.h"
#include "chrome/browser/ash/crostini/crostini_simple_types.h"
#include "chrome/browser/ash/guest_os/guest_id.h"
#include "chrome/browser/ash/guest_os/guest_os_external_protocol_handler.h"
#include "chrome/browser/ash/guest_os/public/types.h"
#include "chromeos/ash/components/dbus/vm_applications/apps.pb.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/services/app_service/public/cpp/icon_types.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/resource/resource_scale_factor.h"
class Profile;
class PrefService;
namespace base {
class Clock;
class Time;
}
namespace apps {
class SvgIconTranscoder;
}
namespace vm_tools {
namespace apps {
class ApplicationList;
}
}
namespace guest_os {
using IconContentCallback = base::OnceCallback<void(std::string)>;
using CanHandleUrlCallback = base::RepeatingCallback<bool(const GURL&)>;
class GuestOsRegistryService : public KeyedService {
public:
class Registration {
public:
Registration(std::string app_id, base::Value pref);
Registration(Registration&& registration) = default;
Registration& operator=(Registration&& registration) = default;
Registration(const Registration&) = delete;
Registration& operator=(const Registration&) = delete;
~Registration();
std::string app_id() const { return app_id_; }
std::string DesktopFileId() const;
VmType VmType() const;
std::string VmName() const;
std::string ContainerName() const;
std::string Name() const;
std::string Exec() const;
std::string ExecutableFileName() const;
std::set<std::string> Extensions() const;
std::set<std::string> MimeTypes() const;
std::set<std::string> Keywords() const;
bool NoDisplay() const;
bool Terminal() const;
std::string PackageId() const;
base::Time InstallTime() const;
base::Time LastLaunchTime() const;
bool IsScaled() const;
bool CanUninstall() const;
guest_os::GuestId ToGuestId() const;
std::string StartupWmClass() const;
bool StartupNotify() const;
private:
std::string GetString(std::string_view key) const;
bool GetBool(std::string_view key) const;
base::Time GetTime(std::string_view key) const;
std::string GetLocalizedString(std::string_view key) const;
std::set<std::string> GetLocalizedList(std::string_view key) const;
std::string app_id_;
base::Value pref_;
};
class Observer {
public:
virtual void OnRegistryUpdated(
guest_os::GuestOsRegistryService* registry_service,
VmType vm_type,
const std::vector<std::string>& updated_apps,
const std::vector<std::string>& removed_apps,
const std::vector<std::string>& inserted_apps) {}
virtual void OnAppLastLaunchTimeUpdated(
VmType vm_type,
const std::string& app_id,
const base::Time& last_launch_time) {}
protected:
virtual ~Observer() = default;
};
explicit GuestOsRegistryService(Profile* profile);
GuestOsRegistryService(const GuestOsRegistryService&) = delete;
GuestOsRegistryService& operator=(const GuestOsRegistryService&) = delete;
~GuestOsRegistryService() override;
base::WeakPtr<GuestOsRegistryService> GetWeakPtr();
std::map<std::string, GuestOsRegistryService::Registration>
GetAllRegisteredApps() const;
std::map<std::string, GuestOsRegistryService::Registration> GetEnabledApps()
const;
std::map<std::string, GuestOsRegistryService::Registration> GetRegisteredApps(
VmType vm_type) const;
std::optional<GuestOsRegistryService::Registration> GetRegistration(
const std::string& app_id) const;
std::optional<GuestOsUrlHandler> GetHandler(const GURL& url) const;
void RegisterTransientUrlHandler(GuestOsUrlHandler handler,
CanHandleUrlCallback canHandleCallback);
base::FilePath GetIconPath(const std::string& app_id,
ui::ResourceScaleFactor scale_factor) const;
void LoadIcon(const std::string& app_id,
const apps::IconKey& icon_key,
apps::IconType icon_type,
int32_t size_hint_in_dip,
bool allow_placeholder_icon,
int fallback_icon_resource_id,
apps::LoadIconCallback callback);
void LoadIconFromVM(const std::string& app_id,
apps::IconType icon_type,
int32_t size_hint_in_dip,
ui::ResourceScaleFactor scale_factor,
apps::IconEffects icon_effects,
int fallback_icon_resource_id,
apps::LoadIconCallback callback);
void OnLoadIconFromVM(const std::string& app_id,
apps::IconType icon_type,
int32_t size_hint_in_dip,
apps::IconEffects icon_effects,
int fallback_icon_resource_id,
apps::LoadIconCallback callback,
std::string compressed_icon_data);
void RequestIcon(const std::string& app_id,
ui::ResourceScaleFactor scale_factor,
IconContentCallback callback);
void ClearApplicationList(VmType vm_type,
const std::string& vm_name,
const std::string& container_name);
void ClearApplicationListForContainer(VmType vm_type,
const std::string& vm_name,
const std::string& container_name);
void UpdateApplicationList(const vm_tools::apps::ApplicationList& app_list);
void ContainerBadgeColorChanged(const guest_os::GuestId& container_id);
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
void AppLaunched(const std::string& app_id);
void SetCurrentTime(base::Value::Dict& dictionary, const char* key) const;
void SetAppScaled(const std::string& app_id, bool scaled);
void SetClockForTesting(base::Clock* clock) { clock_ = clock; }
void ApplyContainerBadge(const std::optional<std::string>& app_id,
gfx::ImageSkia* image_skia);
static std::string GenerateAppId(const std::string& desktop_file_id,
const std::string& vm_name,
const std::string& container_name);
private:
base::FilePath GetAppPath(const std::string& app_id) const;
void RequestContainerAppIcon(const std::string& app_id,
ui::ResourceScaleFactor scale_factor);
void OnContainerAppIcon(const std::string& app_id,
ui::ResourceScaleFactor scale_factor,
bool success,
const std::vector<crostini::Icon>& icons);
void RemoveAppData(const std::string& app_id);
void ApplyContainerBadgeForImageSkiaIcon(SkColor badge_color,
gfx::ImageSkia* icon_out);
void ApplyContainerBadgeWithCallback(SkColor badge_color,
apps::LoadIconCallback callback,
apps::IconValuePtr icon);
void InvokeActiveIconCallbacks(std::string app_id,
ui::ResourceScaleFactor scale_factor,
std::string icon_content);
void TranscodeIconFromSvg(
base::FilePath svg_path,
base::FilePath png_path,
apps::IconType icon_type,
int32_t size_hint_in_dip,
apps::IconEffects icon_effects,
base::OnceCallback<void(apps::LoadIconCallback)> fallback,
apps::LoadIconCallback callback);
void OnSvgIconTranscoded(std::string app_id,
ui::ResourceScaleFactor scale_factor,
std::string svg_icon_content,
std::string png_icon_content);
const raw_ptr<Profile, DanglingUntriaged> profile_;
const raw_ptr<PrefService, DanglingUntriaged> prefs_;
base::FilePath base_icon_path_;
base::ObserverList<Observer>::Unchecked observers_;
raw_ptr<const base::Clock> clock_;
std::vector<std::pair<GuestOsUrlHandler, CanHandleUrlCallback>> url_handlers_;
std::map<std::pair<std::string, ui::ResourceScaleFactor>,
std::vector<IconContentCallback>>
active_icon_requests_;
std::map<std::string, uint32_t> retry_icon_requests_;
std::unique_ptr<apps::SvgIconTranscoder> svg_icon_transcoder_;
base::WeakPtrFactory<GuestOsRegistryService> weak_ptr_factory_{this};
};
}
#endif