OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/drive/drive_uploader.h" | 5 #include "chrome/browser/drive/drive_uploader.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
(...skipping 26 matching lines...) Expand all Loading... |
37 // bytes (except the request for uploading the last chunk of data). | 37 // bytes (except the request for uploading the last chunk of data). |
38 // The value must be a multiple of 512KB according to the spec of GData WAPI and | 38 // The value must be a multiple of 512KB according to the spec of GData WAPI and |
39 // Drive API v2. It is set to a smaller value than 2^31 for working around | 39 // Drive API v2. It is set to a smaller value than 2^31 for working around |
40 // server side error (crbug.com/264089). | 40 // server side error (crbug.com/264089). |
41 const int64 kUploadChunkSize = (1LL << 30); // 1GB | 41 const int64 kUploadChunkSize = (1LL << 30); // 1GB |
42 // Maximum file size to be uploaded by multipart requests. The file that is | 42 // Maximum file size to be uploaded by multipart requests. The file that is |
43 // larger than the size is processed by resumable upload. | 43 // larger than the size is processed by resumable upload. |
44 const int64 kMaxMultipartUploadSize = (1LL << 20); // 1MB | 44 const int64 kMaxMultipartUploadSize = (1LL << 20); // 1MB |
45 } // namespace | 45 } // namespace |
46 | 46 |
47 // Refcounted helper class to manage batch request. DriveUploader uses the class | |
48 // for keeping the BatchRequestConfigurator instance while it prepares upload | |
49 // file information asynchronously. DriveUploader discard the reference after | |
50 // getting file information and the instance will be destroyed after all | |
51 // preparations complete. At that time, the helper instance commits owned batch | |
52 // request at the destrutor. | |
53 class DriveUploader::RefCountedBatchRequest | |
54 : public base::RefCounted<RefCountedBatchRequest> { | |
55 public: | |
56 RefCountedBatchRequest( | |
57 scoped_ptr<BatchRequestConfiguratorInterface> configurator) | |
58 : configurator_(configurator.Pass()) {} | |
59 | |
60 // Gets pointer of BatchRequestConfiguratorInterface owned by the instance. | |
61 BatchRequestConfiguratorInterface* configurator() const { | |
62 return configurator_.get(); | |
63 } | |
64 | |
65 private: | |
66 friend class base::RefCounted<RefCountedBatchRequest>; | |
67 ~RefCountedBatchRequest() { configurator_->Commit(); } | |
68 scoped_ptr<BatchRequestConfiguratorInterface> configurator_; | |
69 }; | |
70 | |
71 // Structure containing current upload information of file, passed between | 47 // Structure containing current upload information of file, passed between |
72 // DriveServiceInterface methods and callbacks. | 48 // DriveServiceInterface methods and callbacks. |
73 struct DriveUploader::UploadFileInfo { | 49 struct DriveUploader::UploadFileInfo { |
74 UploadFileInfo(const base::FilePath& local_path, | 50 UploadFileInfo(const base::FilePath& local_path, |
75 const std::string& content_type, | 51 const std::string& content_type, |
76 const UploadCompletionCallback& callback, | 52 const UploadCompletionCallback& callback, |
77 const ProgressCallback& progress_callback) | 53 const ProgressCallback& progress_callback) |
78 : file_path(local_path), | 54 : file_path(local_path), |
79 content_type(content_type), | 55 content_type(content_type), |
80 completion_callback(callback), | 56 completion_callback(callback), |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 DCHECK(!local_file_path.empty()); | 148 DCHECK(!local_file_path.empty()); |
173 DCHECK(!title.empty()); | 149 DCHECK(!title.empty()); |
174 DCHECK(!content_type.empty()); | 150 DCHECK(!content_type.empty()); |
175 DCHECK(!callback.is_null()); | 151 DCHECK(!callback.is_null()); |
176 | 152 |
177 return StartUploadFile( | 153 return StartUploadFile( |
178 scoped_ptr<UploadFileInfo>(new UploadFileInfo( | 154 scoped_ptr<UploadFileInfo>(new UploadFileInfo( |
179 local_file_path, content_type, callback, progress_callback)), | 155 local_file_path, content_type, callback, progress_callback)), |
180 base::Bind(&DriveUploader::CallUploadServiceAPINewFile, | 156 base::Bind(&DriveUploader::CallUploadServiceAPINewFile, |
181 weak_ptr_factory_.GetWeakPtr(), parent_resource_id, title, | 157 weak_ptr_factory_.GetWeakPtr(), parent_resource_id, title, |
182 options, current_batch_request_)); | 158 options)); |
183 } | |
184 | |
185 void DriveUploader::StartBatchProcessing() { | |
186 DCHECK(current_batch_request_ == nullptr); | |
187 current_batch_request_ = | |
188 new RefCountedBatchRequest(drive_service_->StartBatchRequest().Pass()); | |
189 } | |
190 | |
191 void DriveUploader::StopBatchProcessing() { | |
192 current_batch_request_ = nullptr; | |
193 } | 159 } |
194 | 160 |
195 CancelCallback DriveUploader::UploadExistingFile( | 161 CancelCallback DriveUploader::UploadExistingFile( |
196 const std::string& resource_id, | 162 const std::string& resource_id, |
197 const base::FilePath& local_file_path, | 163 const base::FilePath& local_file_path, |
198 const std::string& content_type, | 164 const std::string& content_type, |
199 const UploadExistingFileOptions& options, | 165 const UploadExistingFileOptions& options, |
200 const UploadCompletionCallback& callback, | 166 const UploadCompletionCallback& callback, |
201 const ProgressCallback& progress_callback) { | 167 const ProgressCallback& progress_callback) { |
202 DCHECK(thread_checker_.CalledOnValidThread()); | 168 DCHECK(thread_checker_.CalledOnValidThread()); |
203 DCHECK(!resource_id.empty()); | 169 DCHECK(!resource_id.empty()); |
204 DCHECK(!local_file_path.empty()); | 170 DCHECK(!local_file_path.empty()); |
205 DCHECK(!content_type.empty()); | 171 DCHECK(!content_type.empty()); |
206 DCHECK(!callback.is_null()); | 172 DCHECK(!callback.is_null()); |
207 | 173 |
208 return StartUploadFile( | 174 return StartUploadFile( |
209 scoped_ptr<UploadFileInfo>(new UploadFileInfo( | 175 scoped_ptr<UploadFileInfo>(new UploadFileInfo( |
210 local_file_path, content_type, callback, progress_callback)), | 176 local_file_path, content_type, callback, progress_callback)), |
211 base::Bind(&DriveUploader::CallUploadServiceAPIExistingFile, | 177 base::Bind(&DriveUploader::CallUploadServiceAPIExistingFile, |
212 weak_ptr_factory_.GetWeakPtr(), resource_id, options, | 178 weak_ptr_factory_.GetWeakPtr(), resource_id, options)); |
213 current_batch_request_)); | |
214 } | 179 } |
215 | 180 |
216 CancelCallback DriveUploader::ResumeUploadFile( | 181 CancelCallback DriveUploader::ResumeUploadFile( |
217 const GURL& upload_location, | 182 const GURL& upload_location, |
218 const base::FilePath& local_file_path, | 183 const base::FilePath& local_file_path, |
219 const std::string& content_type, | 184 const std::string& content_type, |
220 const UploadCompletionCallback& callback, | 185 const UploadCompletionCallback& callback, |
221 const ProgressCallback& progress_callback) { | 186 const ProgressCallback& progress_callback) { |
222 DCHECK(thread_checker_.CalledOnValidThread()); | 187 DCHECK(thread_checker_.CalledOnValidThread()); |
223 DCHECK(!local_file_path.empty()); | 188 DCHECK(!local_file_path.empty()); |
224 DCHECK(!content_type.empty()); | 189 DCHECK(!content_type.empty()); |
225 DCHECK(!callback.is_null()); | 190 DCHECK(!callback.is_null()); |
226 | 191 |
227 scoped_ptr<UploadFileInfo> upload_file_info(new UploadFileInfo( | 192 scoped_ptr<UploadFileInfo> upload_file_info(new UploadFileInfo( |
228 local_file_path, content_type, callback, progress_callback)); | 193 local_file_path, content_type, |
| 194 callback, progress_callback)); |
229 upload_file_info->upload_location = upload_location; | 195 upload_file_info->upload_location = upload_location; |
230 | 196 |
231 return StartUploadFile( | 197 return StartUploadFile( |
232 upload_file_info.Pass(), | 198 upload_file_info.Pass(), |
233 base::Bind(&DriveUploader::StartGetUploadStatus, | 199 base::Bind(&DriveUploader::StartGetUploadStatus, |
234 weak_ptr_factory_.GetWeakPtr())); | 200 weak_ptr_factory_.GetWeakPtr())); |
235 } | 201 } |
236 | 202 |
237 CancelCallback DriveUploader::StartUploadFile( | 203 CancelCallback DriveUploader::StartUploadFile( |
238 scoped_ptr<UploadFileInfo> upload_file_info, | 204 scoped_ptr<UploadFileInfo> upload_file_info, |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 UploadFailed(upload_file_info.Pass(), DRIVE_CANCELLED); | 236 UploadFailed(upload_file_info.Pass(), DRIVE_CANCELLED); |
271 return; | 237 return; |
272 } | 238 } |
273 start_initiate_upload_callback.Run(upload_file_info.Pass()); | 239 start_initiate_upload_callback.Run(upload_file_info.Pass()); |
274 } | 240 } |
275 | 241 |
276 void DriveUploader::CallUploadServiceAPINewFile( | 242 void DriveUploader::CallUploadServiceAPINewFile( |
277 const std::string& parent_resource_id, | 243 const std::string& parent_resource_id, |
278 const std::string& title, | 244 const std::string& title, |
279 const UploadNewFileOptions& options, | 245 const UploadNewFileOptions& options, |
280 const scoped_refptr<RefCountedBatchRequest>& batch_request, | |
281 scoped_ptr<UploadFileInfo> upload_file_info) { | 246 scoped_ptr<UploadFileInfo> upload_file_info) { |
282 DCHECK(thread_checker_.CalledOnValidThread()); | 247 DCHECK(thread_checker_.CalledOnValidThread()); |
283 | 248 |
284 UploadFileInfo* const info_ptr = upload_file_info.get(); | 249 UploadFileInfo* const info_ptr = upload_file_info.get(); |
285 if (info_ptr->content_length <= kMaxMultipartUploadSize) { | 250 if (info_ptr->content_length <= kMaxMultipartUploadSize) { |
286 DriveServiceBatchOperationsInterface* service = drive_service_; | 251 info_ptr->cancel_callback = drive_service_->MultipartUploadNewFile( |
287 // If this is a batched request, calls the API on the request instead. | |
288 if (batch_request.get()) | |
289 service = batch_request->configurator(); | |
290 info_ptr->cancel_callback = service->MultipartUploadNewFile( | |
291 info_ptr->content_type, info_ptr->content_length, parent_resource_id, | 252 info_ptr->content_type, info_ptr->content_length, parent_resource_id, |
292 title, info_ptr->file_path, options, | 253 title, info_ptr->file_path, options, |
293 base::Bind(&DriveUploader::OnMultipartUploadComplete, | 254 base::Bind(&DriveUploader::OnMultipartUploadComplete, |
294 weak_ptr_factory_.GetWeakPtr(), | 255 weak_ptr_factory_.GetWeakPtr(), |
295 base::Passed(&upload_file_info)), | 256 base::Passed(&upload_file_info)), |
296 info_ptr->progress_callback); | 257 info_ptr->progress_callback); |
297 } else { | 258 } else { |
298 info_ptr->cancel_callback = drive_service_->InitiateUploadNewFile( | 259 info_ptr->cancel_callback = drive_service_->InitiateUploadNewFile( |
299 info_ptr->content_type, info_ptr->content_length, parent_resource_id, | 260 info_ptr->content_type, info_ptr->content_length, parent_resource_id, |
300 title, options, base::Bind(&DriveUploader::OnUploadLocationReceived, | 261 title, options, base::Bind(&DriveUploader::OnUploadLocationReceived, |
301 weak_ptr_factory_.GetWeakPtr(), | 262 weak_ptr_factory_.GetWeakPtr(), |
302 base::Passed(&upload_file_info))); | 263 base::Passed(&upload_file_info))); |
303 } | 264 } |
304 } | 265 } |
305 | 266 |
306 void DriveUploader::CallUploadServiceAPIExistingFile( | 267 void DriveUploader::CallUploadServiceAPIExistingFile( |
307 const std::string& resource_id, | 268 const std::string& resource_id, |
308 const UploadExistingFileOptions& options, | 269 const UploadExistingFileOptions& options, |
309 const scoped_refptr<RefCountedBatchRequest>& batch_request, | |
310 scoped_ptr<UploadFileInfo> upload_file_info) { | 270 scoped_ptr<UploadFileInfo> upload_file_info) { |
311 DCHECK(thread_checker_.CalledOnValidThread()); | 271 DCHECK(thread_checker_.CalledOnValidThread()); |
312 | 272 |
313 UploadFileInfo* const info_ptr = upload_file_info.get(); | 273 UploadFileInfo* const info_ptr = upload_file_info.get(); |
314 if (info_ptr->content_length <= kMaxMultipartUploadSize) { | 274 if (info_ptr->content_length <= kMaxMultipartUploadSize) { |
315 DriveServiceBatchOperationsInterface* service = drive_service_; | 275 info_ptr->cancel_callback = drive_service_->MultipartUploadExistingFile( |
316 // If this is a batched request, calls the API on the request instead. | |
317 if (batch_request.get()) | |
318 service = batch_request->configurator(); | |
319 info_ptr->cancel_callback = service->MultipartUploadExistingFile( | |
320 info_ptr->content_type, info_ptr->content_length, resource_id, | 276 info_ptr->content_type, info_ptr->content_length, resource_id, |
321 info_ptr->file_path, options, | 277 info_ptr->file_path, options, |
322 base::Bind(&DriveUploader::OnMultipartUploadComplete, | 278 base::Bind(&DriveUploader::OnMultipartUploadComplete, |
323 weak_ptr_factory_.GetWeakPtr(), | 279 weak_ptr_factory_.GetWeakPtr(), |
324 base::Passed(&upload_file_info)), | 280 base::Passed(&upload_file_info)), |
325 info_ptr->progress_callback); | 281 info_ptr->progress_callback); |
326 } else { | 282 } else { |
327 info_ptr->cancel_callback = drive_service_->InitiateUploadExistingFile( | 283 info_ptr->cancel_callback = drive_service_->InitiateUploadExistingFile( |
328 info_ptr->content_type, info_ptr->content_length, resource_id, options, | 284 info_ptr->content_type, info_ptr->content_length, resource_id, options, |
329 base::Bind(&DriveUploader::OnUploadLocationReceived, | 285 base::Bind(&DriveUploader::OnUploadLocationReceived, |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
497 } else { | 453 } else { |
498 DVLOG(1) << "Upload failed " << upload_file_info->DebugString(); | 454 DVLOG(1) << "Upload failed " << upload_file_info->DebugString(); |
499 if (error == HTTP_PRECONDITION) | 455 if (error == HTTP_PRECONDITION) |
500 error = HTTP_CONFLICT; // ETag mismatch. | 456 error = HTTP_CONFLICT; // ETag mismatch. |
501 upload_file_info->completion_callback.Run( | 457 upload_file_info->completion_callback.Run( |
502 error, upload_file_info->upload_location, scoped_ptr<FileResource>()); | 458 error, upload_file_info->upload_location, scoped_ptr<FileResource>()); |
503 } | 459 } |
504 } | 460 } |
505 | 461 |
506 } // namespace drive | 462 } // namespace drive |
OLD | NEW |