chromium/chrome/browser/ash/app_list/app_service/app_service_promise_app_icon_loader.cc

// 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/ash/app_list/app_service/app_service_promise_app_icon_loader.h"

#include <string>

#include "ash/constants/ash_features.h"
#include "ash/public/cpp/shelf_types.h"
#include "base/functional/callback_helpers.h"
#include "chrome/browser/apps/app_service/app_icon/app_icon_util.h"
#include "chrome/browser/apps/app_service/app_service_proxy.h"
#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
#include "chrome/browser/apps/app_service/promise_apps/promise_app.h"
#include "chrome/browser/apps/app_service/promise_apps/promise_app_registry_cache.h"
#include "chrome/browser/apps/app_service/promise_apps/promise_app_service.h"
#include "chrome/browser/apps/app_service/promise_apps/promise_app_update.h"
#include "chrome/browser/apps/app_service/promise_apps/promise_app_utils.h"
#include "chrome/browser/ash/app_list/app_service/app_service_app_icon_loader.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/ash/shelf/shelf_controller_helper.h"
#include "components/services/app_service/public/cpp/icon_effects.h"
#include "components/services/app_service/public/cpp/package_id.h"

AppServicePromiseAppIconLoader::AppServicePromiseAppIconLoader(
    Profile* profile,
    int resource_size_in_dip,
    AppIconLoaderDelegate* delegate)
    : AppIconLoader(profile, resource_size_in_dip, delegate) {
  promise_app_registry_cache_observation_.Observe(
      apps::AppServiceProxyFactory::GetForProfile(profile)
          ->PromiseAppRegistryCache());
}

AppServicePromiseAppIconLoader::~AppServicePromiseAppIconLoader() = default;

bool AppServicePromiseAppIconLoader::CanLoadImageForApp(const std::string& id) {
  return AppServicePromiseAppIconLoader::CanLoadImage(profile(), id);
}

// static
bool AppServicePromiseAppIconLoader::CanLoadImage(Profile* profile,
                                                  const std::string& id) {
  if (!ash::features::ArePromiseIconsEnabled()) {
    return false;
  }
  if (!apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)) {
    return false;
  }
  return apps::AppServiceProxyFactory::GetForProfile(profile)
      ->PromiseAppRegistryCache()
      ->GetPromiseAppForStringPackageId(id);
}

void AppServicePromiseAppIconLoader::FetchImage(const std::string& id) {
  const apps::PromiseApp* promise_app =
      apps::AppServiceProxyFactory::GetForProfile(profile())
          ->PromiseAppRegistryCache()
          ->GetPromiseAppForStringPackageId(id);
  if (!promise_app) {
    return;
  }
  CallLoadIcon(apps::PackageId::FromString(id).value(),
               apps::IconEffects::kCrOsStandardMask);
}

void AppServicePromiseAppIconLoader::ClearImage(const std::string& id) {
  // The image isn't saved in the icon loader, so we don't need to clear
  // anything.
}

void AppServicePromiseAppIconLoader::UpdateImage(const std::string& id) {
  // Updating the image is the same as fetching the image, which reapplies
  // effects for the current promise status.
  FetchImage(id);
}

void AppServicePromiseAppIconLoader::OnPromiseAppUpdate(
    const apps::PromiseAppUpdate& update) {
  if (!update.StatusChanged()) {
    return;
  }
  if (IsPromiseAppCompleted(update.Status())) {
    return;
  }
  CallLoadIcon(update.PackageId(), apps::IconEffects::kCrOsStandardMask);
}

void AppServicePromiseAppIconLoader::OnPromiseAppRegistryCacheWillBeDestroyed(
    apps::PromiseAppRegistryCache* cache) {
  promise_app_registry_cache_observation_.Reset();
}

void AppServicePromiseAppIconLoader::CallLoadIcon(
    const apps::PackageId& package_id,
    apps::IconEffects icon_effects) {
  apps::AppServiceProxyFactory::GetForProfile(profile())->LoadPromiseIcon(
      package_id, icon_size_in_dip(), icon_effects,
      base::BindOnce(&AppServicePromiseAppIconLoader::OnLoadIcon,
                     weak_ptr_factory_.GetWeakPtr(), package_id));
}

void AppServicePromiseAppIconLoader::OnLoadIcon(
    const apps::PackageId& package_id,
    apps::IconValuePtr icon_value) {
  gfx::ImageSkia image = icon_value->uncompressed;
  delegate()->OnAppImageUpdated(package_id.ToString(), image,
                                icon_value->is_placeholder_icon,
                                /*badge_image=*/std::nullopt);
}