chromium/chrome/browser/ash/app_restore/arc_ghost_window_handler.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_APP_RESTORE_ARC_GHOST_WINDOW_HANDLER_H_
#define CHROME_BROWSER_ASH_APP_RESTORE_ARC_GHOST_WINDOW_HANDLER_H_

#include "ash/components/arc/mojom/app.mojom.h"
#include "base/gtest_prod_util.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "components/exo/client_controlled_shell_surface.h"
#include "components/exo/wm_helper.h"

namespace app_restore {
struct AppRestoreData;
}  // namespace app_restore

namespace arc {
enum class GhostWindowType;
}  // namespace arc

namespace ash::full_restore {

// The ArcGhostWindowHandler class provides control for ARC ghost window.
class ArcGhostWindowHandler : public exo::WMHelper::LifetimeManager::Observer {
  // Map from window_session_id to exo::ClientControlledShellSurface.
  using ShellSurfaceMap =
      std::map<int, std::unique_ptr<exo::ClientControlledShellSurface>>;
  // Map from window_session_id to ::arc::mojom::WindowInfoPtr.
  using WindowInfoMap = std::map<int, ::arc::mojom::WindowInfoPtr>;

  // This class populates the exo::ShellSurfaceBase to PropertyHandler by
  // the corresponding window session id.
  class WindowSessionResolver : public exo::WMHelper::AppPropertyResolver {
   public:
    WindowSessionResolver() = default;
    WindowSessionResolver(const WindowSessionResolver&) = delete;
    WindowSessionResolver& operator=(const WindowSessionResolver&) = delete;
    ~WindowSessionResolver() override = default;

    // exo::WMHelper::AppPropertyResolver:
    void PopulateProperties(
        const Params& params,
        ui::PropertyHandler& out_properties_container) override;
  };

 public:
  // This class is used to notify observers that App and ghost window handler
  // states change.
  class Observer : public base::CheckedObserver {
   public:
    // Observer for app instance connection ready.
    virtual void OnAppInstanceConnected() {}

    // Observer for ghost window close event.
    virtual void OnWindowCloseRequested(int window_id) {}

    // Observer for ARC App specific state updates.
    virtual void OnAppStatesUpdate(const std::string& app_id,
                                   bool ready,
                                   bool need_fixup) {}

    // Observer for ghost window handler destroy.
    virtual void OnGhostWindowHandlerDestroy() {}

   protected:
    ~Observer() override = default;
  };

  ArcGhostWindowHandler();
  ArcGhostWindowHandler(const ArcGhostWindowHandler&) = delete;
  ArcGhostWindowHandler& operator=(const ArcGhostWindowHandler&) = delete;
  ~ArcGhostWindowHandler() override;

  // ArcGhostWindowHandler is created and destroyed with the
  // `AppRestore::AppRestoreArcTaskHandler`.
  // ArcGhostWindowHandler::Get may be nullptr if accessed outside the expected
  // lifetime.
  static ArcGhostWindowHandler* Get();

  // Returns true if the ghost window is created and launched. Otherwise,
  // returns false. virtual for test usage.
  // TODO(sstan): Add mock class.
  virtual bool LaunchArcGhostWindow(
      const std::string& app_id,
      int32_t session_id,
      ::app_restore::AppRestoreData* restore_data);

  bool UpdateArcGhostWindowType(int32_t session_id,
                                arc::GhostWindowType window_type);

  void CloseWindow(int session_id);

  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);
  bool HasObserver(Observer* observer);

  void OnAppInstanceConnected();

  void OnAppStatesUpdate(std::string app_id, bool ready, bool need_fixup);

  void OnWindowInfoUpdated(int window_id,
                           int state,
                           int64_t display_id,
                           gfx::Rect bounds);

  int ghost_window_pop_count() { return ghost_window_pop_count_; }

  // exo::WMHelper::LifetimeManager::Observer:
  void OnDestroyed() override;

 protected:
  FRIEND_TEST_ALL_PREFIXES(ArcGhostWindowHandlerTest,
                           UpdateOverrideBoundsIfGeneralState);
  FRIEND_TEST_ALL_PREFIXES(ArcGhostWindowHandlerTest,
                           NotUpdateOverrideBoundsIfStateIsDefault);

 private:
  bool is_app_instance_connected_ = false;

  int ghost_window_pop_count_ = 0;

  // Map window session id to ClientControlledShellSurface.
  ShellSurfaceMap session_id_to_shell_surface_;

  // Map window session id to pending window info. Before ARC app instance
  // connection establish, all of window info update will be saved here as
  // pending update info.
  WindowInfoMap session_id_to_pending_window_info_;

  base::ObserverList<Observer> observer_list_;

  base::WeakPtrFactory<ArcGhostWindowHandler> weak_ptr_factory_{this};
};

}  // namespace ash::full_restore

#endif  // CHROME_BROWSER_ASH_APP_RESTORE_ARC_GHOST_WINDOW_HANDLER_H_