| // Copyright 2021 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/app_restore/desk_template_read_handler.h" |
| |
| #include "ash/constants/app_types.h" |
| #include "base/bind.h" |
| #include "base/files/file_path.h" |
| #include "base/no_destructor.h" |
| #include "components/app_restore/app_launch_info.h" |
| #include "components/app_restore/app_restore_data.h" |
| #include "components/app_restore/app_restore_utils.h" |
| #include "components/app_restore/restore_data.h" |
| #include "components/app_restore/window_info.h" |
| #include "components/app_restore/window_properties.h" |
| #include "ui/aura/client/aura_constants.h" |
| |
| namespace app_restore { |
| |
| namespace { |
| |
| // Erase all entries in `map` that have the value `value`. |
| void EraseMapByValue(base::flat_map<int32_t, int32_t>& map, int32_t value) { |
| for (auto it = map.begin(); it != map.end();) { |
| if (it->second == value) |
| it = map.erase(it); |
| else |
| ++it; |
| } |
| } |
| |
| } // namespace |
| |
| DeskTemplateReadHandler::DeskTemplateReadHandler() { |
| if (aura::Env::HasInstance()) |
| env_observer_.Observe(aura::Env::GetInstance()); |
| arc_info_observer_.Observe(app_restore::AppRestoreArcInfo::GetInstance()); |
| } |
| |
| DeskTemplateReadHandler::~DeskTemplateReadHandler() = default; |
| |
| // static |
| DeskTemplateReadHandler* DeskTemplateReadHandler::Get() { |
| static base::NoDestructor<DeskTemplateReadHandler> desk_template_read_handler; |
| return desk_template_read_handler.get(); |
| } |
| |
| ArcReadHandler* DeskTemplateReadHandler::GetArcReadHandlerForWindow( |
| int32_t restore_window_id) { |
| return GetArcReadHandlerForLaunch( |
| GetLaunchIdForRestoreWindowId(restore_window_id)); |
| } |
| |
| void DeskTemplateReadHandler::SetRestoreData( |
| int32_t launch_id, |
| std::unique_ptr<RestoreData> restore_data) { |
| RestoreData* rd = restore_data.get(); |
| |
| DCHECK_EQ(restore_data_.count(launch_id), 0u); |
| DCHECK_EQ(arc_read_handler_.count(launch_id), 0u); |
| |
| restore_data_[launch_id] = std::move(restore_data); |
| |
| // Set up mapping from restore window IDs to launch ID. Create an ARC read |
| // handler and add restore data to it if we have at least one ARC app. |
| for (const auto& [app_id, launch_list] : rd->app_id_to_launch_list()) { |
| for (const auto& [window_id, app_restore_data] : launch_list) { |
| restore_window_id_to_launch_id_[window_id] = launch_id; |
| |
| // Only ARC app launch parameters have event_flag. |
| if (!app_restore_data->event_flag.has_value()) |
| continue; |
| |
| auto& arc_read_handler = arc_read_handler_[launch_id]; |
| if (!arc_read_handler) { |
| arc_read_handler = |
| std::make_unique<ArcReadHandler>(base::FilePath(), this); |
| } |
| |
| arc_read_handler->AddRestoreData(app_id, window_id); |
| } |
| } |
| } |
| |
| RestoreData* DeskTemplateReadHandler::GetRestoreDataForWindow( |
| int32_t restore_window_id) { |
| auto it = |
| restore_data_.find(GetLaunchIdForRestoreWindowId(restore_window_id)); |
| return it != restore_data_.end() ? it->second.get() : nullptr; |
| } |
| |
| void DeskTemplateReadHandler::ClearRestoreData(int32_t launch_id) { |
| restore_data_.erase(launch_id); |
| arc_read_handler_.erase(launch_id); |
| |
| EraseMapByValue(restore_window_id_to_launch_id_, launch_id); |
| EraseMapByValue(session_id_to_launch_id_, launch_id); |
| EraseMapByValue(task_id_to_launch_id_, launch_id); |
| } |
| |
| std::unique_ptr<WindowInfo> DeskTemplateReadHandler::GetWindowInfo( |
| int32_t restore_window_id) { |
| const auto* restore_data = GetRestoreDataForWindow(restore_window_id); |
| if (!restore_data) |
| return nullptr; |
| |
| // Try to find the window info associated with `restore_window_id`. |
| const RestoreData::AppIdToLaunchList& launch_list = |
| restore_data->app_id_to_launch_list(); |
| for (const auto& it : launch_list) { |
| const std::string& app_id = it.first; |
| const AppRestoreData* app_restore_data = |
| restore_data->GetAppRestoreData(app_id, restore_window_id); |
| if (app_restore_data) |
| return app_restore_data->GetWindowInfo(); |
| } |
| |
| return nullptr; |
| } |
| |
| int32_t DeskTemplateReadHandler::FetchRestoreWindowId( |
| const std::string& app_id) { |
| if (RestoreData* restore_data = GetMostRecentRestoreDataForApp(app_id)) |
| return restore_data->FetchRestoreWindowId(app_id); |
| return 0; |
| } |
| |
| void DeskTemplateReadHandler::SetNextRestoreWindowIdForChromeApp( |
| const std::string& app_id) { |
| if (RestoreData* restore_data = GetMostRecentRestoreDataForApp(app_id)) |
| restore_data->SetNextRestoreWindowIdForChromeApp(app_id); |
| } |
| |
| void DeskTemplateReadHandler::SetLaunchIdForArcSessionId(int32_t arc_session_id, |
| int32_t launch_id) { |
| session_id_to_launch_id_[arc_session_id] = launch_id; |
| } |
| |
| void DeskTemplateReadHandler::SetArcSessionIdForWindowId(int32_t arc_session_id, |
| int32_t window_id) { |
| if (int32_t launch_id = GetLaunchIdForArcSessionId(arc_session_id)) { |
| if (ArcReadHandler* handler = GetArcReadHandlerForLaunch(launch_id)) |
| handler->SetArcSessionIdForWindowId(arc_session_id, window_id); |
| } |
| } |
| |
| int32_t DeskTemplateReadHandler::GetArcRestoreWindowIdForTaskId( |
| int32_t task_id) { |
| auto it = task_id_to_launch_id_.find(task_id); |
| if (it == task_id_to_launch_id_.end()) |
| return 0; |
| |
| ArcReadHandler* handler = GetArcReadHandlerForLaunch(it->second); |
| return handler ? handler->GetArcRestoreWindowIdForTaskId(task_id) : 0; |
| } |
| |
| int32_t DeskTemplateReadHandler::GetArcRestoreWindowIdForSessionId( |
| int32_t session_id) { |
| int32_t launch_id = GetLaunchIdForArcSessionId(session_id); |
| if (!launch_id) |
| return 0; |
| |
| ArcReadHandler* handler = GetArcReadHandlerForLaunch(launch_id); |
| return handler ? handler->GetArcRestoreWindowIdForSessionId(session_id) : 0; |
| } |
| |
| void DeskTemplateReadHandler::OnWindowInitialized(aura::Window* window) { |
| // If there isn't restore data for ARC apps, we don't need to handle ARC app |
| // windows restoration. |
| if (arc_read_handler_.empty() || !IsArcWindow(window)) |
| return; |
| |
| const int32_t window_id = window->GetProperty(kRestoreWindowIdKey); |
| ArcReadHandler* handler = GetArcReadHandlerForWindow(window_id); |
| |
| if (window_id == app_restore::kParentToHiddenContainer || |
| (handler && handler->HasRestoreData(window_id))) { |
| observed_windows_.AddObservation(window); |
| handler->AddArcWindowCandidate(window); |
| } |
| } |
| |
| void DeskTemplateReadHandler::OnWindowDestroyed(aura::Window* window) { |
| DCHECK(observed_windows_.IsObservingSource(window)); |
| observed_windows_.RemoveObservation(window); |
| |
| const int32_t window_id = window->GetProperty(kRestoreWindowIdKey); |
| if (ArcReadHandler* handler = GetArcReadHandlerForWindow(window_id)) |
| handler->OnWindowDestroyed(window); |
| } |
| |
| std::unique_ptr<app_restore::AppLaunchInfo> |
| DeskTemplateReadHandler::GetAppLaunchInfo(const base::FilePath& profile_path, |
| const std::string& app_id, |
| int32_t restore_window_id) { |
| if (RestoreData* restore_data = GetRestoreDataForWindow(restore_window_id)) |
| return restore_data->GetAppLaunchInfo(app_id, restore_window_id); |
| return nullptr; |
| } |
| |
| std::unique_ptr<WindowInfo> DeskTemplateReadHandler::GetWindowInfo( |
| const base::FilePath& profile_path, |
| const std::string& app_id, |
| int32_t restore_window_id) { |
| if (RestoreData* restore_data = GetRestoreDataForWindow(restore_window_id)) |
| return restore_data->GetWindowInfo(app_id, restore_window_id); |
| return nullptr; |
| } |
| |
| void DeskTemplateReadHandler::RemoveAppRestoreData( |
| const base::FilePath& profile_path, |
| const std::string& app_id, |
| int32_t restore_window_id) { |
| if (RestoreData* restore_data = GetRestoreDataForWindow(restore_window_id)) |
| restore_data->RemoveAppRestoreData(app_id, restore_window_id); |
| } |
| |
| void DeskTemplateReadHandler::OnTaskCreated(const std::string& app_id, |
| int32_t task_id, |
| int32_t session_id) { |
| int32_t launch_id = GetLaunchIdForArcSessionId(session_id); |
| if (launch_id == 0) |
| return; |
| |
| task_id_to_launch_id_[task_id] = launch_id; |
| |
| if (ArcReadHandler* handler = GetArcReadHandlerForLaunch(launch_id)) |
| handler->OnTaskCreated(app_id, task_id, session_id); |
| } |
| |
| void DeskTemplateReadHandler::OnTaskDestroyed(int32_t task_id) { |
| auto it = task_id_to_launch_id_.find(task_id); |
| if (it == task_id_to_launch_id_.end()) |
| return; |
| |
| if (ArcReadHandler* handler = GetArcReadHandlerForLaunch(it->second)) |
| handler->OnTaskDestroyed(task_id); |
| } |
| |
| int32_t DeskTemplateReadHandler::GetLaunchIdForArcSessionId( |
| int32_t arc_session_id) { |
| auto it = session_id_to_launch_id_.find(arc_session_id); |
| return it != session_id_to_launch_id_.end() ? it->second : 0; |
| } |
| |
| int32_t DeskTemplateReadHandler::GetLaunchIdForRestoreWindowId( |
| int32_t restore_window_id) { |
| auto it = restore_window_id_to_launch_id_.find(restore_window_id); |
| return it != restore_window_id_to_launch_id_.end() ? it->second : 0; |
| } |
| |
| ArcReadHandler* DeskTemplateReadHandler::GetArcReadHandlerForLaunch( |
| int32_t launch_id) { |
| auto it = arc_read_handler_.find(launch_id); |
| return it != arc_read_handler_.end() ? it->second.get() : nullptr; |
| } |
| |
| RestoreData* DeskTemplateReadHandler::GetMostRecentRestoreDataForApp( |
| const std::string& app_id) { |
| // Go from newest to oldest. |
| for (auto it = restore_data_.rbegin(); it != restore_data_.rend(); ++it) { |
| auto& restore_data = it->second; |
| if (restore_data->app_id_to_launch_list().count(app_id)) { |
| return restore_data.get(); |
| } |
| } |
| return nullptr; |
| } |
| |
| } // namespace app_restore |