iwa: Integrate IWA installer with ChromeOS Shelf - Ash implementation



Bug: 1479140
Change-Id: I220ea52e482c07d88809d2fe89532f9af00804d7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5186292
Reviewed-by: Stefan Kuhne <skuhne@chromium.org>
Commit-Queue: Zelin Liu <zelin@chromium.org>
Reviewed-by: Robbie McElrath <rmcelrath@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1249079}
diff --git a/chrome/browser/ui/ash/shelf/isolated_web_app_installer_shelf_item_controller.cc b/chrome/browser/ui/ash/shelf/isolated_web_app_installer_shelf_item_controller.cc
index 14470a8..3a4fc3b 100644
--- a/chrome/browser/ui/ash/shelf/isolated_web_app_installer_shelf_item_controller.cc
+++ b/chrome/browser/ui/ash/shelf/isolated_web_app_installer_shelf_item_controller.cc
@@ -1,6 +1,7 @@
 // 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/ui/ash/shelf/isolated_web_app_installer_shelf_item_controller.h"
 
 #include "ash/public/cpp/resources/grit/ash_public_unscaled_resources.h"
@@ -17,16 +18,14 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 
-namespace {
-
-gfx::ImageSkia GetDefaultInstallerShelfIcon() {
+// static
+gfx::ImageSkia
+IsolatedWebAppInstallerShelfItemController::GetDefaultInstallerShelfIcon() {
   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
   // TODO(crbug.com/1515460): Replace the placeholder default icon.
   return *rb.GetImageSkiaNamed(IDR_SETTINGS_LOGO_192);
 }
 
-}  // namespace
-
 IsolatedWebAppInstallerShelfItemController::
     IsolatedWebAppInstallerShelfItemController(const ash::ShelfID& shelf_id)
     : LacrosShelfItemController(shelf_id) {
@@ -36,7 +35,12 @@
 }
 
 IsolatedWebAppInstallerShelfItemController::
-    ~IsolatedWebAppInstallerShelfItemController() {}
+    ~IsolatedWebAppInstallerShelfItemController() {
+  if (window_) {
+    window_->RemoveObserver(this);
+    window_ = nullptr;
+  }
+}
 
 void IsolatedWebAppInstallerShelfItemController::ItemSelected(
     std::unique_ptr<ui::Event> event,
@@ -72,11 +76,7 @@
     return;
   }
 
-  // Post a task to delete later to avoid dangling raw_ptr.
-  base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
-      FROM_HERE,
-      base::BindOnce(&ash::window_util::CloseWidgetForWindow, window_));
-  window_ = nullptr;
+  ash::window_util::CloseWidgetForWindow(window_);
 }
 
 void IsolatedWebAppInstallerShelfItemController::AddWindow(
@@ -86,9 +86,15 @@
   // `window`.
   CHECK(!window_ || window_ == window);
   window_ = window;
+  window_->AddObserver(this);
   UpdateShelfItem();
 }
 
