Chromium Code Reviews| 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/chromeos/gdata/gdata_uploader.h" | 5 #include "chrome/browser/chromeos/gdata/gdata_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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 66 // Create buffer to hold upload data. | 66 // Create buffer to hold upload data. |
| 67 info->buf_len = std::min(info->file_size, kUploadChunkSize); | 67 info->buf_len = std::min(info->file_size, kUploadChunkSize); |
| 68 info->buf = new net::IOBuffer(info->buf_len); | 68 info->buf = new net::IOBuffer(info->buf_len); |
| 69 | 69 |
| 70 OpenFile(info); | 70 OpenFile(info); |
| 71 return upload_id; | 71 return upload_id; |
| 72 } | 72 } |
| 73 | 73 |
| 74 void GDataUploader::UpdateUpload(int upload_id, | 74 void GDataUploader::UpdateUpload(int upload_id, |
| 75 content::DownloadItem* download) { | 75 content::DownloadItem* download) { |
| 76 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 77 | |
| 76 UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id); | 78 UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id); |
| 77 if (!upload_file_info) | 79 if (!upload_file_info) |
| 78 return; | 80 return; |
| 79 | 81 |
| 80 const int64 file_size = download->GetReceivedBytes(); | 82 const int64 file_size = download->GetReceivedBytes(); |
| 81 | 83 |
| 82 // Update file_size and all_bytes_present. | 84 // Update file_size and all_bytes_present. |
| 83 DVLOG(1) << "Updating file size from " << upload_file_info->file_size | 85 DVLOG(1) << "Updating file size from " << upload_file_info->file_size |
| 84 << " to " << file_size | 86 << " to " << file_size |
| 85 << (download->AllDataSaved() ? " (AllDataSaved)" : " (In-progress)"); | 87 << (download->AllDataSaved() ? " (AllDataSaved)" : " (In-progress)"); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 171 | 173 |
| 172 DVLOG(1) << "Error opening \"" << upload_file_info->file_path.value() | 174 DVLOG(1) << "Error opening \"" << upload_file_info->file_path.value() |
| 173 << "\" for reading: " << net::ErrorToString(result) | 175 << "\" for reading: " << net::ErrorToString(result) |
| 174 << ", tries=" << upload_file_info->num_file_open_tries; | 176 << ", tries=" << upload_file_info->num_file_open_tries; |
| 175 | 177 |
| 176 // Stop trying to open this file if we exceed kMaxFileOpenTries. | 178 // Stop trying to open this file if we exceed kMaxFileOpenTries. |
| 177 const bool exceeded_max_attempts = | 179 const bool exceeded_max_attempts = |
| 178 upload_file_info->num_file_open_tries >= kMaxFileOpenTries; | 180 upload_file_info->num_file_open_tries >= kMaxFileOpenTries; |
| 179 upload_file_info->should_retry_file_open = !exceeded_max_attempts; | 181 upload_file_info->should_retry_file_open = !exceeded_max_attempts; |
| 180 if (exceeded_max_attempts) | 182 if (exceeded_max_attempts) |
| 181 UploadFailed(upload_file_info, base::PLATFORM_FILE_ERROR_NOT_FOUND); | 183 UploadFailed(scoped_ptr<UploadFileInfo>(upload_file_info), |
| 184 base::PLATFORM_FILE_ERROR_NOT_FOUND); | |
| 182 | 185 |
| 183 return; | 186 return; |
| 184 } | 187 } |
| 185 | 188 |
| 186 // Open succeeded, initiate the upload. | 189 // Open succeeded, initiate the upload. |
| 187 upload_file_info->should_retry_file_open = false; | 190 upload_file_info->should_retry_file_open = false; |
| 188 const GURL destination_directory_url = file_system_->GetUploadUrlForDirectory( | 191 const GURL destination_directory_url = file_system_->GetUploadUrlForDirectory( |
| 189 upload_file_info->gdata_path.DirName()); | 192 upload_file_info->gdata_path.DirName()); |
| 190 if (destination_directory_url.is_empty()) { | 193 if (destination_directory_url.is_empty()) { |
| 191 UploadFailed(upload_file_info, base::PLATFORM_FILE_ERROR_ABORT); | 194 UploadFailed(scoped_ptr<UploadFileInfo>(upload_file_info), |
| 195 base::PLATFORM_FILE_ERROR_ABORT); | |
| 192 return; | 196 return; |
| 193 } | 197 } |
| 194 | 198 |
| 195 documents_service_->InitiateUpload( | 199 documents_service_->InitiateUpload( |
| 196 InitiateUploadParams(upload_file_info->title, | 200 InitiateUploadParams(upload_file_info->title, |
| 197 upload_file_info->content_type, | 201 upload_file_info->content_type, |
| 198 upload_file_info->content_length, | 202 upload_file_info->content_length, |
| 199 destination_directory_url, | 203 destination_directory_url, |
| 200 upload_file_info->gdata_path), | 204 upload_file_info->gdata_path), |
| 201 base::Bind(&GDataUploader::OnUploadLocationReceived, | 205 base::Bind(&GDataUploader::OnUploadLocationReceived, |
| 202 uploader_factory_.GetWeakPtr(), | 206 uploader_factory_.GetWeakPtr(), |
| 203 upload_file_info->upload_id)); | 207 upload_file_info->upload_id)); |
| 204 } | 208 } |
| 205 | 209 |
| 206 void GDataUploader::OnUploadLocationReceived( | 210 void GDataUploader::OnUploadLocationReceived( |
| 207 int upload_id, | 211 int upload_id, |
| 208 GDataErrorCode code, | 212 GDataErrorCode code, |
| 209 const GURL& upload_location) { | 213 const GURL& upload_location) { |
| 210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 214 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 211 | 215 |
| 212 UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id); | 216 UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id); |
| 213 if (!upload_file_info) | 217 if (!upload_file_info) |
| 214 return; | 218 return; |
| 215 | 219 |
| 216 DVLOG(1) << "Got upload location [" << upload_location.spec() | 220 DVLOG(1) << "Got upload location [" << upload_location.spec() |
| 217 << "] for [" << upload_file_info->title << "]"; | 221 << "] for [" << upload_file_info->title << "]"; |
| 218 | 222 |
| 219 if (code != HTTP_SUCCESS) { | 223 if (code != HTTP_SUCCESS) { |
| 220 // TODO(achuith): Handle error codes from Google Docs server. | 224 // TODO(achuith): Handle error codes from Google Docs server. |
| 221 UploadFailed(upload_file_info, base::PLATFORM_FILE_ERROR_ABORT); | 225 UploadFailed(scoped_ptr<UploadFileInfo>(upload_file_info), |
| 226 base::PLATFORM_FILE_ERROR_ABORT); | |
| 222 return; | 227 return; |
| 223 } | 228 } |
| 224 | 229 |
| 225 upload_file_info->upload_location = upload_location; | 230 upload_file_info->upload_location = upload_location; |
| 226 | 231 |
| 227 // Start the upload from the beginning of the file. | 232 // Start the upload from the beginning of the file. |
| 228 UploadNextChunk(upload_file_info); | 233 UploadNextChunk(upload_file_info); |
| 229 } | 234 } |
| 230 | 235 |
| 231 void GDataUploader::UploadNextChunk(UploadFileInfo* upload_file_info) { | 236 void GDataUploader::UploadNextChunk(UploadFileInfo* upload_file_info) { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 309 if (!upload_file_info) | 314 if (!upload_file_info) |
| 310 return; | 315 return; |
| 311 | 316 |
| 312 if (response.code == HTTP_CREATED) { | 317 if (response.code == HTTP_CREATED) { |
| 313 DVLOG(1) << "Successfully created uploaded file=[" | 318 DVLOG(1) << "Successfully created uploaded file=[" |
| 314 << upload_file_info->title; | 319 << upload_file_info->title; |
| 315 | 320 |
| 316 // Done uploading. | 321 // Done uploading. |
| 317 upload_file_info->entry = entry.Pass(); | 322 upload_file_info->entry = entry.Pass(); |
| 318 if (!upload_file_info->completion_callback.is_null()) { | 323 if (!upload_file_info->completion_callback.is_null()) { |
| 319 upload_file_info->completion_callback.Run(base::PLATFORM_FILE_OK, | 324 upload_file_info->completion_callback.Run( |
| 320 upload_file_info); | 325 base::PLATFORM_FILE_OK, |
| 326 scoped_ptr<UploadFileInfo>(upload_file_info)); | |
| 321 } | 327 } |
| 322 // TODO(achuith): DeleteUpload() here and let clients call | 328 |
| 323 // GDataFileSystem::AddUploadedFile. | 329 // Remove |upload_id| from the UploadFileInfoMap. The UploadFileInfo object |
| 330 // will be deleted upon completion of completion_callback. | |
| 331 RemoveUpload(upload_id); | |
|
achuithb
2012/06/15 01:53:10
RemoveUpload first before passing upload_file_info
hshi1
2012/06/15 02:02:47
Done.
| |
| 324 return; | 332 return; |
| 325 } | 333 } |
| 326 | 334 |
| 327 // If code is 308 (RESUME_INCOMPLETE) and range_received is what has been | 335 // If code is 308 (RESUME_INCOMPLETE) and range_received is what has been |
| 328 // previously uploaded (i.e. = upload_file_info->end_range), proceed to | 336 // previously uploaded (i.e. = upload_file_info->end_range), proceed to |
| 329 // upload the next chunk. | 337 // upload the next chunk. |
| 330 if (response.code != HTTP_RESUME_INCOMPLETE || | 338 if (response.code != HTTP_RESUME_INCOMPLETE || |
| 331 response.start_range_received != 0 || | 339 response.start_range_received != 0 || |
| 332 response.end_range_received != upload_file_info->end_range) { | 340 response.end_range_received != upload_file_info->end_range) { |
| 333 // TODO(achuith): Handle error cases, e.g. | 341 // TODO(achuith): Handle error cases, e.g. |
| 334 // - when previously uploaded data wasn't received by Google Docs server, | 342 // - when previously uploaded data wasn't received by Google Docs server, |
| 335 // i.e. when end_range_received < upload_file_info->end_range | 343 // i.e. when end_range_received < upload_file_info->end_range |
| 336 LOG(ERROR) << "UploadNextChunk http code=" << response.code | 344 LOG(ERROR) << "UploadNextChunk http code=" << response.code |
| 337 << ", start_range_received=" << response.start_range_received | 345 << ", start_range_received=" << response.start_range_received |
| 338 << ", end_range_received=" << response.end_range_received | 346 << ", end_range_received=" << response.end_range_received |
| 339 << ", expected end range=" << upload_file_info->end_range; | 347 << ", expected end range=" << upload_file_info->end_range; |
| 340 UploadFailed(upload_file_info, | 348 UploadFailed( |
| 349 scoped_ptr<UploadFileInfo>(upload_file_info), | |
| 341 response.code == HTTP_FORBIDDEN ? | 350 response.code == HTTP_FORBIDDEN ? |
| 342 base::PLATFORM_FILE_ERROR_NO_SPACE : | 351 base::PLATFORM_FILE_ERROR_NO_SPACE : |
| 343 base::PLATFORM_FILE_ERROR_ABORT); | 352 base::PLATFORM_FILE_ERROR_ABORT); |
| 344 return; | 353 return; |
| 345 } | 354 } |
| 346 | 355 |
| 347 DVLOG(1) << "Received range " << response.start_range_received | 356 DVLOG(1) << "Received range " << response.start_range_received |
| 348 << "-" << response.end_range_received | 357 << "-" << response.end_range_received |
| 349 << " for [" << upload_file_info->title << "]"; | 358 << " for [" << upload_file_info->title << "]"; |
| 350 | 359 |
| 351 // Continue uploading. | 360 // Continue uploading. |
| 352 UploadNextChunk(upload_file_info); | 361 UploadNextChunk(upload_file_info); |
| 353 } | 362 } |
| 354 | 363 |
| 355 void GDataUploader::MoveFileToCache(UploadFileInfo* upload_file_info) { | 364 void GDataUploader::MoveFileToCache(UploadFileInfo* upload_file_info) { |
| 356 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 365 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 357 if (upload_file_info->entry == NULL) | 366 if (upload_file_info->entry == NULL) |
| 358 return; | 367 return; |
| 359 | 368 |
| 369 const int upload_id = upload_file_info->upload_id; | |
| 360 DVLOG(1) << "MoveFileToCache " << upload_file_info->file_path.value(); | 370 DVLOG(1) << "MoveFileToCache " << upload_file_info->file_path.value(); |
| 361 file_system_->AddUploadedFile( | 371 file_system_->AddUploadedFile( |
| 362 upload_file_info->gdata_path.DirName(), | 372 upload_file_info->gdata_path.DirName(), |
| 363 upload_file_info->entry.get(), | 373 upload_file_info->entry.get(), |
| 364 upload_file_info->file_path, | 374 upload_file_info->file_path, |
| 365 GDataCache::FILE_OPERATION_MOVE); | 375 GDataCache::FILE_OPERATION_MOVE, |
| 366 DeleteUpload(upload_file_info); | 376 base::Bind(&base::DeletePointer<UploadFileInfo>, |
| 377 upload_file_info)); | |
| 378 | |
| 379 // Remove |upload_id| from the UploadFileInfoMap. The UploadFileInfo object | |
| 380 // will be deleted upon completion of AddUploadedFile. | |
| 381 RemoveUpload(upload_id); | |
| 367 } | 382 } |
| 368 | 383 |
| 369 void GDataUploader::UploadFailed(UploadFileInfo* upload_file_info, | 384 void GDataUploader::UploadFailed(scoped_ptr<UploadFileInfo> upload_file_info, |
| 370 base::PlatformFileError error) { | 385 base::PlatformFileError error) { |
| 371 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 386 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 387 | |
| 388 const int upload_id = upload_file_info->upload_id; | |
| 372 LOG(ERROR) << "Upload failed " << upload_file_info->DebugString(); | 389 LOG(ERROR) << "Upload failed " << upload_file_info->DebugString(); |
| 373 if (!upload_file_info->completion_callback.is_null()) { | 390 if (!upload_file_info->completion_callback.is_null()) { |
| 374 upload_file_info->completion_callback.Run(error, | 391 upload_file_info->completion_callback.Run(error, |
| 375 upload_file_info); | 392 upload_file_info.Pass()); |
| 376 } | 393 } |
| 377 DeleteUpload(upload_file_info); | 394 |
| 395 RemoveUpload(upload_id); | |
|
achuithb
2012/06/15 01:53:10
I think we want to RemoveUpload first. Otherwise t
hshi1
2012/06/15 02:02:47
Done.
| |
| 378 } | 396 } |
| 379 | 397 |
| 380 void GDataUploader::DeleteUpload(UploadFileInfo* upload_file_info) { | 398 void GDataUploader::RemoveUpload(int upload_id) { |
| 381 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 399 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 382 | 400 pending_uploads_.erase(upload_id); |
| 383 DVLOG(1) << "Deleting upload " << upload_file_info->gdata_path.value(); | |
| 384 pending_uploads_.erase(upload_file_info->upload_id); | |
| 385 | |
| 386 // The file stream is closed by the destructor asynchronously. | |
| 387 delete upload_file_info->file_stream; | |
| 388 delete upload_file_info; | |
| 389 } | 401 } |
| 390 | 402 |
| 391 } // namespace gdata | 403 } // namespace gdata |
| OLD | NEW |