File: trash_io_task.h

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (210 lines) | stat: -rw-r--r-- 8,448 bytes parent folder | download | duplicates (6)
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_