chromium/components/app_restore/lacros_save_handler.cc

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/app_restore/lacros_save_handler.h"

#include <memory>

#include "components/app_constants/constants.h"
#include "components/app_restore/app_launch_info.h"
#include "components/app_restore/app_restore_utils.h"
#include "components/app_restore/full_restore_save_handler.h"
#include "components/app_restore/window_info.h"
#include "components/app_restore/window_properties.h"
#include "ui/aura/window.h"

namespace full_restore {

LacrosSaveHandler::LacrosSaveHandler(const base::FilePath& profile_path)
    : profile_path_(profile_path) {}

LacrosSaveHandler::~LacrosSaveHandler() = default;

void LacrosSaveHandler::OnWindowInitialized(aura::Window* window) {
  const std::string lacros_window_id = app_restore::GetLacrosWindowId(window);

  std::string app_id;
  int32_t window_id = ++window_id_;
  std::unique_ptr<app_restore::AppLaunchInfo> app_launch_info;

  auto it = lacros_window_id_to_app_id_.find(lacros_window_id);
  if (it != lacros_window_id_to_app_id_.end()) {
    app_id = it->second;
    app_launch_info = FullRestoreSaveHandler::GetInstance()->FetchAppLaunchInfo(
        profile_path_, app_id);
    if (!app_launch_info)
      return;
    app_launch_info->window_id = window_id;
  } else {
    app_id = app_constants::kLacrosAppId;
    app_launch_info =
        std::make_unique<app_restore::AppLaunchInfo>(app_id, window_id);
  }

  window_candidates_[lacros_window_id].app_id = app_id;
  window_candidates_[lacros_window_id].window_id = window_id;

  // Don't overwrite window info if `window_id` was already saved by
  // OnAppWindowAdded.
  if (it == lacros_window_id_to_app_id_.end()) {
    // TODO(sophiewen): Move logic to OnWindowInitialized instead of calling
    // OnBrowserWindowAdded.
    OnBrowserWindowAdded(window, false);
    return;
  }

  FullRestoreSaveHandler::GetInstance()->AddAppLaunchInfo(
      profile_path_, std::move(app_launch_info));
}

void LacrosSaveHandler::OnWindowDestroyed(aura::Window* window) {
  const std::string lacros_window_id = app_restore::GetLacrosWindowId(window);
  lacros_window_id_to_app_id_.erase(lacros_window_id);

  auto it = window_candidates_.find(lacros_window_id);
  if (it == window_candidates_.end())
    return;

  FullRestoreSaveHandler::GetInstance()->RemoveAppRestoreData(
      profile_path_, it->second.app_id, it->second.window_id);

  window_candidates_.erase(it);
}

void LacrosSaveHandler::OnBrowserWindowAdded(aura::Window* const window,
                                             bool is_browser_app) {
  const std::string lacros_window_id = app_restore::GetLacrosWindowId(window);
  std::unique_ptr<app_restore::WindowInfo> window_info;
  auto* save_handler = FullRestoreSaveHandler::GetInstance();
  DCHECK(save_handler);

  uint32_t browser_session_id =
      static_cast<uint32_t>(window->GetProperty(app_restore::kWindowIdKey));

  // Ephemeral windows have a`browser_session_id` of 0 by default.
  if (!browser_session_id) {
    return;
  }

  auto it = window_candidates_.find(lacros_window_id);
  if (it != window_candidates_.end() &&
      it->second.window_id != browser_session_id) {
    // If the window has been created and saved using different window id, get
    // the current window info, then remove the restore data for the old window
    // id, and re-save the restore data with the new `browser_session_id`.
    window_info = save_handler->GetWindowInfo(profile_path_, it->second.app_id,
                                              it->second.window_id);

    save_handler->RemoveAppRestoreData(profile_path_, it->second.app_id,
                                       it->second.window_id);
  }

  window_candidates_[lacros_window_id].app_id = app_constants::kLacrosAppId;
  window_candidates_[lacros_window_id].window_id = browser_session_id;

  auto app_launch_info = std::make_unique<app_restore::AppLaunchInfo>(
      app_constants::kLacrosAppId, browser_session_id);
  app_launch_info->browser_extra_info.app_type_browser = is_browser_app;
  save_handler->AddAppLaunchInfo(profile_path_, std::move(app_launch_info));

  if (window_info) {
    save_handler->ModifyWindowInfo(profile_path_, app_constants::kLacrosAppId,
                                   browser_session_id, *window_info);
  }
}

void LacrosSaveHandler::OnAppWindowAdded(const std::string& app_id,
                                         const std::string& lacros_window_id) {
  auto it = window_candidates_.find(lacros_window_id);
  if (it == window_candidates_.end()) {
    // If the window is not created yet, save the app id to
    // `lacros_window_id_to_app_id_` to wait for the window.
    lacros_window_id_to_app_id_[lacros_window_id] = app_id;
    return;
  }

  // If the window has been created, get the app launch info and the current
  // window info, then remove the restore data for lacros browser app id, and
  // re-save the restore data for the Chrome app id.

  auto* save_handler = FullRestoreSaveHandler::GetInstance();
  DCHECK(save_handler);
  auto window_info = save_handler->GetWindowInfo(
      profile_path_, it->second.app_id, it->second.window_id);

  save_handler->RemoveAppRestoreData(profile_path_, it->second.app_id,
                                     it->second.window_id);

  it->second.app_id = app_id;
  auto app_launch_info =
      save_handler->FetchAppLaunchInfo(profile_path_, app_id);
  if (!app_launch_info)
    return;
  app_launch_info->window_id = it->second.window_id;

  save_handler->AddAppLaunchInfo(profile_path_, std::move(app_launch_info));
  save_handler->ModifyWindowInfo(profile_path_, app_id, it->second.window_id,
                                 *window_info);
}

void LacrosSaveHandler::OnAppWindowRemoved(
    const std::string& app_id,
    const std::string& lacros_window_id) {
  lacros_window_id_to_app_id_.erase(lacros_window_id);
}

void LacrosSaveHandler::ModifyWindowInfo(
    const app_restore::WindowInfo& window_info) {
  auto it = window_candidates_.find(
      app_restore::GetLacrosWindowId(window_info.window));
  if (it != window_candidates_.end()) {
    FullRestoreSaveHandler::GetInstance()->ModifyWindowInfo(
        profile_path_, it->second.app_id, it->second.window_id, window_info);
  }
}

std::string LacrosSaveHandler::GetAppId(aura::Window* window) {
  auto it = window_candidates_.find(app_restore::GetLacrosWindowId(window));
  return it != window_candidates_.end() ? it->second.app_id : std::string();
}

int LacrosSaveHandler::GetLacrosChromeAppWindowId(aura::Window* window) const {
  auto it = window_candidates_.find(app_restore::GetLacrosWindowId(window));
  // Window ids start at 0. If we cannot find a corresponding window, return -1
  // so we don't fetch the wrong window data.
  return it != window_candidates_.end() ? it->second.window_id : -1;
}

}  // namespace full_restore