chromium/ios/chrome/browser/drive/model/drive_upload_task.h

// 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 IOS_CHROME_BROWSER_DRIVE_MODEL_DRIVE_UPLOAD_TASK_H_
#define IOS_CHROME_BROWSER_DRIVE_MODEL_DRIVE_UPLOAD_TASK_H_

#import "base/files/file_path.h"
#import "ios/chrome/browser/drive/model/drive_file_uploader.h"
#import "ios/chrome/browser/drive/model/upload_task.h"

class DriveFileUploader;

// Upload task which uses a `DriveFileUploader` to retrieve a destination folder
// in a user's Drive, creates it if necessary, and uploads a file to it.
class DriveUploadTask final : public UploadTask {
 public:
  explicit DriveUploadTask(std::unique_ptr<DriveFileUploader> uploader);
  ~DriveUploadTask() final;

  // Sets source `path`, `suggested_name` and `mime_type` of file to upload.
  void SetFileToUpload(const base::FilePath& path,
                       const base::FilePath& suggested_name,
                       const std::string& mime_type,
                       const int64_t total_bytes);
  // Sets name of folder in which to add uploaded files.
  void SetDestinationFolderName(const std::string& folder_name);

  // UploadTask overrides.
  State GetState() const final;
  void Start() final;
  void Cancel() final;
  id<SystemIdentity> GetIdentity() const final;
  float GetProgress() const final;
  std::optional<GURL> GetResponseLink(
      bool add_user_identifier = false) const final;
  NSError* GetError() const final;

 private:
  // Performs the first step of this upload task i.e. search a destination Drive
  // folder using `uploader_->SearchSaveToDriveFolder(folder_name, ...)`.
  // The result will be reported to `CreateFolderOrDirectlyUploadFile()`;
  void SearchFolderThenCreateFolderOrDirectlyUploadFile();

  // Performs the second step of this upload task i.e.
  // if the first step returned an existing folder, directly upload the file to
  // this existing folder using `UploadFile()`. Otherwise, create a destination
  // folder using `uploader_->CreateSaveToDriveFolder(folder_name, ...)` and
  // report the result to `UploadFile()`;
  void CreateFolderOrDirectlyUploadFile(
      const DriveFolderResult& folder_search_result);

  // Performs the third step of this upload task i.e. uploads the
  // file at `file_url` to the folder contained in `folder_result` using
  // `uploader_->UploadFile(file_url, ...)`.
  void UploadFile(const DriveFolderResult& folder_result);

  // Called when the uploader is reporting progress of upload.
  void OnDriveFileUploadProgress(const DriveFileUploadProgress& progress);
  // Called when the uploader is reporting result of upload.
  void OnDriveFileUploadResult(const DriveFileUploadResult& result);

  // Sets `state_` and calls `UploadTaskUpdated()`.
  void SetState(State state);

  // Current state of upload.
  State state_ = State::kNotStarted;

  // File path of file to upload.
  std::optional<base::FilePath> file_path_;
  // Suggested file name for uploaded file.
  base::FilePath suggested_file_name_;
  // MIME type of uploaded file.
  std::string file_mime_type_;
  // Size of the file to upload.
  int64_t file_total_bytes_ = -1;
  // Name of folder in which to add uploaded files.
  std::string folder_name_;

  // File uploader.
  std::unique_ptr<DriveFileUploader> uploader_;
  // Latest progress reported to `OnDriveFileUploadProgress()`, if any.
  std::optional<DriveFileUploadProgress> upload_progress_;
  // Result of this upload task if it is done. If one the steps failed, then
  // this will contain an error. Otherwise it will contain a link to the
  // successfully uploaded file.
  std::optional<DriveFileUploadResult> upload_result_;
  // Number attempts to start the task i.e. incremented every time
  // `CreateFolderOrDirectlyUploadFile()` is called.
  int number_of_attempts_ = 0;

  base::WeakPtrFactory<DriveUploadTask> weak_ptr_factory_{this};
};

#endif  // IOS_CHROME_BROWSER_DRIVE_MODEL_DRIVE_UPLOAD_TASK_H_