File: odfs_skyvault_uploader.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (246 lines) | stat: -rw-r--r-- 9,593 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
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
// 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_POLICY_SKYVAULT_ODFS_SKYVAULT_UPLOADER_H_
#define CHROME_BROWSER_ASH_POLICY_SKYVAULT_ODFS_SKYVAULT_UPLOADER_H_

#include <optional>

#include "base/callback_list.h"
#include "base/files/file_path.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/timer/timer.h"
#include "chrome/browser/ash/file_manager/io_task_controller.h"
#include "chrome/browser/ash/policy/skyvault/policy_utils.h"
#include "chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.h"
#include "services/network/public/cpp/network_connection_tracker.h"

namespace ash::cloud_upload {

using policy::local_user_files::MigrationUploadError;
using policy::local_user_files::UploadTrigger;

// Uploads the file to Microsoft OneDrive and calls the `upload_callback_` with
// the result of the file upload, which is when `OdfsSkyvaultUploader` goes out
// of scope. Instantiated by the static `Upload` method. Runs
// `progress_callback` by the upload progress if possible.
class OdfsSkyvaultUploader
    : public base::RefCounted<OdfsSkyvaultUploader>,
      ::file_manager::io_task::IOTaskController::Observer {
 public:
  using UploadDoneCallback =
      base::OnceCallback<void(storage::FileSystemURL,
                              std::optional<MigrationUploadError>,
                              base::FilePath upload_root_path)>;

  // Uploads the file at `path` to the OneDrive root directory.
  //
  // Upon completion, invokes `upload_callback` with the following:
  // * `bool success` - Indicates whether the upload was successful.
  // * `storage::FileSystemURL url` - (If successful) The URL of the uploaded
  // file on OneDrive.
  //
  // Optionally, periodically invokes the `progress_callback` during the upload
  // to provide progress updates in bytes transferred.
  //
  // Returns a weak pointer to the `OdfsSkyvaultUploader` object. This can be
  // used to cancel the upload before it completes.
  static base::WeakPtr<OdfsSkyvaultUploader> Upload(
      Profile* profile,
      const base::FilePath& path,
      UploadTrigger trigger,
      base::RepeatingCallback<void(int64_t)> progress_callback,
      base::OnceCallback<void(bool, storage::FileSystemURL)> upload_callback,
      std::optional<const gfx::Image> thumbnail = std::nullopt);

  // Uploads the file to OneDrive, placing it in the device-unique folder at the
  // specified relative path.
  //
  // Invokes `upload_callback` upon completion.
  //
  // Optionally, periodically invokes the `progress_callback` during the upload
  // to provide progress updates in bytes transferred.
  //
  // Returns a weak pointer to the `OdfsSkyvaultUploader` object. This can be
  // used to cancel the upload before it completes.
  //
  // Example: Uploading "example.txt" with a `relative_source_path` of
  // "Documents/Files" and `upload_root` "ChromeOS Device 123" results in
  // "<ODFS ROOT>/ChromeOS Device 123/Documents/Files/example.txt" on OneDrive.
  static base::WeakPtr<OdfsSkyvaultUploader> Upload(
      Profile* profile,
      const base::FilePath& path,
      const base::FilePath& relative_source_path,
      const std::string& upload_root,
      UploadTrigger trigger,
      base::RepeatingCallback<void(int64_t)> progress_callback,
      UploadDoneCallback upload_callback);

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

  // Returns a weak pointer to this instance.
  base::WeakPtr<OdfsSkyvaultUploader> GetWeakPtr();

  // Should cancel the whole upload, if possible.
  virtual void Cancel();

 protected:
  OdfsSkyvaultUploader(Profile* profile,
                       int64_t id,
                       const storage::FileSystemURL& file_system_url,
                       UploadTrigger trigger,
                       base::RepeatingCallback<void(int64_t)> progress_callback,
                       std::optional<const gfx::Image> thumbnail);
  ~OdfsSkyvaultUploader() override;

  // Returns the path to upload the file to.
  virtual base::FilePath GetDestinationFolderPath(
      file_system_provider::ProvidedFileSystemInterface* file_system);

  // Requests the sign in to OneDrive.
  virtual void RequestSignIn(
      base::OnceCallback<void(base::File::Error)> on_sign_in_cb);

  // Starts the upload flow.
  virtual void Run(UploadDoneCallback upload_callback);

  void OnEndUpload(storage::FileSystemURL url,
                   std::optional<MigrationUploadError> error = std::nullopt);

  raw_ptr<Profile> profile_;

  // Absolute path to the device's upload root folder on Drive. This is
  // populated when the upload is about to start.
  base::FilePath upload_root_path_;

 private:
  friend base::RefCounted<OdfsSkyvaultUploader>;

  void GetODFSMetadataAndStartIOTask();

  void CheckReauthenticationAndStartIOTask(
      base::expected<ODFSMetadata, base::File::Error> metadata_or_error);

  // IOTaskController::Observer:
  void OnIOTaskStatus(
      const ::file_manager::io_task::ProgressStatus& status) override;

  // Translates the status error into a MigrationUploadError.
  void ProcessError(const ::file_manager::io_task::ProgressStatus& status);

  // Called when the mount response is received.
  void OnMountResponse(base::File::Error result);

  // Starts the IOTask to upload the file to OneDrive.
  void StartIOTask();

  scoped_refptr<storage::FileSystemContext> file_system_context_;
  raw_ptr<::file_manager::io_task::IOTaskController> io_task_controller_;

  // The Id of the OdfsSkyvaultUploader instance. Used for notifications.
  const int64_t id_;

  // The Id of the move IOTask.
  std::optional<::file_manager::io_task::IOTaskId> observed_task_id_ =
      std::nullopt;

  // The url of the file to be uploaded.
  storage::FileSystemURL file_system_url_;

  // The event or action that initiated the file upload.
  const UploadTrigger trigger_;

  // Progress callback repeatedly run with progress updates.
  base::RepeatingCallback<void(int64_t)> progress_callback_;

  // Upload callback run once with upload success/failure and the file url (if
  // successfully uploaded).
  UploadDoneCallback upload_callback_;

  // Set to `true` if upload is explicitly cancelled by owner. Forces every step
  // to exit early.
  bool cancelled_ = false;

  // Optional preview of the file that is being uploaded.
  std::optional<const gfx::Image> thumbnail_;

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

// Similar to  OdfsSkyvaultUploader, but specialized for the migration flow:
// - doesn't require the file to first be moved to tmp
// - doesn't require progress updates
// - uploads file to a dedicated folder on OneDrive, and not to root
// - invokes different sign-in process, that ensures only one notification is
// TODO(aidazolic): Fix the instantiation.
class OdfsMigrationUploader
    : public OdfsSkyvaultUploader,
      public network::NetworkConnectionTracker::NetworkConnectionObserver {
 public:
  using FactoryCallback =
      base::RepeatingCallback<scoped_refptr<OdfsMigrationUploader>(
          Profile*,
          int64_t,
          const storage::FileSystemURL&,
          const base::FilePath&)>;
  static scoped_refptr<OdfsMigrationUploader> Create(
      Profile* profile,
      int64_t id,
      const storage::FileSystemURL& file_system_url,
      const base::FilePath& relative_source_path,
      const std::string& upload_root);

  // Sets a testing factory function, allowing the injection of mock
  // OdfsMigrationUploader objects into the migration upload process.
  static void SetFactoryForTesting(FactoryCallback factory);

 protected:
  OdfsMigrationUploader(Profile* profile,
                        int64_t id,
                        const storage::FileSystemURL& file_system_url,
                        const base::FilePath& relative_source_path,
                        const std::string& upload_root);
  ~OdfsMigrationUploader() override;

 private:
  // OdfsSkyvaultUploader:
  void Run(UploadDoneCallback upload_callback) override;
  base::FilePath GetDestinationFolderPath(
      file_system_provider::ProvidedFileSystemInterface* file_system) override;
  void RequestSignIn(
      base::OnceCallback<void(base::File::Error)> on_sign_in_cb) override;

  // network::NetworkConnectionTracker::NetworkConnectionObserver:
  void OnConnectionChanged(network::mojom::ConnectionType type) override;

  // Starts the upload process after establishing network connection.
  void RunInternal();

  // Called when waiting for connection times out.
  void OnReconnectionTimeout();

  // Indicates whether there was no connection on starting the task.
  bool waiting_for_connection_ = false;
  // Time at which we started waiting for connection. Used for UMA.
  std::optional<base::Time> connection_wait_start_time_;
  // Ensures that we don't wait for connection indefinitely
  base::OneShotTimer reconnection_timer_;

  UploadDoneCallback upload_callback_;
  // Part of the source path relative to MyFiles
  const base::FilePath relative_source_path_;
  // The name of the device-unique upload root folder on Drive
  const std::string upload_root_;

  base::CallbackListSubscription subscription_;

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

}  // namespace ash::cloud_upload

#endif  // CHROME_BROWSER_ASH_POLICY_SKYVAULT_ODFS_SKYVAULT_UPLOADER_H_