blob: f9e54b756e1d7360061ec1a44ca7fcdc3c6d4f9b [file] [log] [blame]
// Copyright 2025 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_DOWNLOAD_MODEL_DOWNLOAD_FILE_SERVICE_H_
#define IOS_CHROME_BROWSER_DOWNLOAD_MODEL_DOWNLOAD_FILE_SERVICE_H_
#import <string>
#import "base/files/file_path.h"
#import "base/functional/callback.h"
#import "base/memory/raw_ptr.h"
#import "base/memory/weak_ptr.h"
#import "base/sequence_checker.h"
#import "base/task/sequenced_task_runner.h"
#import "components/keyed_service/core/keyed_service.h"
class DownloadRecordService;
// Service that manages download file operations independently of UI components.
// Ensures reliable file operations even if UI elements are destroyed during
// async operations.
class DownloadFileService : public KeyedService {
public:
using MoveCompleteCallback =
base::OnceCallback<void(bool success,
const std::string& download_id,
const base::FilePath& source_path,
const base::FilePath& final_path)>;
// Constructor accepts DownloadRecordService pointer (may be nullptr).
explicit DownloadFileService(DownloadRecordService* download_record_service);
DownloadFileService(const DownloadFileService&) = delete;
DownloadFileService& operator=(const DownloadFileService&) = delete;
~DownloadFileService() override;
// Asynchronously moves a download file from source to destination.
// Must be called on the main thread. Callback runs on the main thread.
void MoveDownloadFile(const std::string& download_id,
const base::FilePath& source_path,
const base::FilePath& destination_path,
MoveCompleteCallback callback);
// Asynchronously resolves an available file path in the target directory.
// Handles file name conflicts by generating unique names if needed.
// Must be called on the main thread. Callback runs on the main thread.
void ResolveAvailableFilePath(
const base::FilePath& target_directory,
const base::FilePath& suggested_filename,
base::OnceCallback<void(base::FilePath)> callback);
// Asynchronously checks if a file exists.
// Must be called on the main thread. Callback runs on the main thread.
void CheckFileExists(const base::FilePath& file_path,
base::OnceCallback<void(bool)> callback);
private:
// Called on the main thread when the file move operation completes.
void OnFileMoveComplete(const std::string& download_id,
const base::FilePath& source_path,
const base::FilePath& destination_path,
MoveCompleteCallback callback,
bool move_success);
// Performs the actual file move on the background thread.
static bool DoMoveFileOnBackgroundThread(
scoped_refptr<base::SequencedTaskRunner> file_task_runner,
const base::FilePath& source_path,
const base::FilePath& destination_path);
// Finds an available file path in the target directory on the background
// thread. If the file already exists, a new file name will be generated.
static base::FilePath FindAvailableDownloadFilePath(
scoped_refptr<base::SequencedTaskRunner> file_task_runner,
const base::FilePath& download_dir,
const base::FilePath& file_name);
// Task runner for file operations.
scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
// Download record service for persistent storage operations.
raw_ptr<DownloadRecordService> download_record_service_ = nullptr;
// Sequence checker for main thread operations.
SEQUENCE_CHECKER(main_sequence_checker_);
// Weak pointer factory for callbacks.
base::WeakPtrFactory<DownloadFileService> weak_ptr_factory_{this};
};
#endif // IOS_CHROME_BROWSER_DOWNLOAD_MODEL_DOWNLOAD_FILE_SERVICE_H_