chromium/components/app_restore/arc_save_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 COMPONENTS_APP_RESTORE_ARC_SAVE_HANDLER_H_
#define COMPONENTS_APP_RESTORE_ARC_SAVE_HANDLER_H_

#include <map>
#include <memory>
#include <set>
#include <utility>

#include "base/component_export.h"
#include "base/files/file_path.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"

namespace app_restore {
struct AppLaunchInfo;
struct WindowInfo;
}  // namespace app_restore

namespace ash {
namespace full_restore {
class FullRestoreAppLaunchHandlerArcAppBrowserTest;
}
}  // namespace ash

namespace aura {
class Window;
}

namespace full_restore {

// ArcSaveHandler is a helper class for FullRestoreSaveHandler to handle ARC app
// windows special cases, e.g. ARC task creation, ARC session id, etc.
//
// Task id is saved as the window id. Session id is generated when launch the
// ARC app, and sent back as a parameter of OnTaskCreated, to connect the launch
// parameters with the task id. `session_id_to_app_launch_info_` saves the
// mapping from the session id to the launch parameter.
//
// When the task is created, in OnTaskCreated callback, get the launch info from
// `session_id_to_app_launch_info_` with `session id`, and save the launch info
// using the task is as the window id.
//
// For ghost window, session id is used as the the window id before the task is
// created. When the task is created, window id is modified to use the task id
// as the window id.
class COMPONENT_EXPORT(APP_RESTORE) ArcSaveHandler {
 public:
  using AppLaunchInfoPtr = std::unique_ptr<app_restore::AppLaunchInfo>;
  using SessionIdMap =
      std::map<int32_t, std::pair<AppLaunchInfoPtr, base::TimeTicks>>;

  explicit ArcSaveHandler(const base::FilePath& profile_path);
  ArcSaveHandler(const ArcSaveHandler&) = delete;
  ArcSaveHandler& operator=(const ArcSaveHandler&) = delete;
  ~ArcSaveHandler();

  // Saves |app_launch_info| to |arc_session_id_to_app_launch_info_|, and wait
  // for the ARC task to be created.
  void SaveAppLaunchInfo(AppLaunchInfoPtr app_launch_info);

  // Saves |window_info|.
  void ModifyWindowInfo(const app_restore::WindowInfo& window_info);

  // Invoked when |window| is initialized.
  void OnWindowInitialized(aura::Window* window);

  // Invoked when |window| is destroyed.
  void OnWindowDestroyed(aura::Window* window);

  // Invoked when the task is created for an ARC app.
  void OnTaskCreated(const std::string& app_id,
                     int32_t task_id,
                     int32_t session_id);

  // Invoked when the task is destroyed for an ARC app.
  void OnTaskDestroyed(int32_t task_id);

  // Invoked when Google Play Store is enabled or disabled.
  void OnArcPlayStoreEnabledChanged(bool enabled);

  // Invoked when the task theme color is updated for an ARC app.
  void OnTaskThemeColorUpdated(int32_t task_id,
                               uint32_t primary_color,
                               uint32_t status_bar_color);

  // Generates the ARC session id (0 - 1,000,000,000) for save ARC apps.
  int32_t GetArcSessionId();

  // Returns the app id that associates with |window|.
  std::string GetAppId(aura::Window* window);

  void set_is_connection_ready(bool is_connection_ready) {
    is_connection_ready_ = is_connection_ready;
  }

 private:
  friend class FullRestoreSaveHandlerTestApi;
  friend class ash::full_restore::FullRestoreAppLaunchHandlerArcAppBrowserTest;

  // Starts the timer to check whether a task is created for the app launching
  // (if timer isn't already running).
  void MaybeStartCheckTimer();

  // Check whether a task is created for each app launching. If not, remove the
  // app launching record.
  void CheckTasksForAppLaunching();

  // The user profile path for ARC app.
  base::FilePath profile_path_;

  int32_t session_id_ = 0;

  // Specify whether the ARC instance connection is ready.
  bool is_connection_ready_ = false;

  // The map from the ARC session id to the app launch info.
  SessionIdMap session_id_to_app_launch_info_;

  // The map from the task id to the app id. The task id is saved in the window
  // property. This map is used to find the app id when save the window info.
  std::map<int32_t, std::string> task_id_to_app_id_;

  // The map from the session id to the app id for ghost windows, so that we can
  // save the restore data, once the ghost window is created.
  std::map<int32_t, std::string> ghost_window_session_id_to_app_id_;

  // ARC app tasks could be created after the window initialized.
  // |arc_window_candidates_| is used to record those initialized ARC app
  // windows, whose tasks have not been created. Once the task for the window is
  // created, the window is removed from |arc_window_candidates_|.
  std::set<raw_ptr<aura::Window, SetExperimental>> arc_window_candidates_;

  // Timer used to check whether a task is created. App launching could have
  // failed. If an app is launched without a task created, the launch record
  // should be removed from |session_id_to_app_launch_info_|.
  base::RepeatingTimer check_timer_;

  base::WeakPtrFactory<ArcSaveHandler> weak_factory_{this};
};

}  // namespace full_restore

#endif  // COMPONENTS_APP_RESTORE_ARC_SAVE_HANDLER_H_