// 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_DRIVE_UPLOAD_OBSERVER_H_
#define CHROME_BROWSER_ASH_POLICY_SKYVAULT_DRIVE_UPLOAD_OBSERVER_H_
#include "base/files/file_path.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "chrome/browser/ash/drive/drive_integration_service.h"
#include "chrome/browser/ash/file_manager/io_task.h"
#include "chrome/browser/ash/file_manager/io_task_controller.h"
#include "chromeos/ash/components/drivefs/drivefs_host.h"
#include "storage/browser/file_system/file_system_context.h"
class Profile;
namespace ash::cloud_upload {
// Observes the "upload to Google Drive" after the file is written to the local
// cache of Google Drive. Immediately uploads the file to Google Drive if the
// file is still queued. Instantiated by the static `Observe` method. Gets
// upload status by observing Drive events. Calls the `upload_callback_` when
// the file is successfully uploaded, which is when `DriveUploadObserver` goes
// out of scope. If the upload to Drive fails, it'll delete the file from the
// local cache.
class DriveUploadObserver
: public base::RefCounted<DriveUploadObserver>,
drivefs::DriveFsHost::Observer,
drive::DriveIntegrationService::Observer,
::file_manager::io_task::IOTaskController::Observer {
public:
// Starts observing the upload of the file specified at construct time.
static void Observe(Profile* profile,
base::FilePath file_path,
int64_t file_bytes,
base::RepeatingCallback<void(int64_t)> progress_callback,
base::OnceCallback<void(bool)> upload_callback);
DriveUploadObserver(const DriveUploadObserver&) = delete;
DriveUploadObserver& operator=(const DriveUploadObserver&) = delete;
FRIEND_TEST_ALL_PREFIXES(DriveUploadObserverTest, NoSyncUpdates);
FRIEND_TEST_ALL_PREFIXES(DriveUploadObserverTest, NoFileMetadata);
private:
friend base::RefCounted<DriveUploadObserver>;
DriveUploadObserver(Profile* profile,
base::FilePath file_path,
int64_t file_bytes,
base::RepeatingCallback<void(int64_t)> progress_callback);
~DriveUploadObserver() override;
void Run(base::OnceCallback<void(bool)> upload_callback);
void OnEndUpload(bool success);
// DriveFsHost::Observer implementation.
void OnUnmounted() override;
void OnSyncingStatusUpdate(
const drivefs::mojom::SyncingStatus& status) override;
void OnError(const drivefs::mojom::DriveError& error) override;
// DriveIntegrationService::Observer implementation.
void OnDriveConnectionStatusChanged(
drive::util::ConnectionStatus status) override;
// IOTaskController::Observer implementation.
void OnIOTaskStatus(
const ::file_manager::io_task::ProgressStatus& status) override;
void OnImmediatelyUploadDone(int64_t bytes_transferred,
drive::FileError error);
void StartNoSyncUpdateTimer();
void NoSyncTimedOut();
void OnGetDriveMetadata(drive::FileError error,
drivefs::mojom::FileMetadataPtr metadata);
raw_ptr<Profile> profile_;
scoped_refptr<storage::FileSystemContext> file_system_context_;
const raw_ptr<drive::DriveIntegrationService> drive_integration_service_;
// The Id of the delete task. It'll have a value only if the upload fails.
std::optional<::file_manager::io_task::IOTaskId> observed_delete_task_id_ =
std::nullopt;
// The observed file local path.
base::FilePath observed_local_path_;
// The observed file Drive path.
base::FilePath observed_drive_path_;
// The size of the observed file.
int64_t file_bytes_;
// Progress callback repeatedly run with progress updates.
base::RepeatingCallback<void(int64_t)> progress_callback_;
// Upload callback run once with upload success/failure.
base::OnceCallback<void(bool)> upload_callback_;
// If there's no sync updates received, the timer will timeout.
base::OneShotTimer no_sync_update_timeout_;
base::ScopedObservation<::file_manager::io_task::IOTaskController,
::file_manager::io_task::IOTaskController::Observer>
io_task_controller_observer_{this};
base::WeakPtrFactory<DriveUploadObserver> weak_ptr_factory_{this};
};
} // namespace ash::cloud_upload
#endif // CHROME_BROWSER_ASH_POLICY_SKYVAULT_DRIVE_UPLOAD_OBSERVER_H_