summaryrefslogtreecommitdiffstats
path: root/components/drive/drive_uploader.h
blob: 13ab9a7cc3127332b60edb94d5595b151d581f02 (plain)
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
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_DRIVE_DRIVE_UPLOADER_H_
#define COMPONENTS_DRIVE_DRIVE_UPLOADER_H_

#include <stdint.h>

#include <string>

#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "components/drive/service/drive_service_interface.h"
#include "google_apis/drive/drive_api_error_codes.h"

class GURL;

namespace base {
class FilePath;
class TaskRunner;
}

namespace google_apis {
struct UploadRangeResponse;
}

namespace drive {
class DriveServiceInterface;

// Callback to be invoked once the upload has completed.
// |upload_location| will be returned when the uploading process is started but
// terminated before the completion due to some errors. It can be used to
// resume it.
typedef base::Callback<void(
    google_apis::DriveApiErrorCode error,
    const GURL& upload_location,
    scoped_ptr<google_apis::FileResource> resource_entry)>
    UploadCompletionCallback;

class DriveUploaderInterface {
 public:
  virtual ~DriveUploaderInterface() {}

  // Starts batch processing for upload requests. All requests which upload
  // small files (less than kMaxMultipartUploadSize) between
  // |StartBatchProcessing| and |StopBatchProcessing| are sent as a single batch
  // request.
  virtual void StartBatchProcessing() = 0;

  // Stops batch processing. Must be called after calling |StartBatchProcessing|
  // to commit requests.
  virtual void StopBatchProcessing() = 0;

  // Uploads a new file to a directory specified by |upload_location|.
  // Returns a callback for cancelling the uploading job.
  //
  // parent_resource_id:
  //   resource id of the destination directory.
  //
  // local_file_path:
  //   The path to the local file to be uploaded.
  //
  // title:
  //   The title (file name) of the file to be uploaded.
  //
  // content_type:
  //   The content type of the file to be uploaded.
  //
  // callback:
  //   Called when an upload is done regardless of it was successful or not.
  //   Must not be null.
  //
  // progress_callback:
  //   Periodically called back with the total number of bytes sent so far.
  //   May be null if the information is not needed.
  virtual google_apis::CancelCallback UploadNewFile(
      const std::string& parent_resource_id,
      const base::FilePath& local_file_path,
      const std::string& title,
      const std::string& content_type,
      const UploadNewFileOptions& options,
      const UploadCompletionCallback& callback,
      const google_apis::ProgressCallback& progress_callback) = 0;

  // Uploads an existing file (a file that already exists on Drive).
  //
  // See comments at UploadNewFile about common parameters and the return value.
  //
  // resource_id:
  //   resource id of the existing file to be overwritten.
  //
  // etag:
  //   Expected ETag for the destination file. If it does not match, the upload
  //   fails with UPLOAD_ERROR_CONFLICT.
  //   If |etag| is empty, the test is skipped.
  virtual google_apis::CancelCallback UploadExistingFile(
      const std::string& resource_id,
      const base::FilePath& local_file_path,
      const std::string& content_type,
      const UploadExistingFileOptions& options,
      const UploadCompletionCallback& callback,
      const google_apis::ProgressCallback& progress_callback) = 0;

  // Resumes the uploading process terminated before the completion.
  // |upload_location| should be the one returned via UploadCompletionCallback
  // for previous invocation. |drive_file_path|, |local_file_path| and
  // |content_type| must be set to the same ones for previous invocation.
  //
  // See comments at UploadNewFile about common parameters and the return value.
  virtual google_apis::CancelCallback ResumeUploadFile(
      const GURL& upload_location,
      const base::FilePath& local_file_path,
      const std::string& content_type,
      const UploadCompletionCallback& callback,
      const google_apis::ProgressCallback& progress_callback) = 0;
};

class DriveUploader : public DriveUploaderInterface {
 public:
  DriveUploader(DriveServiceInterface* drive_service,
                const scoped_refptr<base::TaskRunner>& blocking_task_runner);
  ~DriveUploader() override;

  // DriveUploaderInterface overrides.
  void StartBatchProcessing() override;
  void StopBatchProcessing() override;
  google_apis::CancelCallback UploadNewFile(
      const std::string& parent_resource_id,
      const base::FilePath& local_file_path,
      const std::string& title,
      const std::string& content_type,
      const UploadNewFileOptions& options,
      const UploadCompletionCallback& callback,
      const google_apis::ProgressCallback& progress_callback) override;
  google_apis::CancelCallback UploadExistingFile(
      const std::string& resource_id,
      const base::FilePath& local_file_path,
      const std::string& content_type,
      const UploadExistingFileOptions& options,
      const UploadCompletionCallback& callback,
      const google_apis::ProgressCallback& progress_callback) override;
  google_apis::CancelCallback ResumeUploadFile(
      const GURL& upload_location,
      const base::FilePath& local_file_path,
      const std::string& content_type,
      const UploadCompletionCallback& callback,
      const google_apis::ProgressCallback& progress_callback) override;

