chromium/chrome/browser/ash/crosapi/lacros_shelf_item_tracker.h

// 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.
#ifndef CHROME_BROWSER_ASH_CROSAPI_LACROS_SHELF_ITEM_TRACKER_H_
#define CHROME_BROWSER_ASH_CROSAPI_LACROS_SHELF_ITEM_TRACKER_H_

#include <map>
#include <optional>
#include <string>

#include "base/scoped_multi_source_observation.h"
#include "base/scoped_observation.h"
#include "chromeos/crosapi/mojom/lacros_shelf_item_tracker.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "ui/aura/env.h"
#include "ui/aura/env_observer.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"

namespace ash {
class ShelfItemDelegate;
struct ShelfID;
}  // namespace ash

namespace crosapi {

// Receives Lacros windows and tracks them.
// Also tracks the destruction of the windows.
// Based on the tracked windows, this class can add new items to the Shelf and
// remove existing items from the Shelf.
class LacrosShelfItemTracker : public mojom::LacrosShelfItemTracker,
                               public aura::EnvObserver,
                               public aura::WindowObserver {
 public:
  LacrosShelfItemTracker();
  ~LacrosShelfItemTracker() override;

  void BindReceiver(
      mojo::PendingReceiver<mojom::LacrosShelfItemTracker> receiver);

  // mojom::LacrosShelfItemTracker override:
  void AddOrUpdateWindow(mojom::WindowDataPtr window_data) override;

  // aura::WindowObserver override:
  void OnWindowDestroying(aura::Window* window) override;

  // aura::EnvObserver override:
  void OnWindowInitialized(aura::Window* window) override;

 protected:
  // Protected virtual for testing.
  virtual ash::ShelfItemDelegate* AddOrUpdateShelfItemAndReturnDelegate(
      mojom::WindowDataPtr window_data);

  // Protected virtual for testing.
  virtual void RemoveFromShelf(const ash::ShelfID& shelf_id);

 private:
  struct WindowInfo {
    WindowInfo();
    ~WindowInfo();
    raw_ptr<aura::Window> window;
    std::optional<mojom::WindowDataPtr> window_data;
  };

  // If |window_id| is present in both |all_lacros_windows_| and
  // |tracked_windows_| then we add the window to shelf.
  void MaybeAddToShelf(const std::string& window_id);

  // Virtual for testing.
  virtual std::unique_ptr<ash::ShelfItemDelegate> CreateDelegateByInstanceType(
      const ash::ShelfID& shelf_id,
      mojom::InstanceType instance_type);

  // A map for all windows whose app id starts with |LacrosAppIdPrefix| when
  // initialized.
  std::map<std::string, WindowInfo> lacros_prefixed_windows_;

  // A map for all windows associated with a Shelf item this instance has
  // created. Key: unique ID for a Shelf item. Value: a set of all window ID
  // associated with the item.
  std::map<std::string, std::set<std::string>> shelf_item_windows_;

  // Observes all Lacros windows for destruction.
  base::ScopedMultiSourceObservation<aura::Window, aura::WindowObserver>
      lacros_prefixed_windows_observations_{this};

  // Observes aura::Env for newly created windows.
  base::ScopedObservation<aura::Env, EnvObserver> env_observation_{this};

  // Supports multiple receivers.
  mojo::ReceiverSet<mojom::LacrosShelfItemTracker> receivers_;
};

}  // namespace crosapi

#endif  // CHROME_BROWSER_ASH_CROSAPI_LACROS_SHELF_ITEM_TRACKER_H_