+void IsolatedWebAppInstallerShelfItemController::OnWindowDestroying(
+    aura::Window* window) {
+  window_ = nullptr;
+}
+
 void IsolatedWebAppInstallerShelfItemController::UpdateShelfItem() {
   const ash::ShelfItem* current_item =
       ash::ShelfModel::Get()->ItemByID(shelf_id());
diff --git a/chrome/browser/ui/ash/shelf/isolated_web_app_installer_shelf_item_controller.h b/chrome/browser/ui/ash/shelf/isolated_web_app_installer_shelf_item_controller.h
index d56b0123..db5cfe629 100644
--- a/chrome/browser/ui/ash/shelf/isolated_web_app_installer_shelf_item_controller.h
+++ b/chrome/browser/ui/ash/shelf/isolated_web_app_installer_shelf_item_controller.h
@@ -9,7 +9,7 @@
 
 #include "chrome/browser/ui/ash/shelf/lacros_shelf_item_controller.h"
 #include "ui/aura/window_observer.h"
-#include "ui/wm/public/activation_change_observer.h"
+#include "ui/gfx/image/image_skia.h"
 
 namespace ash {
 struct ShelfID;
@@ -25,13 +25,16 @@
 // has its own IsolatedWebAppInstallerShelfItemController. This class tracks
 // the window it starts with, and prohibits tracking of additional windows.
 class IsolatedWebAppInstallerShelfItemController
-    : public LacrosShelfItemController {
+    : public LacrosShelfItemController,
+      aura::WindowObserver {
  public:
   explicit IsolatedWebAppInstallerShelfItemController(
       const ash::ShelfID& shelf_id);
 
   ~IsolatedWebAppInstallerShelfItemController() override;
 
+  static gfx::ImageSkia GetDefaultInstallerShelfIcon();
+
   // ash::ShelfItemDelegate overrides:
   void ItemSelected(std::unique_ptr<ui::Event> event,
                     int64_t display_id,
@@ -50,6 +53,9 @@
   // LacrosShelfItemController overrides:
   void AddWindow(aura::Window* window) override;
 
+  // aura::WindowObserver
+  void OnWindowDestroying(aura::Window* window) override;
+
  private:
   void UpdateShelfItem();
 
diff --git a/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view_controller.cc b/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view_controller.cc
index 77145e6..50b5319 100644
--- a/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view_controller.cc
+++ b/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view_controller.cc
@@ -47,7 +47,10 @@
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "ash/public/cpp/shelf_model.h"
+#include "ash/public/cpp/shelf_types.h"
 #include "ash/webui/settings/public/constants/routes.mojom.h"
+#include "chrome/browser/ui/ash/shelf/isolated_web_app_installer_shelf_item_controller.h"
 #include "chrome/browser/ui/settings_window_manager_chromeos.h"
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
@@ -196,8 +199,6 @@
   if (!window_) {
     return;
   }
-// Currently only supports Lacros.
-// TODO(crbug.com/1515466): Ash Implementation.
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
   chromeos::LacrosService* lacros_service = chromeos::LacrosService::Get();
   if (lacros_service->IsAvailable<crosapi::mojom::LacrosShelfItemTracker>()) {
@@ -215,8 +216,37 @@
     lacros_service->GetRemote<crosapi::mojom::LacrosShelfItemTracker>()
         ->AddOrUpdateWindow(std::move(window_data));
   }
-
 #endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  ash::ShelfModel* shelf_model = ash::ShelfModel::Get();
+  ash::ShelfID shelf_id = ash::ShelfID(instance_id_);
+
+  ash::ShelfItem item;
+  item.id = shelf_id;
+  item.status = ash::STATUS_RUNNING;
+  item.type = ash::TYPE_APP;
+  if (icon_.isNull()) {
+    item.image = IsolatedWebAppInstallerShelfItemController::
+        GetDefaultInstallerShelfIcon();
+  } else {
+    item.image = icon_;
+  }
+
+  auto item_index = shelf_model->ItemIndexByID(shelf_id);
+  if (item_index == -1) {
+    // Add as new item to the shelf.
+    auto delegate =
+        std::make_unique<IsolatedWebAppInstallerShelfItemController>(shelf_id);
+    shelf_model->Add(item, std::move(delegate));
+    static_cast<LacrosShelfItemController*>(
+        shelf_model->GetShelfItemDelegate(shelf_id))
+        ->AddWindow(window_);
+  } else {
+    // Update existing item on the shelf.
+    shelf_model->Set(item_index, item);
+  }
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 void IsolatedWebAppInstallerViewController::SetIcon(gfx::ImageSkia icon) {
@@ -308,6 +338,15 @@
 }
 
 void IsolatedWebAppInstallerViewController::OnComplete() {
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  ash::ShelfModel* shelf_model = ash::ShelfModel::Get();
+  ash::ShelfID shelf_id = ash::ShelfID(instance_id_);
+  int index = shelf_model->ItemIndexByID(shelf_id);
+  if (-1 != index) {
+    shelf_model->RemoveItemAt(index);
+  }
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
   view_ = nullptr;
   dialog_delegate_ = nullptr;
   std::move(completion_callback_).Run();