 private:
  class RefCountedBatchRequest;
  struct UploadFileInfo;
  typedef base::Callback<void(scoped_ptr<UploadFileInfo> upload_file_info)>
      StartInitiateUploadCallback;

  // Starts uploading a file with |upload_file_info|.
  google_apis::CancelCallback StartUploadFile(
      scoped_ptr<UploadFileInfo> upload_file_info,
      const StartInitiateUploadCallback& start_initiate_upload_callback);
  void StartUploadFileAfterGetFileSize(
      scoped_ptr<UploadFileInfo> upload_file_info,
      const StartInitiateUploadCallback& start_initiate_upload_callback,
      bool get_file_size_result);

  // Checks file size and call InitiateUploadNewFile or MultipartUploadNewFile
  // API.  Upon completion, OnUploadLocationReceived (for InitiateUploadNewFile)
  // or OnMultipartUploadComplete (for MultipartUploadNewFile) should be called.
  // If |batch_request| is non-null, it calls the API function on the batch
  // request.
  void CallUploadServiceAPINewFile(
      const std::string& parent_resource_id,
      const std::string& title,
      const UploadNewFileOptions& options,
      const scoped_refptr<RefCountedBatchRequest>& batch_request,
      scoped_ptr<UploadFileInfo> upload_file_info);

  // Checks file size and call InitiateUploadExistingFile or
  // MultipartUploadExistingFile API.  Upon completion, OnUploadLocationReceived
  // (for InitiateUploadExistingFile) or OnMultipartUploadComplete (for
  // MultipartUploadExistingFile) should be called.
  // If |batch_request| is non-null, it calls the API function on the batch
  // request.
  void CallUploadServiceAPIExistingFile(
      const std::string& resource_id,
      const UploadExistingFileOptions& options,
      const scoped_refptr<RefCountedBatchRequest>& batch_request,
      scoped_ptr<UploadFileInfo> upload_file_info);

  // DriveService callback for InitiateUpload.
  void OnUploadLocationReceived(scoped_ptr<UploadFileInfo> upload_file_info,
                                google_apis::DriveApiErrorCode code,
                                const GURL& upload_location);

  // Starts to get the current upload status for the file uploading.
  // Upon completion, OnUploadRangeResponseReceived should be called.
  void StartGetUploadStatus(scoped_ptr<UploadFileInfo> upload_file_info);

  // Uploads the next chunk of data from the file.
  void UploadNextChunk(scoped_ptr<UploadFileInfo> upload_file_info);

  // DriveService callback for ResumeUpload.
  void OnUploadRangeResponseReceived(
      scoped_ptr<UploadFileInfo> upload_file_info,
      const google_apis::UploadRangeResponse& response,
      scoped_ptr<google_apis::FileResource> entry);
  void OnUploadProgress(const google_apis::ProgressCallback& callback,
                        int64_t start_position,
                        int64_t total_size,
                        int64_t progress_of_chunk,
                        int64_t total_of_chunk);

  // Handles failed uploads.
  void UploadFailed(scoped_ptr<UploadFileInfo> upload_file_info,
                    google_apis::DriveApiErrorCode error);

  // Handles completion/error of multipart uploading.
  void OnMultipartUploadComplete(scoped_ptr<UploadFileInfo> upload_file_info,
                                 google_apis::DriveApiErrorCode error,
                                 scoped_ptr<google_apis::FileResource> entry);

  // The class is expected to run on UI thread.
  base::ThreadChecker thread_checker_;

  // The lifetime of this object should be guaranteed to exceed that of the
  // DriveUploader instance.
  DriveServiceInterface* drive_service_;  // Not owned by this class.

  scoped_refptr<base::TaskRunner> blocking_task_runner_;
  scoped_refptr<RefCountedBatchRequest> current_batch_request_;

  // Note: This should remain the last member so it'll be destroyed and
  // invalidate its weak pointers before any other members are destroyed.
  base::WeakPtrFactory<DriveUploader> weak_ptr_factory_;
  DISALLOW_COPY_AND_ASSIGN(DriveUploader);
};

}  // namespace drive

#endif  // COMPONENTS_DRIVE_DRIVE_UPLOADER_H_