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

// Copyright 2021 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_CHROME_APP_WINDOW_TRACKER_ASH_H_
#define CHROME_BROWSER_ASH_CROSAPI_CHROME_APP_WINDOW_TRACKER_ASH_H_

#include <map>
#include <string>

#include "base/memory/raw_ptr.h"
#include "base/scoped_multi_source_observation.h"
#include "base/scoped_observation.h"
#include "chromeos/crosapi/mojom/app_window_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 crosapi {

// Implements the crosapi interface for ChromeAppWindowTracker Ash-Chrome on the
// UI thread. This is responsible for tracking windows associated with chrome
// apps, and populating the shelf with their metadata.
//
// There are two different IPC channels whose information must be combined to
// create a shelf item: aura::Window* via Wayland and app_id via crosapi. This
// class tracks both pending aura::Windows and pending app_ids. Once both are
// present, this class hands off tracking/ownership to
// StandaloneBrowserExtensionAppShelfItemDelegate.
class ChromeAppWindowTrackerAsh : public mojom::AppWindowTracker,
                                  public aura::EnvObserver,
                                  public aura::WindowObserver {
 public:
  ChromeAppWindowTrackerAsh();
  ChromeAppWindowTrackerAsh(const ChromeAppWindowTrackerAsh&) = delete;
  ChromeAppWindowTrackerAsh& operator=(const ChromeAppWindowTrackerAsh&) =
      delete;
  ~ChromeAppWindowTrackerAsh() override;

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

  // mojom::AppWindowTracker overrides:
  void OnAppWindowAdded(const std::string& app_id,
                        const std::string& window_id) override;
  void OnAppWindowRemoved(const std::string& app_id,
                          const std::string& window_id) override;

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

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

  // public and virtual for testing.
  // Given a newly created chrome app window, either creates a shelf item
  // controller or updates the existing shelf item controller.
  virtual void UpdateShelf(const std::string& app_id, aura::Window* window);

 protected:
  // Holds metadata associated with a chrome app window. Once both pieces of
  // metadata are available, this class has sufficient information to either
  // create a StandaloneBrowserExtensionAppShelfItemController, or else update
  // an existing one.
  struct WindowData {
    std::string app_id;
    raw_ptr<aura::Window> window = nullptr;
  };

 private:
  // If both pieces of metadata are present, then stop tracking the window as
  // it's no longer pending.
  void CheckWindowNoLongerPending(const std::string& window_id);

  // A map from |window_id| to WindowData. Note that Lacros windows that are not
  // associated with chrome apps will also be present in this map. They will be
  // removed when the window is closed.
  std::map<std::string, WindowData> pending_window_ids_;

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

  // Observes windows in |pending_window_ids_| for destruction.
  base::ScopedMultiSourceObservation<aura::Window, aura::WindowObserver>
      window_observations_{this};

  // This class supports any number of connections. This allows the client to
  // have multiple, potentially thread-affine, remotes.
  mojo::ReceiverSet<mojom::AppWindowTracker> receivers_;
};

}  // namespace crosapi

#endif  // CHROME_BROWSER_ASH_CROSAPI_CHROME_APP_WINDOW_TRACKER_ASH_H_