| // 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 CHROME_BROWSER_UI_ASH_DESKS_DESKS_CLIENT_H_ |
| #define CHROME_BROWSER_UI_ASH_DESKS_DESKS_CLIENT_H_ |
| |
| #include <map> |
| #include <memory> |
| |
| #include "ash/public/cpp/session/session_observer.h" |
| #include "ash/wm/desks/desks_controller.h" |
| #include "base/containers/flat_map.h" |
| #include "base/functional/callback.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/time/time.h" |
| #include "base/types/expected.h" |
| #include "base/uuid.h" |
| #include "base/values.h" |
| #include "components/desks_storage/core/desk_model.h" |
| #include "components/sessions/core/session_id.h" |
| |
| class DesksTemplatesAppLaunchHandler; |
| class LacrosAppWindowObserver; |
| class Profile; |
| |
| namespace ash { |
| class Desk; |
| class DeskTemplate; |
| class DesksController; |
| } // namespace ash |
| |
| namespace aura { |
| class Window; |
| } // namespace aura |
| |
| namespace desks_storage { |
| class DeskModel; |
| class LocalDeskDataManager; |
| class DeskModelWrapper; |
| } // namespace desks_storage |
| |
| // Class to handle all Desks in-browser functionalities. Will call into |
| // ash::DesksController to do actual desk related operations. |
| class DesksClient : public ash::SessionObserver { |
| public: |
| DesksClient(); |
| DesksClient(const DesksClient&) = delete; |
| DesksClient& operator=(const DesksClient&) = delete; |
| ~DesksClient() override; |
| |
| static DesksClient* Get(); |
| |
| enum class DeskActionError { |
| // Unknown error. |
| kUnknownError = 0, |
| // Storage error. |
| kStorageError = 1, |
| // Therer is no active profile. |
| kNoCurrentUserError = 2, |
| // Either the profile is not valid or there is not an active profile. |
| kBadProfileError = 3, |
| // The resource cannot be found. |
| kResourceNotFoundError = 4, |
| // The identifier is not valid. |
| kInvalidIdError = 5, |
| // The desks are currently being modified. |
| kDesksBeingModifiedError = 6, |
| // The desk count requirement not met. |
| kDesksCountCheckFailedError = 7, |
| kMaxValue = kDesksCountCheckFailedError, |
| }; |
| |
| // ash::SessionObserver: |
| void OnActiveUserSessionChanged(const AccountId& account_id) override; |
| |
| // TODO: Change the callback to accept a ash::DeskTemplate* type parameter |
| // later when DesksTemplatesClient (or DesksController) hooks up with storage |
| // and can hold an in-memory captured desk template instance. |
| using CaptureActiveDeskAndSaveTemplateCallback = |
| base::OnceCallback<void(std::optional<DeskActionError> result, |
| std::unique_ptr<ash::DeskTemplate>)>; |
| |
| // Captures the active desk and saves it as template or saved desk for later |
| // use. If such desk can be saved, `callback` will be invoked with |
| // `std::nullopt` as the `result` with the pointer to the captured desk |
| // template, otherwise, `callback` will be invoked with an `DeskActionError` |
| // error as the `result` and a nullptr for desk template. |
| void CaptureActiveDeskAndSaveTemplate( |
| CaptureActiveDeskAndSaveTemplateCallback callback, |
| ash::DeskTemplateType template_type); |
| |
| // Captures the active desk without saving it. If such desk can be saved, |
| // `callback` will be invoked with `std::nullopt` as the `result` with the |
| // pointer to the captured desk template, otherwise, `callback` will be |
| // invoked with an `DeskActionError` error as the `result` and a nullptr for |
| // desk template. |
| virtual void CaptureActiveDesk( |
| CaptureActiveDeskAndSaveTemplateCallback callback, |
| ash::DeskTemplateType template_type); |
| |
| using DeleteDeskTemplateCallback = |
| base::OnceCallback<void(std::optional<DeskActionError> result)>; |
| // Deletes a saved desk template from storage. If the template can't be |
| // deleted, |callback| will be invoked with the error code. |
| // If it can be deleted successfully, or there is no such |template_uuid| |
| // to be removed,|callback| will be invoked with the success result code. |
| // TODO(crbug.com/1286515): This will be removed with the extension. Avoid |
| // further uses of this method. |
| void DeleteDeskTemplate(const base::Uuid& template_uuid, |
| DeleteDeskTemplateCallback callback); |
| |
| using GetDeskTemplatesCallback = |
| base::OnceCallback<void(std::optional<DeskActionError> result, |
| const std::vector<raw_ptr<const ash::DeskTemplate, |
| VectorExperimental>>&)>; |
| // Returns the current available saved desk templates. |
| // TODO(crbug.com/1286515): This will be removed with the extension. Avoid |
| // further uses of this method. |
| void GetDeskTemplates(GetDeskTemplatesCallback callback); |
| |
| // Returns the current available desks. |
| virtual base::expected<std::vector<const ash::Desk*>, DeskActionError> |
| GetAllDesks(); |
| |
| using GetTemplateJsonCallback = |
| base::OnceCallback<void(std::optional<DeskActionError> result, |
| const base::Value& template_json)>; |
| // Takes in |uuid| and fetches the stringified json representation of a |
| // desk template. |
| void GetTemplateJson(const base::Uuid& uuid, |
| Profile* profile, |
| GetTemplateJsonCallback callback); |
| |
| using LaunchDeskCallback = |
| base::OnceCallback<void(std::optional<DeskActionError> result, |
| const base::Uuid& desk_uuid)>; |
| // Launches the desk template with `template_uuid` as a new desk. |
| // `template_uuid` should be the unique id for an existing desk template. If |
| // no such id can be found or we are at the max desk limit (currently is 8) |
| // so can't create new desk for the desk template, `callback` will be invoked |
| // with a the error code. If `customized_desk_name` is provided, desk name |
| // will be set to `customized_desk_name` or `customized_desk_name ({counter})` |
| // to resolve naming conflicts. Otherwise, desk name will be set to auto |
| // generated name. |
| // TODO(crbug.com/1286515): This will be removed with the extension. Avoid |
| // further uses of this method. |
| virtual void LaunchDeskTemplate( |
| const base::Uuid& template_uuid, |
| LaunchDeskCallback callback, |
| const std::u16string& customized_desk_name = std::u16string()); |
| |
| // Launches an empty new desk. Desk name will be set to `customized_desk_name` |
| // variant if it's provided, otherwise will be set to auto generated name. |
| base::expected<const base::Uuid, DeskActionError> LaunchEmptyDesk( |
| const std::u16string& customized_desk_name = std::u16string()); |
| |
| using ErrorHandlingCallBack = |
| base::OnceCallback<void(std::optional<DeskActionError> result)>; |
| // Remove a desk, close all windows if `close_type` set to kCloseAllWindows, |
| // otherwise combine the windows to the active desk to the left. Provide |
| // a notification allowing the user to undo the removal if `close_type` is |
| // set to `kCloseAllWindowsAndWait` |
| virtual std::optional<DesksClient::DeskActionError> RemoveDesk( |
| const base::Uuid& desk_uuid, |
| ash::DeskCloseType close_type); |
| |
| // Uses `app_launch_handler_` to launch apps from the restore data found in |
| // `desk_template`. |
| virtual void LaunchAppsFromTemplate( |
| std::unique_ptr<ash::DeskTemplate> desk_template); |
| |
| // Returns either the local desk storage backend or Chrome sync desk storage |
| // backend depending on the feature flag DeskTemplateSync. |
| desks_storage::DeskModel* GetDeskModel(); |
| |
| // Sets the preconfigured desk template. |
| void SetPolicyPreconfiguredTemplate(const AccountId& account_id, |
| std::unique_ptr<std::string> data); |
| void RemovePolicyPreconfiguredTemplate(const AccountId& account_id); |
| |
| // Notifies launch performance trackers that an app has been moved rather |
| // than launched. |
| void NotifyMovedSingleInstanceApp(int32_t window_id); |
| |
| // Set the property of showing on all-desk or not to a window. |
| std::optional<DesksClient::DeskActionError> |
| SetAllDeskPropertyByBrowserSessionId(SessionID browser_session_id, |
| bool all_desk); |
| |
| // Returns the UUID of active desk. |
| virtual base::Uuid GetActiveDesk(); |
| |
| // Retrieves desk by its UUID. |
| virtual base::expected<const ash::Desk*, DesksClient::DeskActionError> |
| GetDeskByID(const base::Uuid& desk_uuid) const; |
| |
| // Switches to the target desk, returns error string if operation fails. |
| std::optional<DesksClient::DeskActionError> SwitchDesk( |
| const base::Uuid& desk_uuid); |
| |
| // If `window` is a lacros window that has an app id, return it. |
| std::optional<std::string> GetAppIdForLacrosWindow( |
| aura::Window* window) const; |
| |
| private: |
| class LaunchPerformanceTracker; |
| class DeskEventObserver; |
| friend class DesksClientTest; |
| friend class ScopedDesksTemplatesAppLaunchHandlerSetter; |
| |
| // Launches DeskTemplate after retrieval from storage. |
| void OnGetTemplateForDeskLaunch( |
| LaunchDeskCallback callback, |
| std::u16string customized_desk_name, |
| desks_storage::DeskModel::GetEntryByUuidStatus status, |
| std::unique_ptr<ash::DeskTemplate> saved_desk); |
| |
| // Callback function that allows the |CaptureActiveDeskAndSaveTemplate| |
| // |callback| to be called as a |desks_storage::AddOrUpdateEntryCallback|. |
| void OnCaptureActiveDeskAndSaveTemplate( |
| CaptureActiveDeskAndSaveTemplateCallback callback, |
| desks_storage::DeskModel::AddOrUpdateEntryStatus status, |
| std::unique_ptr<ash::DeskTemplate> desk_template); |
| |
| // Callback function that allows for the |DeleteDeskTemplateCallback| to be |
| // called as a |desks_storage::DeleteEntryCallback| |
| void OnDeleteDeskTemplate(DeleteDeskTemplateCallback callback, |
| desks_storage::DeskModel::DeleteEntryStatus status); |
| // Callback function that is run after a saved desk called and moved from |
| // library. |
| void OnRecallSavedDesk(DesksClient::LaunchDeskCallback callback, |
| const base::Uuid& desk_id, |
| desks_storage::DeskModel::DeleteEntryStatus status); |
| |
| // Callback function that is called once the DesksController has captured the |
| // active desk as a template. Invokes |callback| with |desk_template| as an |
| // argument. |
| void OnCapturedDeskTemplate(CaptureActiveDeskAndSaveTemplateCallback callback, |
| std::optional<DesksClient::DeskActionError> error, |
| std::unique_ptr<ash::DeskTemplate> desk_template); |
| |
| // Callback function that handles the JSON representation of a specific |
| // template. |
| void OnGetTemplateJson(DesksClient::GetTemplateJsonCallback callback, |
| desks_storage::DeskModel::GetTemplateJsonStatus status, |
| const base::Value& json_representation); |
| |
| // Callback function that clears the data associated with a specific launch. |
| void OnLaunchComplete(int32_t launch_id); |
| |
| // Called by a launch performance tracker when it has completed monitoring the |
| // launch of a template. |
| void RemoveLaunchPerformanceTracker(const base::Uuid& tracker_uuid); |
| |
| // Get the pointer to the window by `browser_session_id`. |
| aura::Window* GetWindowByBrowserSessionId(SessionID browser_session_id); |
| |
| // Creates a new desk and switch to it. If `customized_desk_name` is |
| // provided, desk name will be `customized_desk_name` or `customized_desk_name |
| // ({counter})` to resolve naming conflicts. CanCreateDesks() must be checked |
| // before calling this. |
| const ash::Desk* CreateEmptyDeskAndActivate( |
| const std::u16string& customized_desk_name); |
| |
| // Convenience pointer to ash::DesksController. Guaranteed to be not null for |
| // the duration of `this`. |
| const raw_ptr<ash::DesksController> desks_controller_; |
| |
| raw_ptr<Profile> active_profile_ = nullptr; |
| |
| // Maps launch id to a launch handler. |
| std::map<int32_t, std::unique_ptr<DesksTemplatesAppLaunchHandler>> |
| app_launch_handlers_; |
| |
| // A test only template for testing `LaunchDeskTemplate`. |
| std::unique_ptr<ash::DeskTemplate> launch_template_for_test_; |
| |
| // Local desks storage backend for desk templates. |
| std::unique_ptr<desks_storage::LocalDeskDataManager> |
| desk_templates_storage_manager_; |
| |
| // Local desks storage backend for save and recall desks. |
| std::unique_ptr<desks_storage::LocalDeskDataManager> |
| save_and_recall_desks_storage_manager_; |
| |
| // Wrapper desk model to house both desk types backend storage. |
| std::unique_ptr<desks_storage::DeskModelWrapper> saved_desk_storage_manager_; |
| |
| // Monitors lacros app windows for use in saved desks. |
| std::unique_ptr<LacrosAppWindowObserver> lacros_app_window_observer_; |
| |
| // The stored JSON values of preconfigured desk templates |
| base::flat_map<AccountId, std::string> preconfigured_desk_templates_json_; |
| |
| // Mapping of template ids that are being launched to their launch performance |
| // trackers. |
| base::flat_map<base::Uuid, std::unique_ptr<LaunchPerformanceTracker>> |
| template_ids_to_launch_performance_trackers_; |
| |
| // Monitors desk events. |
| std::unique_ptr<DeskEventObserver> desk_event_observer_; |
| |
| base::WeakPtrFactory<DesksClient> weak_ptr_factory_{this}; |
| }; |
| |
| #endif // CHROME_BROWSER_UI_ASH_DESKS_DESKS_CLIENT_H_ |