blob: bd59c6688258eea11b693840f8b0495da4909e72 [file] [log] [blame]
// 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/functional/callback_helpers.h"
#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;
// Called when the migration of files to the cloud has been reset.
virtual void OnMigrationReset() = 0;
};
// Creates an instance of LocalFilesMigrationManager with overridden
// dependencies.
static LocalFilesMigrationManager* CreateForTesting(
content::BrowserContext* context,
MigrationNotificationManager* notification_manager,
std::unique_ptr<MigrationCoordinator> coordinator);
// Creates an instance of LocalFilesMigrationManager.
explicit LocalFilesMigrationManager(content::BrowserContext* context);
LocalFilesMigrationManager(const LocalFilesMigrationManager&) = delete;
LocalFilesMigrationManager& operator=(const LocalFilesMigrationManager&) =
delete;
~LocalFilesMigrationManager() override;
// Initializes this instance.
void Initialize();
// 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);
// Injects a mock FilesCleanupHandler for tests.
void SetCleanupHandlerForTesting(
base::WeakPtr<chromeos::FilesCleanupHandler> cleanup_handler);
private:
// Called after the preferences have been loaded.
void OnPrefsInitialized(bool success);
// Initializes this instance, after the preferences have been loaded.
void InitializeFromPrefs();
// policy::local_user_files::Observer overrides:
void OnLocalUserFilesPolicyChanged() override;
// Called after migration is stopped and can be started again.
void OnMigrationStopped(bool log_file_deleted);
// Called after contents of MyFiles are checked. If empty, removes the volume
// and restricts write access, otherwise initiates the migration based on the
// current state.
void OnMyFilesChecked(bool is_empty);
// 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(const base::Time scheduled_start_time);
// 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).
// If the migration was successful, starts the cleanup process, and handles
// the errors otherwise.
void OnMigrationDone(std::map<base::FilePath, MigrationUploadError> errors,
base::FilePath upload_root_path,
base::FilePath error_log_path);
// Completes the migration process, taking into account any errors that
// occurred during the migration.
void ProcessErrors(std::map<base::FilePath, MigrationUploadError> errors,
base::FilePath error_log_path);
// Cleans up any remaining files from the device after a successful migration.
void CleanupLocalFiles();
// 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(MigrationDestination previous_destination,
bool close_dialog = true,
MigrationStoppedCallback = base::DoNothing());
// Sets and stores the state on the device.
void SetState(State new_state);
// Resets all stored prefs, like the state and start time, in case migration
// is stopped.
void ResetMigrationPrefs();
// Notifies the observers that migration succeeded.
void NotifySuccess();
// Notifies the observers that migration was reset.
void NotifyReset();
// Observers for migration events.
base::ObserverList<Observer>::Unchecked observers_;
// Indicates the migration state.
State state_ = State::kUninitialized;
// 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;
// Indicates how local files should be handled (upload to the cloud or
// delete). If not specified, no migration happens.
MigrationDestination migration_destination_ =
MigrationDestination::kNotSpecified;
// The name of the device-unique upload root folder on Drive
std::string upload_root_;
// 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_;
// Number of times the entire upload failed and was retried.
int current_retry_count_;
base::WeakPtr<chromeos::FilesCleanupHandler> cleanup_handler_for_testing_ =
nullptr;
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. If `create` is true, an instance is created if it doesn't
// exist.
static LocalFilesMigrationManager* GetForBrowserContext(
content::BrowserContext* context,
bool create = true);
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_