File: diversion_backend_delegate.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 (195 lines) | stat: -rw-r--r-- 8,715 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
// 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_FILEAPI_DIVERSION_BACKEND_DELEGATE_H_
#define CHROME_BROWSER_ASH_FILEAPI_DIVERSION_BACKEND_DELEGATE_H_

#include <memory>

#include "base/memory/weak_ptr.h"
#include "chrome/browser/ash/fileapi/diversion_file_manager.h"
#include "chrome/browser/ash/fileapi/file_system_backend_delegate.h"
#include "storage/browser/file_system/async_file_util.h"

namespace ash {

// A FileSystemBackendDelegate decorator (and, transitively, an AsyncFileUtil
// decorator) that combines its wrappees with a DiversionFileManager. It
// interposes a backed-by-local-disk cache (which also enables efficient
// incremental-append writes) for potentially-remote file systems.
//
// A DiversionBackendDelegate's methods should only be called from the
// content::BrowserThread::IO thread. Callbacks run on the same thread.
class DiversionBackendDelegate : public FileSystemBackendDelegate,
                                 public storage::AsyncFileUtil {
 public:
  // How this wrapper treats a virtual file (identified by its FileSystemURL).
  enum class Policy {
    kDoNotDivert,

    // Operations (EnsureFileExists, GetFileInfo, etc) happen entirely in the
    // interposed local-disk cache, and do not touch the wrappees, up until the
    // virtual file is copied or moved to another place (a place that, if also
    // subject to this DiversionBackendDelegate, its Policy should be
    // kDoNotDivert) or an inactivity time out.
    //
    // For example, calling GetFileInfo will return FILE_ERROR_NOT_FOUND
    // (unless EnsureFileExists was previously called) even if the wrapped file
    // system has an existing file for that name (that FileSystemURL). It
    // "doesn't exist" because the wrappees are not even consulted.
    //
    // Similarly, calling EnsureFileExists will return created=true even if the
    // wrappees have an existing file for that FileSystemURL.
    //
    // This Policy is intended for "temporary files", like "*.crdownload" or
    // "*.crswap", where a potentially-large file is incrementally built over
    // time before being moved/renamed over the ultimate destination. These
    // temporary files don't really care about their name other than it doesn't
    // clash with other files. But in Chromium's //storage/browser/file_system
    // cross-platform abstraction, every virtual file needs a unique name. With
    // DiversionBackendDelegate, we can provide an isolated "overlay namespace"
    // for these temporary files, ignoring the underlying wrapped file system.
    //
    // Isolation reduces the number of spurious calls to the wrappees. Spurious
    // work can fail (unnecessarily), take a noticeable amount of time (for
    // cloud-backed file systems), add noise to metrics or debug logs, etc.
    kDivertIsolated,

    // Operations happen in the interposed local-disk cache, but unlike
    // kDivertIsolated, they consult with the wrappee file system.
    //
    // For example, EnsureFileExists will return created=false when the wrappee
    // has an existing file for that FileSystemURL.
    //
    // This Policy is intended for when you do want diversion to apply (e.g.
    // you want efficient incremental-append writes) but you don't have a
    // "temporary file".
    //
    // If in doubt, use kDivertMingled instead of kDivertIsolated, as its
    // behavior is closer to not having a DiversionBackendDelegate at all.
    kDivertMingled,
  };

  explicit DiversionBackendDelegate(
      std::unique_ptr<FileSystemBackendDelegate> wrappee);
  ~DiversionBackendDelegate() override;

  DiversionBackendDelegate(const DiversionBackendDelegate&) = delete;
  DiversionBackendDelegate& operator=(const DiversionBackendDelegate&) = delete;

  // FileSystemBackendDelegate overrides.
  storage::AsyncFileUtil* GetAsyncFileUtil(
      storage::FileSystemType type) override;
  std::unique_ptr<storage::FileStreamReader> CreateFileStreamReader(
      const storage::FileSystemURL& url,
      int64_t offset,
      int64_t max_bytes_to_read,
      const base::Time& expected_modification_time,
      storage::FileSystemContext* context) override;
  std::unique_ptr<storage::FileStreamWriter> CreateFileStreamWriter(
      const storage::FileSystemURL& url,
      int64_t offset,
      storage::FileSystemContext* context) override;
  storage::WatcherManager* GetWatcherManager(
      storage::FileSystemType type) override;

  // storage::AsyncFileUtil overrides.
  void CreateOrOpen(
      std::unique_ptr<storage::FileSystemOperationContext> context,
      const storage::FileSystemURL& url,
      uint32_t file_flags,
      CreateOrOpenCallback callback) override;
  void EnsureFileExists(
      std::unique_ptr<storage::FileSystemOperationContext> context,
      const storage::FileSystemURL& url,
      EnsureFileExistsCallback callback) override;
  void CreateDirectory(
      std::unique_ptr<storage::FileSystemOperationContext> context,
      const storage::FileSystemURL& url,
      bool exclusive,
      bool recursive,
      StatusCallback callback) override;
  void GetFileInfo(std::unique_ptr<storage::FileSystemOperationContext> context,
                   const storage::FileSystemURL& url,
                   GetMetadataFieldSet fields,
                   GetFileInfoCallback callback) override;
  void ReadDirectory(
      std::unique_ptr<storage::FileSystemOperationContext> context,
      const storage::FileSystemURL& url,
      ReadDirectoryCallback callback) override;
  void Touch(std::unique_ptr<storage::FileSystemOperationContext> context,
             const storage::FileSystemURL& url,
             const base::Time& last_access_time,
             const base::Time& last_modified_time,
             StatusCallback callback) override;
  void Truncate(std::unique_ptr<storage::FileSystemOperationContext> context,
                const storage::FileSystemURL& url,
                int64_t length,
                StatusCallback callback) override;
  void CopyFileLocal(
      std::unique_ptr<storage::FileSystemOperationContext> context,
      const storage::FileSystemURL& src_url,
      const storage::FileSystemURL& dest_url,
      CopyOrMoveOptionSet options,
      CopyFileProgressCallback progress_callback,
      StatusCallback callback) override;
  void MoveFileLocal(
      std::unique_ptr<storage::FileSystemOperationContext> context,
      const storage::FileSystemURL& src_url,
      const storage::FileSystemURL& dest_url,
      CopyOrMoveOptionSet options,
      StatusCallback callback) override;
  void CopyInForeignFile(
      std::unique_ptr<storage::FileSystemOperationContext> context,
      const base::FilePath& src_file_path,
      const storage::FileSystemURL& dest_url,
      StatusCallback callback) override;
  void DeleteFile(std::unique_ptr<storage::FileSystemOperationContext> context,
                  const storage::FileSystemURL& url,
                  StatusCallback callback) override;
  void DeleteDirectory(
      std::unique_ptr<storage::FileSystemOperationContext> context,
      const storage::FileSystemURL& url,
      StatusCallback callback) override;
  void DeleteRecursively(
      std::unique_ptr<storage::FileSystemOperationContext> context,
      const storage::FileSystemURL& url,
      StatusCallback callback) override;
  void CreateSnapshotFile(
      std::unique_ptr<storage::FileSystemOperationContext> context,
      const storage::FileSystemURL& url,
      CreateSnapshotFileCallback callback) override;

  void OverrideTmpfileDirForTesting(const base::FilePath& tmpfile_dir);
  static Policy ShouldDivertForTesting(const storage::FileSystemURL& url);
  static base::TimeDelta IdleTimeoutForTesting();

 private:
  enum class OnDiversionFinishedCallSite {
    kEnsureFileExists,
    kCopyFileLocal,
    kMoveFileLocal,
  };

  static void OnDiversionFinished(
      base::WeakPtr<DiversionBackendDelegate> weak_ptr,
      OnDiversionFinishedCallSite call_site,
      std::unique_ptr<storage::FileSystemOperationContext> context,
      const storage::FileSystemURL& dest_url,
      storage::AsyncFileUtil::StatusCallback callback,
      DiversionFileManager::StoppedReason stopped_reason,
      const storage::FileSystemURL& src_url,
      base::ScopedFD scoped_fd,
      int64_t file_size,
      base::File::Error error);

  std::unique_ptr<FileSystemBackendDelegate> wrappee_;
  scoped_refptr<DiversionFileManager> diversion_file_manager_;

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

}  // namespace ash

#endif  // CHROME_BROWSER_ASH_FILEAPI_DIVERSION_BACKEND_DELEGATE_H_