chromium/chrome/browser/ash/app_list/app_service/app_service_promise_app_model_builder.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_model_builder.h"
#include <ostream>

#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_registry_cache.h"
#include "chrome/browser/ash/app_list/app_list_controller_delegate.h"
#include "chrome/browser/ash/app_list/app_list_model_builder.h"
#include "chrome/browser/ash/app_list/app_service/app_service_promise_app_item.h"

AppServicePromiseAppModelBuilder::AppServicePromiseAppModelBuilder(
    AppListControllerDelegate* controller)
    : AppListModelBuilder(controller, AppServicePromiseAppItem::kItemType) {}

AppServicePromiseAppModelBuilder::~AppServicePromiseAppModelBuilder() = default;

void AppServicePromiseAppModelBuilder::BuildModel() {
  CHECK(!promise_app_registry_cache_observation_.IsObserving());
  promise_app_registry_cache_observation_.Observe(
      apps::AppServiceProxyFactory::GetForProfile(profile())
          ->PromiseAppRegistryCache());

  // No need to iterate through the registry cache and insert existing promise
  // apps into the model since the registry cache will be empty on start up.
  // Promise apps in the cache only get registered/ created when we start new
  // app installations, at which point the AppServicePromiseAppModelBuilder
  // should already exist. This will change in the future when we support ARC
  // default promise apps.
  // TODO(b/286981938): Insert existing promise app entries from the registry
  // cache.
}

// Update the App Service Promise App Item for the appropriate promise app if
// one already exists. Otherwise, create a new one.
void AppServicePromiseAppModelBuilder::OnPromiseAppUpdate(
    const apps::PromiseAppUpdate& update) {
  ChromeAppListItem* item = GetAppItem(update.PackageId().ToString());
  bool show = update.ShouldShow();
  if (item) {
    CHECK(item->GetItemType() == AppServicePromiseAppItem::kItemType);
    static_cast<AppServicePromiseAppItem*>(item)->OnPromiseAppUpdate(update);

    if (update.StatusChanged() &&
        update.Status() == apps::PromiseStatus::kSuccess &&
        item->GetPromisedItemId().empty()) {
      if (service()) {
        service()->CopyPromiseItemAttributesToItem(
            update.PackageId().ToString(), update.InstalledAppId());
      }
    }

    if (!show) {
      RemoveApp(update.PackageId().ToString(), false);
    }
  } else if (show) {
    std::optional<app_list::AppListSyncableService::LinkedPromiseAppSyncItem>
        linked_sync_item =
            service() ? service()->CreateLinkedPromiseSyncItemIfAvailable(
                            update.PackageId().ToString())
                      : std::nullopt;
    if (linked_sync_item) {
      InsertApp(std::make_unique<AppServicePromiseAppItem>(
          profile(), model_updater(), update, linked_sync_item->linked_item_id,
          linked_sync_item->promise_item));
    } else {
      InsertApp(std::make_unique<AppServicePromiseAppItem>(
          profile(), model_updater(), update, "", nullptr));
    }
  }
}

void AppServicePromiseAppModelBuilder::OnPromiseAppRemoved(
    const apps::PackageId& package_id) {
  RemoveApp(package_id.ToString(), false);
}

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