// Copyright 2024 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_ASH_POLICY_SKYVAULT_LOCAL_FILES_MIGRATION_MANAGER_H_
#define CHROME_BROWSER_ASH_POLICY_SKYVAULT_LOCAL_FILES_MIGRATION_MANAGER_H_
#include <memory>
#include <optional>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/timer/wall_clock_timer.h"
#include "chrome/browser/ash/policy/skyvault/local_user_files_policy_observer.h"
#include "chrome/browser/ash/policy/skyvault/migration_coordinator.h"
#include "chrome/browser/ash/policy/skyvault/migration_notification_manager.h"
#include "chrome/browser/ash/policy/skyvault/policy_utils.h"
#include "chrome/browser/chromeos/extensions/login_screen/login/cleanup/files_cleanup_handler.h"
#include "chrome/browser/profiles/profile_keyed_service_factory.h"
#include "chromeos/ash/components/dbus/cryptohome/UserDataAuth.pb.h"
#include "components/keyed_service/core/keyed_service.h"
namespace base {
template <typename T>
class NoDestructor;
} // namespace base
namespace content {
class BrowserContext;
} // namespace content
namespace policy::local_user_files {
// Manages the migration of local files to the cloud when SkyVault is enabled.
// Handles starting, monitoring, and completing the migration process.
class LocalFilesMigrationManager : public LocalUserFilesPolicyObserver,
public KeyedService {
public:
class Observer {
public:
// Called when the migration of files to the cloud has completed
// successfully.
virtual void OnMigrationSucceeded() = 0;
};
explicit LocalFilesMigrationManager(content::BrowserContext* context);
LocalFilesMigrationManager(const LocalFilesMigrationManager&) = delete;
LocalFilesMigrationManager& operator=(const LocalFilesMigrationManager&) =
delete;
~LocalFilesMigrationManager() override;
// KeyedService overrides:
void Shutdown() override;
// Adds an observer to receive notifications about migration events.
void AddObserver(Observer* observer);
// Removes an observer.
void RemoveObserver(Observer* observer);
// Injects a mock MigrationNotificationManager for tests.
void SetNotificationManagerForTesting(
MigrationNotificationManager* notification_manager);
// Injects a mock MigrationCoordinator for tests.
void SetCoordinatorForTesting(
std::unique_ptr<MigrationCoordinator> coordinator);
private:
// policy::local_user_files::Observer overrides:
void OnLocalUserFilesPolicyChanged() override;
// Informs the user about the upcoming migration. Schedules another dialog to
// appear closer to the start. From the dialog, the user can also choose to
// start the migration immediately.
void InformUser();
// After initial delay, informs the user again and schedules the migration to
// start automatically. From the dialog, the user can also choose to start the
// migration immediately.
void ScheduleMigrationAndInformUser();
// Bypasses the migration delay and initiates the upload process immediately.
// Called when the user clicks the "Upload now" button in the info dialog.
void SkipMigrationDelay();
// Called after the full migration timeout elapses. Closes the dialog if
// opened, and starts migration.
void OnTimeoutExpired();
// Gathers all file paths that need to be uploaded.
void GetPathsToUpload();
// Starts the migration process by uploading `files` to `cloud_provider_`.
void StartMigration(std::vector<base::FilePath> files);
// Handles the completion of the migration process (success or failure).
void OnMigrationDone(std::map<base::FilePath, MigrationUploadError> errors);
// Handles the completion of the local files cleanup process.
void OnCleanupDone(
std::unique_ptr<chromeos::FilesCleanupHandler> cleanup_handler,
const std::optional<std::string>& error_message);
// Sends a D-Bus call to enable or disable write access to MyFiles.
void SetLocalUserFilesWriteEnabled(bool enabled);
// Handles the response of the SetUserDataStorageWriteEnabled D-Bus call.
void OnFilesWriteRestricted(
std::optional<user_data_auth::SetUserDataStorageWriteEnabledReply> reply);
// Stops the migration if currently ongoing.
void MaybeStopMigration();
// Observers for migration events.
base::ObserverList<Observer>::Unchecked observers_;
// Indicates if migration is currently running.
bool in_progress_ = false;
// Indicates if local files cleanup is currently running.
bool cleanup_in_progress_ = false;
// Whether local user files are allowed by policy.
bool local_user_files_allowed_ = true;
// Cloud provider to which files are uploaded. If not specified, no migration
// happens.
CloudProvider cloud_provider_ = CloudProvider::kNotSpecified;
// The time at which the migration will start automatically.
base::Time migration_start_time_;
// Context for which this instance is created.
raw_ptr<content::BrowserContext> context_;
// Shows and manages migration notifications and dialogs.
raw_ptr<MigrationNotificationManager> notification_manager_;
// Manages the upload of local files to the cloud.
std::unique_ptr<MigrationCoordinator> coordinator_;
// Timer for delaying the start of migration and showing dialogs.
std::unique_ptr<base::WallClockTimer> scheduling_timer_;
base::WeakPtrFactory<LocalFilesMigrationManager> weak_factory_{this};
};
// Manages all LocalFilesMigrationManager instances and associates them with
// Profiles.
class LocalFilesMigrationManagerFactory : public ProfileKeyedServiceFactory {
public:
LocalFilesMigrationManagerFactory(const LocalFilesMigrationManagerFactory&) =
delete;
LocalFilesMigrationManagerFactory& operator=(
const LocalFilesMigrationManagerFactory&) = delete;
// Gets the singleton instance of the factory.
static LocalFilesMigrationManagerFactory* GetInstance();
// Gets the LocalFilesMigrationManager instance associated with the given
// BrowserContext.
static LocalFilesMigrationManager* GetForBrowserContext(
content::BrowserContext* context);
private:
friend base::NoDestructor<LocalFilesMigrationManagerFactory>;
LocalFilesMigrationManagerFactory();
~LocalFilesMigrationManagerFactory() override;
// BrowserContextKeyedServiceFactory overrides:
bool ServiceIsNULLWhileTesting() const override;
std::unique_ptr<KeyedService> BuildServiceInstanceForBrowserContext(
content::BrowserContext* context) const override;
};
} // namespace policy::local_user_files
#endif // CHROME_BROWSER_ASH_POLICY_SKYVAULT_LOCAL_FILES_MIGRATION_MANAGER_H_