File: drive_upload_handler.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 (175 lines) | stat: -rw-r--r-- 7,909 bytes parent folder | download | duplicates (4)
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 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_UI_WEBUI_ASH_CLOUD_UPLOAD_DRIVE_UPLOAD_HANDLER_H_
#define CHROME_BROWSER_UI_WEBUI_ASH_CLOUD_UPLOAD_DRIVE_UPLOAD_HANDLER_H_

#include <memory>
#include <optional>
#include <string>

#include "base/files/file_path.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/types/expected.h"
#include "chrome/browser/ash/drive/drive_integration_service.h"
#include "chrome/browser/ash/drive/file_system_util.h"
#include "chrome/browser/ash/extensions/file_manager/scoped_suppress_drive_notifications_for_path.h"
#include "chrome/browser/ash/file_manager/io_task_controller.h"
#include "chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics.h"
#include "chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_notification_manager.h"
#include "chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.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"
#include "url/gurl.h"

class Profile;

namespace ash::cloud_upload {
FORWARD_DECLARE_TEST(DriveUploadHandlerTest, OnGetDriveMetadata_WhenNoMetadata);
FORWARD_DECLARE_TEST(DriveUploadHandlerTest,
                     OnGetDriveMetadata_WhenInvalidAlternateUrl);
FORWARD_DECLARE_TEST(DriveUploadHandlerTest,
                     OnGetDriveMetadata_WhenHostIsUnexpected);
FORWARD_DECLARE_TEST(DriveUploadHandlerTest,
                     OnGetDriveMetadata_WhenFileNotAnOfficeFile);

// Manages the "upload to Drive" workflow after user confirmation on the upload
// dialog. Instantiated by the static `Upload` method. Starts with moving the
// file to the cloud. Gets upload status by observing move and Drive events.
// Calls the UploadCallback with the uploaded file's hosted URL once the upload
// is completed, which is when `DriveUploadHandler` goes out of scope.
class DriveUploadHandler
    : public ::file_manager::io_task::IOTaskController::Observer,
      drivefs::DriveFsHost::Observer,
      drive::DriveIntegrationService::Observer {
 public:
  using UploadCallback =
      base::OnceCallback<void(OfficeTaskResult, std::optional<GURL>, int64_t)>;

  DriveUploadHandler(Profile* profile,
                     const storage::FileSystemURL& source_url,
                     UploadType upload_type,
                     UploadCallback callback,
                     base::SafeRef<CloudOpenMetrics> cloud_open_metrics);
  ~DriveUploadHandler() 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.
  // Initiated by the `Upload` static method.
  void Run();

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

  FRIEND_TEST_ALL_PREFIXES(DriveUploadHandlerTest,
                           OnGetDriveMetadata_WhenNoMetadata);
  FRIEND_TEST_ALL_PREFIXES(DriveUploadHandlerTest,
                           OnGetDriveMetadata_WhenInvalidAlternateUrl);
  FRIEND_TEST_ALL_PREFIXES(DriveUploadHandlerTest,
                           OnGetDriveMetadata_WhenHostIsUnexpected);
  FRIEND_TEST_ALL_PREFIXES(DriveUploadHandlerTest,
                           OnGetDriveMetadata_WhenFileNotAnOfficeFile);

 private:
  // Updates the progress notification for the upload workflow (copy + syncing).
  void UpdateProgressNotification();

  // Called upon a copy to Drive success or failure. If required, complete or
  // undo the operation. Then call |OnSuccessfulUpload| or |OnFailedUpload| to
  // end the successful or failed upload respectively.
  void OnEndCopy(OfficeFilesUploadResult result_metric,
                 base::expected<GURL, std::string> hosted_url =
                     base::unexpected(GetGenericErrorMessage()));

  // Ends upload in a successful state, shows a complete notification and runs
  // the upload callback.
  void OnSuccessfulUpload(OfficeFilesUploadResult result_metric,
                          GURL hosted_url);

  // Ends upload in a failed state, shows an error notification and runs the
  // upload callback.
  void OnFailedUpload(OfficeFilesUploadResult result_metric,
                      std::string error_message);

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

  // Find the base::File::Error error returned by the IO Task and convert it to
  // an appropriate error notification.
  void ShowIOTaskError(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;

  // Checks the alternate URL from the request file's metadata.
  void OnGetDriveMetadata(bool timed_out,
                          drive::FileError error,
                          drivefs::mojom::FileMetadataPtr metadata);

  // Get the uploaded file's alternate URL. `timed_out` indicates whether or not
  // the timeout for getting the alternate URL is hit.
  void CheckAlternateUrl(bool timed_out);

  const raw_ptr<Profile> profile_;
  scoped_refptr<storage::FileSystemContext> file_system_context_;
  raw_ptr<::file_manager::io_task::IOTaskController> io_task_controller_ =
      nullptr;
  const raw_ptr<drive::DriveIntegrationService> drive_integration_service_;
  const UploadType upload_type_;
  scoped_refptr<CloudUploadNotificationManager> notification_manager_;
  const storage::FileSystemURL source_url_;
  ::file_manager::io_task::IOTaskId observed_copy_task_id_;
  ::file_manager::io_task::IOTaskId observed_delete_task_id_;
  base::FilePath observed_absolute_dest_path_;
  base::FilePath observed_relative_drive_path_;
  bool copy_ended_ = false;
  int move_progress_ = 0;
  int sync_progress_ = 0;
  base::OneShotTimer alternate_url_timeout_;
  base::OneShotTimer alternate_url_poll_timer_;
  base::OnceClosure end_upload_callback_;
  UploadCallback callback_;
  // Total size (in bytes) required to upload.
  int64_t upload_size_ = 0;
  std::unique_ptr<::file_manager::ScopedSuppressDriveNotificationsForPath>
      scoped_suppress_drive_notifications_for_path_ = nullptr;
  base::ScopedObservation<::file_manager::io_task::IOTaskController,
                          ::file_manager::io_task::IOTaskController::Observer>
      io_task_controller_observer_{this};
  base::SafeRef<CloudOpenMetrics> cloud_open_metrics_;
  base::WeakPtrFactory<DriveUploadHandler> weak_ptr_factory_{this};
};

}  // namespace ash::cloud_upload

#endif  // CHROME_BROWSER_UI_WEBUI_ASH_CLOUD_UPLOAD_DRIVE_UPLOAD_HANDLER_H_