1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
|
// Copyright 2022 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_FILE_MANAGER_TRASH_IO_TASK_H_
#define CHROME_BROWSER_ASH_FILE_MANAGER_TRASH_IO_TASK_H_
#include <functional>
#include <memory>
#include <optional>
#include <vector>
#include "base/files/file_error_or.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "chrome/browser/ash/file_manager/file_manager_copy_or_move_hook_delegate.h"
#include "chrome/browser/ash/file_manager/io_task.h"
#include "chrome/browser/ash/file_manager/trash_common_util.h"
#include "chromeos/ash/components/file_manager/speedometer.h"
#include "storage/browser/file_system/file_system_context.h"
#include "storage/browser/file_system/file_system_operation_runner.h"
#include "storage/browser/file_system/file_system_url.h"
class Profile;
namespace file_manager::io_task {
namespace {
struct TrashEntry {
TrashEntry();
~TrashEntry();
TrashEntry(TrashEntry&& other);
TrashEntry& operator=(TrashEntry&& other);
// The relative path (to `trash_mount_path`) where the final location of the
// trashed file.
base::FilePath relative_trash_path;
// An absolute location which contains the `relative_trash_path` and combined
// represents the final location of the trashed file.
base::FilePath trash_mount_path;
// The date of deletion, stored in the metadata file to help scheduled
// cleanup.
base::Time deletion_time;
// The contents of the .trashinfo file containing the deletion date and
// original path of the trashed file.
std::string trash_info_contents;
// The source file size.
int64_t source_file_size;
};
} // namespace
// This class represents a trash task. A trash task attempts to trash zero or
// more files by first moving them to a .Trash/files or .Trash-{UID}/files
// folder that resides in a parent folder for:
// - MyFiles
// - Downloads
// - Crostini
// - Drive
// A corresponding .trashinfo file will be created at .Trash/info or
// .Trash-{UID}/info that contains a timestamp of deletion and the original path
// (relative to the trash folder location).
//
// This follows the XDG specification
// https://specifications.freedesktop.org/trash-spec/trashspec-1.0.html
class TrashIOTask : public IOTask {
public:
TrashIOTask(std::vector<storage::FileSystemURL> file_urls,
Profile* profile,
scoped_refptr<storage::FileSystemContext> file_system_context,
const base::FilePath base_path,
bool show_notification = true);
~TrashIOTask() override;
// Starts trash trask.
void Execute(ProgressCallback progress_callback,
CompleteCallback complete_callback) override;
void Cancel() override;
private:
void Complete(State state);
void UpdateTrashEntry(size_t source_idx);
void GetFileSize(size_t source_idx);
void GotFileSize(size_t source_idx,
base::File::Error error,
const base::File::Info& file_info);
const storage::FileSystemURL CreateFileSystemURL(
const storage::FileSystemURL& original_url,
const base::FilePath& path);
void SetCurrentOperationID(
storage::FileSystemOperationRunner::OperationID id);
void ValidateAndDecrementFreeSpace(
size_t source_idx,
const trash::TrashPathsMap::reverse_iterator& it);
// Get the free disk space for `trash_parent_path` to know whether the
// metadata can be written. The `folder_name` is used to differentiate between
// .Trash and .Trash-1000 folder names on various file systems (both are valid
// in the XDG spec).
void GetFreeDiskSpace(size_t source_idx,
const trash::TrashPathsMap::reverse_iterator& it);
void GotFreeDiskSpace(size_t source_idx,
const trash::TrashPathsMap::reverse_iterator& it,
int64_t free_space);
// Sets up the .Trash/files and .Trash/info subdirectories specified by the
// `trash_subdirectory` parameter. Will create the parent directories as well
// in the instance .Trash folder does not exist.
void SetupSubDirectory(trash::TrashPathsMap::const_iterator& it,
const storage::FileSystemURL trash_subdirectory);
// During low-disk space situations, cryptohome needs a way to identify
// folders to purge. Trash should be considered prior to the rest of the
// users' profile.
void SetDirectoryTracking(
base::OnceCallback<void(base::File::Error)> on_setup_complete_callback,
const base::FilePath& trash_subdirectory,
base::File::Error error);
void OnSetupSubDirectory(trash::TrashPathsMap::const_iterator& it,
const storage::FileSystemURL trash_subdirectory,
base::File::Error error);
// After setting up directory permissions, `set_permissions_success` will have
// true on success and false otherwise.
void OnSetDirectoryPermissions(trash::TrashPathsMap::const_iterator& it,
bool set_permissions_success);
base::FilePath MakeRelativeFromBasePath(const base::FilePath& absolute_path);
base::FilePath MakeRelativePathAbsoluteFromBasePath(
const base::FilePath& relative_path);
// Attempts to generate a unique destination filename when saving to
// .Trash/files. Appends an increasing (N) suffix until a unique name is
// identified.
void GenerateDestinationURL(size_t source_idx, size_t output_idx);
// Creates a file in .Trash/info that matches the name generated from
// `GenerateDestinationURL`. Writes the relative restoration path as well as
// the date time of deletion.
void WriteMetadata(
size_t source_idx,
size_t output_idx,
const storage::FileSystemURL& files_folder_location,
base::FileErrorOr<storage::FileSystemURL> destination_result);
void OnWriteMetadata(size_t source_idx,
size_t output_idx,
const storage::FileSystemURL& destination_url,
bool success);
// Called upon either error of writing metadata or completion of moving the
// trashed file. Ensures progress is invoked and the next file is queued.
void TrashComplete(size_t source_idx,
size_t output_idx,
base::File::Error error);
// Move a file from it's location to the final .Trash/files destination with
// a unique name determined by `GenerateDestinationURL`.
void TrashFile(size_t source_idx,
size_t output_idx,
const storage::FileSystemURL& destination_url);
void OnMoveComplete(size_t source_idx,
size_t output_idx,
base::File::Error error);
raw_ptr<Profile> profile_;
scoped_refptr<storage::FileSystemContext> file_system_context_;
// Stores the total size required for all the metadata files, keyed by the
// trash location to ensure enough disk space to write.
std::vector<TrashEntry> trash_entries_;
// Maintains the free space required to write all the metadata files along
// with the underlying locations of the .Trash/{files,info} directories.
trash::TrashPathsMap free_space_map_;
// Stores the size reported by the last progress update so we can compute the
// delta on the next progress update.
int64_t last_progress_size_;
// Stores the last url for the most recently updated metadata file, in the
// event of a move failure this file is removed.
storage::FileSystemURL last_metadata_url_;
// Speedometer for this operation, used to calculate the remaining time to
// finish the operation.
Speedometer speedometer_;
// Stores the id of the operations currently behind undertaken by Trash,
// including directory creation. Enables cancelling an inflight operation.
std::optional<storage::FileSystemOperationRunner::OperationID> operation_id_;
ProgressCallback progress_callback_;
CompleteCallback complete_callback_;
// Represents the parent path that all the source URLs descend from. Used to
// work around the fact `FileSystemOperationRunner` requires relative paths
// only in testing.
const base::FilePath base_path_;
base::WeakPtrFactory<TrashIOTask> weak_ptr_factory_{this};
};
} // namespace file_manager::io_task
#endif // CHROME_BROWSER_ASH_FILE_MANAGER_TRASH_IO_TASK_H_
|