1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_DRIVE_DRIVE_UPLOADER_H_
6#define CHROME_BROWSER_DRIVE_DRIVE_UPLOADER_H_
7
8#include <string>
9
10#include "base/basictypes.h"
11#include "base/callback_forward.h"
12#include "base/memory/ref_counted.h"
13#include "base/memory/weak_ptr.h"
14#include "chrome/browser/drive/drive_service_interface.h"
15#include "google_apis/drive/gdata_errorcode.h"
16
17class GURL;
18
19namespace base {
20class FilePath;
21class TaskRunner;
22}
23
24namespace google_apis {
25struct UploadRangeResponse;
26}
27
28namespace drive {
29class DriveServiceInterface;
30
31// Callback to be invoked once the upload has completed.
32// |upload_location| will be returned when the uploading process is started but
33// terminated before the completion due to some errors. It can be used to
34// resume it.
35typedef base::Callback<void(
36    google_apis::GDataErrorCode error,
37    const GURL& upload_location,
38    scoped_ptr<google_apis::FileResource> resource_entry)>
39    UploadCompletionCallback;
40
41class DriveUploaderInterface {
42 public:
43  typedef DriveServiceInterface::InitiateUploadNewFileOptions
44      UploadNewFileOptions;
45  typedef DriveServiceInterface::InitiateUploadExistingFileOptions
46      UploadExistingFileOptions;
47
48  virtual ~DriveUploaderInterface() {}
49
50  // Uploads a new file to a directory specified by |upload_location|.
51  // Returns a callback for cancelling the uploading job.
52  //
53  // parent_resource_id:
54  //   resource id of the destination directory.
55  //
56  // local_file_path:
57  //   The path to the local file to be uploaded.
58  //
59  // title:
60  //   The title (file name) of the file to be uploaded.
61  //
62  // content_type:
63  //   The content type of the file to be uploaded.
64  //
65  // callback:
66  //   Called when an upload is done regardless of it was successful or not.
67  //   Must not be null.
68  //
69  // progress_callback:
70  //   Periodically called back with the total number of bytes sent so far.
71  //   May be null if the information is not needed.
72  virtual google_apis::CancelCallback UploadNewFile(
73      const std::string& parent_resource_id,
74      const base::FilePath& local_file_path,
75      const std::string& title,
76      const std::string& content_type,
77      const UploadNewFileOptions& options,
78      const UploadCompletionCallback& callback,
79      const google_apis::ProgressCallback& progress_callback) = 0;
80
81  // Uploads an existing file (a file that already exists on Drive).
82  //
83  // See comments at UploadNewFile about common parameters and the return value.
84  //
85  // resource_id:
86  //   resource id of the existing file to be overwritten.
87  //
88  // etag:
89  //   Expected ETag for the destination file. If it does not match, the upload
90  //   fails with UPLOAD_ERROR_CONFLICT.
91  //   If |etag| is empty, the test is skipped.
92  virtual google_apis::CancelCallback UploadExistingFile(
93      const std::string& resource_id,
94      const base::FilePath& local_file_path,
95      const std::string& content_type,
96      const UploadExistingFileOptions& options,
97      const UploadCompletionCallback& callback,
98      const google_apis::ProgressCallback& progress_callback) = 0;
99
100  // Resumes the uploading process terminated before the completion.
101  // |upload_location| should be the one returned via UploadCompletionCallback
102  // for previous invocation. |drive_file_path|, |local_file_path| and
103  // |content_type| must be set to the same ones for previous invocation.
104  //
105  // See comments at UploadNewFile about common parameters and the return value.
106  virtual google_apis::CancelCallback ResumeUploadFile(
107      const GURL& upload_location,
108      const base::FilePath& local_file_path,
109      const std::string& content_type,
110      const UploadCompletionCallback& callback,
111      const google_apis::ProgressCallback& progress_callback) = 0;
112};
113
114class DriveUploader : public DriveUploaderInterface {
115 public:
116  DriveUploader(DriveServiceInterface* drive_service,
117                const scoped_refptr<base::TaskRunner>& blocking_task_runner);
118  virtual ~DriveUploader();
119
120  // DriveUploaderInterface overrides.
121  virtual google_apis::CancelCallback UploadNewFile(
122      const std::string& parent_resource_id,
123      const base::FilePath& local_file_path,
124      const std::string& title,
125      const std::string& content_type,
126      const UploadNewFileOptions& options,
127      const UploadCompletionCallback& callback,
128      const google_apis::ProgressCallback& progress_callback) OVERRIDE;
129  virtual google_apis::CancelCallback UploadExistingFile(
130      const std::string& resource_id,
131      const base::FilePath& local_file_path,
132      const std::string& content_type,
133      const UploadExistingFileOptions& options,
134      const UploadCompletionCallback& callback,
135      const google_apis::ProgressCallback& progress_callback) OVERRIDE;
136  virtual google_apis::CancelCallback ResumeUploadFile(
137      const GURL& upload_location,
138      const base::FilePath& local_file_path,
139      const std::string& content_type,
140      const UploadCompletionCallback& callback,
141      const google_apis::ProgressCallback& progress_callback) OVERRIDE;
142
143 private:
144  struct UploadFileInfo;
145  typedef base::Callback<void(scoped_ptr<UploadFileInfo> upload_file_info)>
146      StartInitiateUploadCallback;
147
148  // Starts uploading a file with |upload_file_info|.
149  google_apis::CancelCallback StartUploadFile(
150      scoped_ptr<UploadFileInfo> upload_file_info,
151      const StartInitiateUploadCallback& start_initiate_upload_callback);
152  void StartUploadFileAfterGetFileSize(
153      scoped_ptr<UploadFileInfo> upload_file_info,
154      const StartInitiateUploadCallback& start_initiate_upload_callback,
155      bool get_file_size_result);
156
157  // Starts to initiate the new file uploading.
158  // Upon completion, OnUploadLocationReceived should be called.
159  void StartInitiateUploadNewFile(
160      const std::string& parent_resource_id,
161      const std::string& title,
162      const UploadNewFileOptions& options,
163      scoped_ptr<UploadFileInfo> upload_file_info);
164
165  // Starts to initiate the existing file uploading.
166  // Upon completion, OnUploadLocationReceived should be called.
167  void StartInitiateUploadExistingFile(
168      const std::string& resource_id,
169      const UploadExistingFileOptions& options,
170      scoped_ptr<UploadFileInfo> upload_file_info);
171
172  // DriveService callback for InitiateUpload.
173  void OnUploadLocationReceived(scoped_ptr<UploadFileInfo> upload_file_info,
174                                google_apis::GDataErrorCode code,
175                                const GURL& upload_location);
176
177  // Starts to get the current upload status for the file uploading.
178  // Upon completion, OnUploadRangeResponseReceived should be called.
179  void StartGetUploadStatus(scoped_ptr<UploadFileInfo> upload_file_info);
180
181  // Uploads the next chunk of data from the file.
182  void UploadNextChunk(scoped_ptr<UploadFileInfo> upload_file_info);
183
184  // DriveService callback for ResumeUpload.
185  void OnUploadRangeResponseReceived(
186      scoped_ptr<UploadFileInfo> upload_file_info,
187      const google_apis::UploadRangeResponse& response,
188      scoped_ptr<google_apis::FileResource> entry);
189  void OnUploadProgress(const google_apis::ProgressCallback& callback,
190                        int64 start_position,
191                        int64 total_size,
192                        int64 progress_of_chunk,
193                        int64 total_of_chunk);
194
195  // Handle failed uploads.
196  void UploadFailed(scoped_ptr<UploadFileInfo> upload_file_info,
197                    google_apis::GDataErrorCode error);
198
199  // The lifetime of this object should be guaranteed to exceed that of the
200  // DriveUploader instance.
201  DriveServiceInterface* drive_service_;  // Not owned by this class.
202
203  scoped_refptr<base::TaskRunner> blocking_task_runner_;
204
205  // Note: This should remain the last member so it'll be destroyed and
206  // invalidate its weak pointers before any other members are destroyed.
207  base::WeakPtrFactory<DriveUploader> weak_ptr_factory_;
208  DISALLOW_COPY_AND_ASSIGN(DriveUploader);
209};
210
211}  // namespace drive
212
213#endif  // CHROME_BROWSER_DRIVE_DRIVE_UPLOADER_H_
214