| // Copyright 2020 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. |
| |
| #ifndef COMPONENTS_APP_RESTORE_FULL_RESTORE_SAVE_HANDLER_H_ |
| #define COMPONENTS_APP_RESTORE_FULL_RESTORE_SAVE_HANDLER_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <set> |
| #include <utility> |
| |
| #include "base/component_export.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/scoped_multi_source_observation.h" |
| #include "base/scoped_observation.h" |
| #include "base/timer/timer.h" |
| #include "components/app_restore/app_restore_arc_info.h" |
| #include "components/app_restore/arc_save_handler.h" |
| #include "ui/aura/env.h" |
| #include "ui/aura/env_observer.h" |
| #include "ui/aura/window.h" |
| #include "ui/aura/window_observer.h" |
| |
| namespace apps { |
| class AppRegistryCache; |
| } // namespace apps |
| |
| namespace app_restore { |
| struct AppLaunchInfo; |
| class RestoreData; |
| struct WindowInfo; |
| } // namespace app_restore |
| |
| namespace ash { |
| namespace full_restore { |
| class FullRestoreServiceTestHavingFullRestoreFile; |
| class FullRestoreAppLaunchHandlerArcAppBrowserTest; |
| } |
| } // namespace ash |
| |
| namespace base { |
| class FilePath; |
| class SequencedTaskRunner; |
| } // namespace base |
| |
| namespace full_restore { |
| |
| class FullRestoreFileHandler; |
| |
| // FullRestoreSaveHandler is responsible for writing both the app launch |
| // information and the app window information to disk. FullRestoreSaveHandler |
| // runs on the main thread and creates FullRestoreFileHandler (which runs on a |
| // background task runner) for the actual writing. To minimize IO, |
| // FullRestoreSaveHandler starts a timer that invokes restore data saving at a |
| // later time. |
| class COMPONENT_EXPORT(APP_RESTORE) FullRestoreSaveHandler |
| : public aura::EnvObserver, |
| public aura::WindowObserver, |
| public app_restore::AppRestoreArcInfo::Observer { |
| public: |
| using AppLaunchInfoPtr = std::unique_ptr<app_restore::AppLaunchInfo>; |
| |
| static FullRestoreSaveHandler* GetInstance(); |
| |
| FullRestoreSaveHandler(); |
| FullRestoreSaveHandler(const FullRestoreSaveHandler&) = delete; |
| FullRestoreSaveHandler& operator=(const FullRestoreSaveHandler&) = delete; |
| ~FullRestoreSaveHandler() override; |
| |
| void SetPrimaryProfilePath(const base::FilePath& profile_path); |
| |
| void SetActiveProfilePath(const base::FilePath& profile_path); |
| |
| void SetAppRegistryCache(const base::FilePath& profile_path, |
| apps::AppRegistryCache* app_registry_cache); |
| |
| // When called, allows the Save() method to write to disk. Schedules the save |
| // timer to start for each monitored profile. |
| void AllowSave(); |
| |
| void SetShutDown(); |
| |
| // aura::EnvObserver: |
| void OnWindowInitialized(aura::Window* window) override; |
| |
| // aura::WindowObserver: |
| void OnWindowDestroyed(aura::Window* window) override; |
| |
| // app_restore::AppRestoreArcInfo::Observer: |
| void OnTaskCreated(const std::string& app_id, |
| int32_t task_id, |
| int32_t session_id) override; |
| void OnTaskDestroyed(int32_t task_id) override; |
| void OnArcConnectionChanged(bool is_connection_ready) override; |
| void OnArcPlayStoreEnabledChanged(bool enabled) override; |
| void OnTaskThemeColorUpdated(int32_t task_id, |
| uint32_t primary_color, |
| uint32_t status_bar_color) override; |
| |
| // Saves |app_launch_info| to the full restore file in |profile_path|. |
| void SaveAppLaunchInfo( |
| const base::FilePath& profile_path, |
| std::unique_ptr<app_restore::AppLaunchInfo> app_launch_info); |
| |
| // Saves |window_info| to |profile_path_to_restore_data_|. |
| void SaveWindowInfo(const app_restore::WindowInfo& window_info); |
| |
| // Flushes the full restore file in |profile_path| with the current restore |
| // data. |
| void Flush(const base::FilePath& profile_path); |
| |
| // Returns true if there is a AppRestoreData for the given `profile_path`, |
| // `app_id` and `window_id`. Otherwise, returns false. |
| bool HasAppRestoreData(const base::FilePath& profile_path, |
| const std::string& app_id, |
| int32_t window_id); |
| |
| // Saves |app_launch_info| to |profile_path_to_file_handler_| for |
| // |profile_path| which will be written to the full restore file, if |
| // |app_launch_info| has a window_id. |
| void AddAppLaunchInfo(const base::FilePath& profile_path, |
| AppLaunchInfoPtr app_launch_info); |
| |
| // Modify the window id for `app_id` from `old_window_id` to `new_window_id`. |
| void ModifyWindowId(const base::FilePath& profile_path, |
| const std::string& app_id, |
| int32_t old_window_id, |
| int32_t new_window_id); |
| |
| // Saves |window_info| to |profile_path| for |app_id| and |window_id|. |
| void ModifyWindowInfo(const base::FilePath& profile_path, |
| const std::string& app_id, |
| int32_t window_id, |
| const app_restore::WindowInfo& window_info); |
| |
| // Saves |primary_color| and |status_bar_color| to |profile_path| for |app_id| |
| // and |window_id|. |
| void ModifyThemeColor(const base::FilePath& profile_path, |
| const std::string& app_id, |
| int32_t window_id, |
| uint32_t primary_color, |
| uint32_t status_bar_color); |
| |
| // Removes app launching and app windows for an app with the given |app_id| |
| // from |file_path_to_restore_data_| for |profile_path| . |
| void RemoveApp(const base::FilePath& profile_path, const std::string& app_id); |
| |
| // Removes AppRestoreData from |profile_path| for |app_id| and |window_id|. |
| void RemoveAppRestoreData(const base::FilePath& profile_path, |
| const std::string& app_id, |
| int window_id); |
| |
| // Sends the window for `profile_path` `app_id and `window_id` to background. |
| void SendWindowToBackground(const base::FilePath& profile_path, |
| const std::string& app_id, |
| int window_id); |
| |
| // Starts the timer, and when timeout, clears restore data for |profile_path|. |
| void ClearRestoreData(const base::FilePath& profile_path); |
| |
| // Generates the ARC session id (0 - 1,000,000,000) for ARC apps. |
| int32_t GetArcSessionId(); |
| |
| // Returns the RestoreData that associates with |profile_path|. Returns |
| // nullptr if there is no such RestoreData. |
| const app_restore::RestoreData* GetRestoreData( |
| const base::FilePath& profile_path); |
| |
| // Returns the full restore app id for |window| that can be used to look up |
| // the window's associated AppRestoreData. |
| std::string GetAppId(aura::Window* window); |
| |
| base::OneShotTimer* GetTimerForTesting() { return &save_timer_; } |
| |
| // Since this is a singleton, tests may need to clear it between tests. |
| void ClearForTesting(); |
| |
| private: |
| friend class FullRestoreSaveHandlerTestApi; |
| friend class ash::full_restore::FullRestoreServiceTestHavingFullRestoreFile; |
| friend class ash::full_restore::FullRestoreAppLaunchHandlerArcAppBrowserTest; |
| |
| // Map from a profile path to AppLaunchInfos. |
| using AppLaunchInfos = std::map<base::FilePath, std::list<AppLaunchInfoPtr>>; |
| |
| // Starts the timer that invokes Save (if timer isn't already running). |
| void MaybeStartSaveTimer(const base::FilePath& profile_path); |
| |
| // Passes |profile_path_to_restore_data_| to the backend for saving. |
| void Save(); |
| |
| // Invoked when write to file operation for |profile_path| is finished. |
| void OnSaveFinished(const base::FilePath& profile_path); |
| |
| FullRestoreFileHandler* GetFileHandler(const base::FilePath& profile_path); |
| |
| base::SequencedTaskRunner* BackendTaskRunner( |
| const base::FilePath& profile_path); |
| |
| // Saves |window_info| to |profile_path_to_file_handler_|. |
| void ModifyWindowInfo(int window_id, |
| const app_restore::WindowInfo& window_info); |
| |
| // Removes AppRestoreData for |window_id|. |
| void RemoveAppRestoreData(int window_id); |
| |
| // FullRestoreSaveHandler might be called to save the help app before |
| // FullRestoreAppLaunchHandler reads the full restore data from the full |
| // restore file during the system startup phase, e.g. when a new user login. |
| // So call FullRestoreReadHandler to read the file before saving the new data. |
| // `been_read_profile_paths_` is used to save the profile paths, whose full |
| // restore file has been read by FullRestoreReadHandler. |
| std::set<base::FilePath> been_read_profile_paths_; |
| |
| // Records whether there are new updates for saving between each saving delay. |
| // |pending_save_profile_paths_| is cleared when Save is invoked. |
| std::set<base::FilePath> pending_save_profile_paths_; |
| |
| // The restore data for each user's profile. The key is the profile path. |
| std::map<base::FilePath, app_restore::RestoreData> |
| profile_path_to_restore_data_; |
| |
| // The file handler for each user's profile to write the restore data to the |
| // full restore file for each user. The key is the profile path. |
| std::map<base::FilePath, scoped_refptr<FullRestoreFileHandler>> |
| profile_path_to_file_handler_; |
| |
| // The AppRegistryCache for each user's profile. The key is the profile path. |
| std::map<base::FilePath, apps::AppRegistryCache*> |
| profile_path_to_app_registry_cache_; |
| |
| // The map from the window id to the full restore file path and the app id. |
| // The window id is saved in the window property. This map is used to find the |
| // file path and the app id for browser windows and Chrome app windows only |
| // when save the window info. This map can't be used for ARC app windows. |
| std::map<int32_t, std::pair<base::FilePath, std::string>> |
| window_id_to_app_restore_info_; |
| |
| // The map from the app id to the app launch info for each full restore file |
| // path. |
| std::map<std::string, AppLaunchInfos> app_id_to_app_launch_infos_; |
| |
| // The current active user profile path. |
| base::FilePath active_profile_path_; |
| |
| // The primary user profile path for ARC apps. |
| base::FilePath primary_profile_path_; |
| |
| // Timer used to delay the restore data writing to the full restore file. |
| base::OneShotTimer save_timer_; |
| |
| // During the startup phase, start `wait_timer_` to wait for the system |
| // finishes the startup and the restore process, to prevent the original |
| // restore data is overwritten if the system restarts due to fast crash or |
| // upgrading. |
| base::OneShotTimer wait_timer_; |
| |
| // Records whether the saving process is running for a full restore file. |
| std::set<base::FilePath> save_running_; |
| |
| std::unique_ptr<ArcSaveHandler> arc_save_handler_; |
| |
| bool is_shut_down_ = false; |
| |
| // Due to the system crash or upgrading, the system might restart or reboot |
| // very fast after startup. If the new window is written for the first time |
| // startup, after the second time reboot, the original restore data can't be |
| // restored. For the user, it looks like not restore. So block the save timer |
| // when startup until one of the below condition is matched: |
| // 1. restore finish if the restore setting is always, and no crash. |
| // 2. restore finish if there is a restore notification, and the user selects |
| // restore. |
| // 3. an app is launched by the user if there is a restore notification. |
| // 4. the restore notification is cancel or closed by the user if there is a |
| // restore notification. |
| // 5. the restore setting is off. |
| // 6. 'wait_timer_' is expired. |
| // |
| // When one of the above condition is matched, allow_save_ is set as true to |
| // permit `save_timer_` to start periodically triggering saving to disk. |
| bool allow_save_ = false; |
| |
| base::ScopedObservation<aura::Env, aura::EnvObserver> env_observer_{this}; |
| |
| base::ScopedMultiSourceObservation<aura::Window, aura::WindowObserver> |
| observed_windows_{this}; |
| |
| base::ScopedObservation<app_restore::AppRestoreArcInfo, |
| app_restore::AppRestoreArcInfo::Observer> |
| arc_info_observer_{this}; |
| |
| base::WeakPtrFactory<FullRestoreSaveHandler> weak_factory_{this}; |
| }; |
| |
| } // namespace full_restore |
| |
| #endif // COMPONENTS_APP_RESTORE_FULL_RESTORE_SAVE_HANDLER_H_ |