| // 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. |
| |
| #include "components/app_restore/arc_read_handler.h" |
| |
| #include <algorithm> |
| #include <memory> |
| |
| #include "base/containers/contains.h" |
| #include "components/app_restore/app_launch_info.h" |
| #include "components/app_restore/app_restore_info.h" |
| #include "components/app_restore/app_restore_utils.h" |
| #include "components/app_restore/window_info.h" |
| #include "components/app_restore/window_properties.h" |
| #include "ui/aura/window.h" |
| |
| namespace app_restore { |
| namespace { |
| |
| bool IsValidRestoreWindowId(int32_t restore_window_id) { |
| return restore_window_id != 0 && |
| restore_window_id != kParentToHiddenContainer; |
| } |
| |
| } // namespace |
| |
| ArcReadHandler::ArcReadHandler(const base::FilePath& profile_path, |
| Delegate* delegate) |
| : profile_path_(profile_path), delegate_(delegate) { |
| DCHECK(delegate_); |
| } |
| |
| ArcReadHandler::~ArcReadHandler() = default; |
| |
| void ArcReadHandler::AddRestoreData(const std::string& app_id, |
| int32_t window_id) { |
| window_id_to_app_id_[window_id] = app_id; |
| } |
| |
| void ArcReadHandler::AddArcWindowCandidate(aura::Window* window) { |
| if (!base::Contains(task_id_to_window_id_, |
| window->GetProperty(kWindowIdKey))) { |
| // Check `session_id` to see whether this is a ghost window. |
| int32_t session_id = window->GetProperty(kGhostWindowSessionIdKey); |
| if (session_id >= kArcSessionIdOffsetForRestoredLaunching) |
| return; |
| |
| // If the task hasn't been created, and this is not a ghost window, add |
| // `window` to `arc_window_candidates_` to wait for the task to be created. |
| arc_window_candidates_.insert(window); |
| } |
| } |
| |
| void ArcReadHandler::OnWindowDestroyed(aura::Window* window) { |
| DCHECK(window); |
| |
| // If |window| is list in |arc_window_candidates_|, |window| is not attached |
| // to a valid restore window id yet, so we don't need to remove AppRestoreData |
| // from the restore data. |
| auto it = arc_window_candidates_.find(window); |
| if (it != arc_window_candidates_.end()) { |
| arc_window_candidates_.erase(it); |
| return; |
| } |
| |
| int32_t restore_window_id = window->GetProperty(kRestoreWindowIdKey); |
| RemoveAppRestoreData(restore_window_id); |
| } |
| |
| void ArcReadHandler::OnTaskCreated(const std::string& app_id, |
| int32_t task_id, |
| int32_t session_id) { |
| auto it = session_id_to_window_id_.find(session_id); |
| if (it == session_id_to_window_id_.end()) { |
| not_restored_task_ids_.insert(task_id); |
| UpdateWindowCandidates(task_id, /*restore_window_id=*/-1); |
| return; |
| } |
| |
| int32_t restore_window_id = it->second; |
| session_id_to_window_id_.erase(it); |
| task_id_to_window_id_[task_id] = restore_window_id; |
| |
| UpdateWindowCandidates(task_id, restore_window_id); |
| } |
| |
| void ArcReadHandler::OnTaskDestroyed(int32_t task_id) { |
| not_restored_task_ids_.erase(task_id); |
| |
| auto it = task_id_to_window_id_.find(task_id); |
| if (it == task_id_to_window_id_.end()) |
| return; |
| |
| int32_t window_id = it->second; |
| task_id_to_window_id_.erase(it); |
| |
| RemoveAppRestoreData(window_id); |
| } |
| |
| bool ArcReadHandler::HasRestoreData(int32_t window_id) { |
| return base::Contains(window_id_to_app_id_, window_id); |
| } |
| |
| std::unique_ptr<AppLaunchInfo> ArcReadHandler::GetArcAppLaunchInfo( |
| const std::string& app_id, |
| int32_t session_id) { |
| int32_t restore_window_id = GetArcRestoreWindowIdForSessionId(session_id); |
| if (restore_window_id == 0) |
| return nullptr; |
| |
| return delegate_->GetAppLaunchInfo(profile_path_, app_id, restore_window_id); |
| } |
| |
| std::unique_ptr<WindowInfo> ArcReadHandler::GetWindowInfo( |
| int32_t restore_window_id) { |
| if (!IsValidRestoreWindowId(restore_window_id)) |
| return nullptr; |
| |
| auto it = window_id_to_app_id_.find(restore_window_id); |
| if (it == window_id_to_app_id_.end()) |
| return nullptr; |
| |
| std::unique_ptr<WindowInfo> window_info = |
| delegate_->GetWindowInfo(profile_path_, it->second, restore_window_id); |
| if (!window_info) |
| return nullptr; |
| |
| // For ARC windows, Android can restore window bounds, so remove the window |
| // bounds from the window info. |
| window_info->current_bounds.reset(); |
| |
| // For ARC windows, Android can restore window minimized or maximized status, |
| // so remove the WindowStateType from the window info for the minimized and |
| // maximized state. |
| if (window_info->window_state_type.has_value() && |
| (chromeos::IsMinimizedWindowStateType( |
| window_info->window_state_type.value()) || |
| window_info->window_state_type.value() == |
| chromeos::WindowStateType::kMaximized)) { |
| window_info->window_state_type.reset(); |
| } |
| |
| return window_info; |
| } |
| |
| int32_t ArcReadHandler::GetArcRestoreWindowIdForTaskId(int32_t task_id) { |
| auto it = task_id_to_window_id_.find(task_id); |
| if (it != task_id_to_window_id_.end()) |
| return it->second; |
| |
| // If |session_id_to_window_id_| is empty, that means there is no ARC apps |
| // launched. If `not_restored_task_ids_` has `task_id`, that means the ARC app |
| // window is not restored. |
| if (session_id_to_window_id_.empty() || |
| base::Contains(not_restored_task_ids_, task_id)) { |
| return 0; |
| } |
| |
| // If |session_id_to_window_id_| is not empty, that means there are ARC |
| // apps launched. Returns -1 to add the ARC app window to the hidden |
| // container. |
| return kParentToHiddenContainer; |
| } |
| |
| int32_t ArcReadHandler::GetArcRestoreWindowIdForSessionId(int32_t session_id) { |
| // If `session_id` doesn't exist, that means there is no ARC app restored. |
| auto it = session_id_to_window_id_.find(session_id); |
| return it == session_id_to_window_id_.end() ? 0 : it->second; |
| } |
| |
| void ArcReadHandler::SetArcSessionIdForWindowId(int32_t session_id, |
| int32_t window_id) { |
| DCHECK_GT(session_id, kArcSessionIdOffsetForRestoredLaunching); |
| session_id_to_window_id_[session_id] = window_id; |
| } |
| |
| void ArcReadHandler::RemoveAppRestoreData(int32_t window_id) { |
| if (!IsValidRestoreWindowId(window_id)) |
| return; |
| |
| auto it = window_id_to_app_id_.find(window_id); |
| if (it == window_id_to_app_id_.end()) |
| return; |
| |
| delegate_->RemoveAppRestoreData(profile_path_, it->second, window_id); |
| |
| window_id_to_app_id_.erase(it); |
| } |
| |
| void ArcReadHandler::UpdateWindowCandidates(int32_t task_id, |
| int32_t restore_window_id) { |
| // Go through `arc_window_candidates_`. |
| auto window_it = std::ranges::find( |
| arc_window_candidates_, task_id, |
| [](aura::Window* window) { return window->GetProperty(kWindowIdKey); }); |
| if (window_it == arc_window_candidates_.end()) |
| return; |
| |
| // If `restore_window_id` is valid, sets the window property |
| // `kRestoreWindowIdKey` and `kWindowInfoKey`. |
| if (IsValidRestoreWindowId(restore_window_id)) { |
| (*window_it)->SetProperty(kRestoreWindowIdKey, restore_window_id); |
| |
| // When the window was created, there was not any window info due to there |
| // being no task. Apply properties to the window now that there is window |
| // info. |
| std::unique_ptr<WindowInfo> window_info = GetWindowInfo(restore_window_id); |
| if (window_info) |
| ApplyProperties(window_info.get(), *window_it); |
| } |
| |
| // Remove the window from the hidden container. |
| if ((*window_it)->GetProperty(kParentToHiddenContainerKey)) { |
| app_restore::AppRestoreInfo::GetInstance()->OnParentWindowToValidContainer( |
| *window_it); |
| } |
| |
| arc_window_candidates_.erase(*window_it); |
| } |
| |
| } // namespace app_restore |