File: drive_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 (175 lines) | stat: -rw-r--r-- 7,002 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
// 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_DRIVE_SKYVAULT_UPLOADER_H_
#define CHROME_BROWSER_ASH_POLICY_SKYVAULT_DRIVE_SKYVAULT_UPLOADER_H_

#include <optional>
#include <string>

#include "base/files/file_path.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "chrome/browser/ash/drive/drive_integration_service.h"
#include "chrome/browser/ash/drive/file_system_util.h"
#include "chrome/browser/ash/file_manager/io_task_controller.h"
#include "chrome/browser/ash/policy/skyvault/policy_utils.h"
#include "chromeos/ash/components/drivefs/drivefs_host.h"
#include "chromeos/ash/components/drivefs/mojom/drivefs.mojom.h"
#include "storage/browser/file_system/file_system_context.h"
#include "storage/browser/file_system/file_system_url.h"

class Profile;

namespace policy::local_user_files {

// Manages the "upload to Drive" workflow as part of the SkyVault files
// migration. Starts with moving the file to the cloud. Gets upload status by
// observing move and Drive events. Calls the UploadCallback with once the
// upload is completed, passing the error if any occurred.
// TODO(b/353475473): Extract code shared with DriveUploadObserver, if possible.
class DriveSkyvaultUploader
    : public file_manager::io_task::IOTaskController::Observer,
      drivefs::DriveFsHost::Observer,
      drive::DriveIntegrationService::Observer {
 public:
  // Called when the upload finishes. Parameters:
  //   error: The upload error, if any.
  //   upload_root_path: Path to the upload root, or empty on early failure.
  using UploadCallback =
      base::OnceCallback<void(std::optional<MigrationUploadError>,
                              base::FilePath)>;

  DriveSkyvaultUploader(Profile* profile,
                        const base::FilePath& file_path,
                        const base::FilePath& relative_source_path,
                        const std::string& upload_root,
                        UploadCallback callback);
  ~DriveSkyvaultUploader() override;

  // Starts the upload workflow:
  // - Copy the file via an IO task.
  // - Sync to Drive.
  // - Remove the source file in case of a move operation. Move mode of the
  //   `CopyOrMoveIOTask` is not used because the source file should only be
  //   deleted at the end of the sync operation.
  void Run();

  // Cancels the upload, if possible.
  void Cancel();

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

  void SetFailDeleteForTesting(bool fail);

 private:
  // Starts the IOTask to upload the file to Google Drive to
  // `destination_folder_path`, if it was created successfully and fails the
  // operation otherwise.
  void CreateCopyIOTask(const base::FilePath& destination_folder_path,
                        bool created);

  // Called when copy to Drive completes. Cleans up files if needed, or
  // completes the operation immediately. Saves `error` so it's not overridden
  // if delete fails.
  void OnEndCopy(std::optional<MigrationUploadError> error = std::nullopt);

  // Called after unrecoverable error or when all tasks complete successfully.
  // Invokes the upload callback, passing the error if any occurred.
  void OnEndUpload();

  // Callback for when ImmediatelyUpload() is called on DriveFS.
  void ImmediatelyUploadDone(drive::FileError error);

  // Directs IO task status updates to |OnCopyStatus| or |OnDeleteStatus| based
  // on task id.
  void OnIOTaskStatus(
      const file_manager::io_task::ProgressStatus& status) override;

  // Observes copy to Drive IO task status updates. Calls `OnEndCopy` upon any
  // error.
  void OnCopyStatus(const file_manager::io_task::ProgressStatus& status);

  // Observes delete IO task status updates from the delete task for cleaning up
  // the source file. Calls `OnEndUpload` once the delete is finished.
  void OnDeleteStatus(const file_manager::io_task::ProgressStatus& status);

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

  // DriveFsHost::Observer implementation.
  void OnUnmounted() override;
  void OnSyncingStatusUpdate(
      const drivefs::mojom::SyncingStatus& status) override;
  void OnError(const drivefs::mojom::DriveError& error) override;

  // DriveIntegrationService::Observer implementation.
  void OnDriveConnectionStatusChanged(
      drive::util::ConnectionStatus status) override;

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

  // Test-only: Simulates a delete failure if true. Actual result of the
  // DeleteIO task is ignored.
  bool fail_delete_for_testing_ = false;

  const raw_ptr<Profile> profile_;
  scoped_refptr<storage::FileSystemContext> file_system_context_;
  const raw_ptr<drive::DriveIntegrationService> drive_integration_service_;

  // Upload details:
  // Source file URL
  const storage::FileSystemURL source_url_;
  // 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_;
  // 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_;
  // Invoked on completion
  UploadCallback callback_;

  // Tracks upload progress:
  std::optional<file_manager::io_task::IOTaskId> observed_copy_task_id_ =
      std::nullopt;
  std::optional<file_manager::io_task::IOTaskId> observed_delete_task_id_ =
      std::nullopt;
  base::FilePath observed_absolute_dest_path_;
  base::FilePath observed_relative_drive_path_;

  // Whether `EndCopy()` was called.
  bool copy_ended_ = false;

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

  // 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_;

  // Stores the first encountered error, if any.
  std::optional<MigrationUploadError> error_;

  raw_ptr<file_manager::io_task::IOTaskController> io_task_controller_ =
      nullptr;
  base::ScopedObservation<file_manager::io_task::IOTaskController,
                          file_manager::io_task::IOTaskController::Observer>
      io_task_controller_observer_{this};

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

}  // namespace policy::local_user_files

#endif  // CHROME_BROWSER_ASH_POLICY_SKYVAULT_DRIVE_SKYVAULT_UPLOADER_H_