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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 45 int GDataUploader::UploadFile(scoped_ptr<UploadFileInfo> upload_file_info) { | 45 int GDataUploader::UploadFile(scoped_ptr<UploadFileInfo> upload_file_info) { |
| 46 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 46 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 47 DCHECK(upload_file_info.get()); | 47 DCHECK(upload_file_info.get()); |
| 48 DCHECK_EQ(upload_file_info->upload_id, -1); | 48 DCHECK_EQ(upload_file_info->upload_id, -1); |
| 49 DCHECK(!upload_file_info->file_path.empty()); | 49 DCHECK(!upload_file_info->file_path.empty()); |
| 50 DCHECK_NE(upload_file_info->file_size, 0); | 50 DCHECK_NE(upload_file_info->file_size, 0); |
| 51 DCHECK(!upload_file_info->gdata_path.empty()); | 51 DCHECK(!upload_file_info->gdata_path.empty()); |
| 52 DCHECK(!upload_file_info->title.empty()); | 52 DCHECK(!upload_file_info->title.empty()); |
| 53 DCHECK(!upload_file_info->content_type.empty()); | 53 DCHECK(!upload_file_info->content_type.empty()); |
| 54 | 54 |
| 55 base::AutoLock lock(lock_); | |
| 56 | |
| 55 const int upload_id = next_upload_id_++; | 57 const int upload_id = next_upload_id_++; |
| 56 upload_file_info->upload_id = upload_id; | 58 upload_file_info->upload_id = upload_id; |
| 57 // Add upload_file_info to our internal map and take ownership. | 59 // Add upload_file_info to our internal map and take ownership. |
| 58 pending_uploads_[upload_id] = upload_file_info.release(); | 60 pending_uploads_[upload_id] = upload_file_info.release(); |
| 59 | 61 |
| 60 UploadFileInfo* info = GetUploadFileInfo(upload_id); | 62 UploadFileInfo* info = GetUploadFileInfo(upload_id); |
| 61 DVLOG(1) << "Uploading file: " << info->DebugString(); | 63 DVLOG(1) << "Uploading file: " << info->DebugString(); |
| 62 | 64 |
| 63 // Create a FileStream to make sure the file can be opened successfully. | 65 // Create a FileStream to make sure the file can be opened successfully. |
| 64 info->file_stream = new net::FileStream(NULL); | 66 info->file_stream = new net::FileStream(NULL); |
| 65 | 67 |
| 66 // Create buffer to hold upload data. | 68 // Create buffer to hold upload data. |
| 67 info->buf_len = std::min(info->file_size, kUploadChunkSize); | 69 info->buf_len = std::min(info->file_size, kUploadChunkSize); |
| 68 info->buf = new net::IOBuffer(info->buf_len); | 70 info->buf = new net::IOBuffer(info->buf_len); |
| 69 | 71 |
| 70 OpenFile(info); | 72 OpenFile(info); |
| 71 return upload_id; | 73 return upload_id; |
| 72 } | 74 } |
| 73 | 75 |
| 74 void GDataUploader::UpdateUpload(int upload_id, | 76 void GDataUploader::UpdateUpload(int upload_id, |
| 75 content::DownloadItem* download) { | 77 content::DownloadItem* download) { |
|
satorux1
2012/06/14 21:32:34
on what thread is this function called? In other p
hshi1
2012/06/14 21:40:17
Done.
satorux1
2012/06/14 21:47:25
Hmm, then seems to me that all functions run on UI
| |
| 78 base::AutoLock lock(lock_); | |
| 79 | |
| 76 UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id); | 80 UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id); |
| 77 if (!upload_file_info) | 81 if (!upload_file_info) |
| 78 return; | 82 return; |
| 79 | 83 |
| 80 const int64 file_size = download->GetReceivedBytes(); | 84 const int64 file_size = download->GetReceivedBytes(); |
| 81 | 85 |
| 82 // Update file_size and all_bytes_present. | 86 // Update file_size and all_bytes_present. |
| 83 DVLOG(1) << "Updating file size from " << upload_file_info->file_size | 87 DVLOG(1) << "Updating file size from " << upload_file_info->file_size |
| 84 << " to " << file_size | 88 << " to " << file_size |
| 85 << (download->AllDataSaved() ? " (AllDataSaved)" : " (In-progress)"); | 89 << (download->AllDataSaved() ? " (AllDataSaved)" : " (In-progress)"); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 127 UploadFileInfo* upload_info = GetUploadFileInfo(upload_id); | 131 UploadFileInfo* upload_info = GetUploadFileInfo(upload_id); |
| 128 // We return the start_range as the count of uploaded bytes since that is the | 132 // We return the start_range as the count of uploaded bytes since that is the |
| 129 // start of the next or currently uploading chunk. | 133 // start of the next or currently uploading chunk. |
| 130 // TODO(asanka): Use a finer grained progress value than this. We end up | 134 // TODO(asanka): Use a finer grained progress value than this. We end up |
| 131 // reporting progress in kUploadChunkSize increments. | 135 // reporting progress in kUploadChunkSize increments. |
| 132 return upload_info ? upload_info->start_range : 0; | 136 return upload_info ? upload_info->start_range : 0; |
| 133 } | 137 } |
| 134 | 138 |
| 135 UploadFileInfo* GDataUploader::GetUploadFileInfo(int upload_id) const { | 139 UploadFileInfo* GDataUploader::GetUploadFileInfo(int upload_id) const { |
| 136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 140 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 141 lock_.AssertAcquired(); | |
| 137 | 142 |
| 138 UploadFileInfoMap::const_iterator it = pending_uploads_.find(upload_id); | 143 UploadFileInfoMap::const_iterator it = pending_uploads_.find(upload_id); |
| 139 DVLOG_IF(1, it == pending_uploads_.end()) << "No upload found for id " | 144 DVLOG_IF(1, it == pending_uploads_.end()) << "No upload found for id " |
| 140 << upload_id; | 145 << upload_id; |
| 141 return it != pending_uploads_.end() ? it->second : NULL; | 146 return it != pending_uploads_.end() ? it->second : NULL; |
| 142 } | 147 } |
| 143 | 148 |
| 144 void GDataUploader::OpenFile(UploadFileInfo* upload_file_info) { | 149 void GDataUploader::OpenFile(UploadFileInfo* upload_file_info) { |
| 145 // Open the file asynchronously. | 150 // Open the file asynchronously. |
| 146 const int rv = upload_file_info->file_stream->Open( | 151 const int rv = upload_file_info->file_stream->Open( |
| 147 upload_file_info->file_path, | 152 upload_file_info->file_path, |
| 148 base::PLATFORM_FILE_OPEN | | 153 base::PLATFORM_FILE_OPEN | |
| 149 base::PLATFORM_FILE_READ | | 154 base::PLATFORM_FILE_READ | |
| 150 base::PLATFORM_FILE_ASYNC, | 155 base::PLATFORM_FILE_ASYNC, |
| 151 base::Bind(&GDataUploader::OpenCompletionCallback, | 156 base::Bind(&GDataUploader::OpenCompletionCallback, |
| 152 uploader_factory_.GetWeakPtr(), | 157 uploader_factory_.GetWeakPtr(), |
| 153 upload_file_info->upload_id)); | 158 upload_file_info->upload_id)); |
| 154 DCHECK_EQ(net::ERR_IO_PENDING, rv); | 159 DCHECK_EQ(net::ERR_IO_PENDING, rv); |
| 155 } | 160 } |
| 156 | 161 |
| 157 void GDataUploader::OpenCompletionCallback(int upload_id, int result) { | 162 void GDataUploader::OpenCompletionCallback(int upload_id, int result) { |
| 158 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 163 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 164 base::AutoLock lock(lock_); | |
| 159 | 165 |
| 160 UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id); | 166 UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id); |
| 161 if (!upload_file_info) | 167 if (!upload_file_info) |
| 162 return; | 168 return; |
| 163 | 169 |
| 164 // The file may actually not exist yet, as the downloads system downloads | 170 // The file may actually not exist yet, as the downloads system downloads |
| 165 // to a temp location and then renames the file. If this is the case, we | 171 // to a temp location and then renames the file. If this is the case, we |
| 166 // just retry opening the file later. | 172 // just retry opening the file later. |
| 167 if (result != net::OK) { | 173 if (result != net::OK) { |
| 168 DCHECK_EQ(result, net::ERR_FILE_NOT_FOUND); | 174 DCHECK_EQ(result, net::ERR_FILE_NOT_FOUND); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 201 base::Bind(&GDataUploader::OnUploadLocationReceived, | 207 base::Bind(&GDataUploader::OnUploadLocationReceived, |
| 202 uploader_factory_.GetWeakPtr(), | 208 uploader_factory_.GetWeakPtr(), |
| 203 upload_file_info->upload_id)); | 209 upload_file_info->upload_id)); |
| 204 } | 210 } |
| 205 | 211 |
| 206 void GDataUploader::OnUploadLocationReceived( | 212 void GDataUploader::OnUploadLocationReceived( |
| 207 int upload_id, | 213 int upload_id, |
| 208 GDataErrorCode code, | 214 GDataErrorCode code, |
| 209 const GURL& upload_location) { | 215 const GURL& upload_location) { |
| 210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 216 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 217 base::AutoLock lock(lock_); | |
| 211 | 218 |
| 212 UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id); | 219 UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id); |
| 213 if (!upload_file_info) | 220 if (!upload_file_info) |
| 214 return; | 221 return; |
| 215 | 222 |
| 216 DVLOG(1) << "Got upload location [" << upload_location.spec() | 223 DVLOG(1) << "Got upload location [" << upload_location.spec() |
| 217 << "] for [" << upload_file_info->title << "]"; | 224 << "] for [" << upload_file_info->title << "]"; |
| 218 | 225 |
| 219 if (code != HTTP_SUCCESS) { | 226 if (code != HTTP_SUCCESS) { |
| 220 // TODO(achuith): Handle error codes from Google Docs server. | 227 // TODO(achuith): Handle error codes from Google Docs server. |
| 221 UploadFailed(upload_file_info, base::PLATFORM_FILE_ERROR_ABORT); | 228 UploadFailed(upload_file_info, base::PLATFORM_FILE_ERROR_ABORT); |
| 222 return; | 229 return; |
| 223 } | 230 } |
| 224 | 231 |
| 225 upload_file_info->upload_location = upload_location; | 232 upload_file_info->upload_location = upload_location; |
| 226 | 233 |
| 227 // Start the upload from the beginning of the file. | 234 // Start the upload from the beginning of the file. |
| 228 UploadNextChunk(upload_file_info); | 235 UploadNextChunk(upload_file_info); |
| 229 } | 236 } |
| 230 | 237 |
| 231 void GDataUploader::UploadNextChunk(UploadFileInfo* upload_file_info) { | 238 void GDataUploader::UploadNextChunk(UploadFileInfo* upload_file_info) { |
| 232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 240 lock_.AssertAcquired(); | |
| 241 | |
| 233 // Check that |upload_file_info| is in pending_uploads_. | 242 // Check that |upload_file_info| is in pending_uploads_. |
| 234 DCHECK(upload_file_info == GetUploadFileInfo(upload_file_info->upload_id)); | 243 DCHECK(upload_file_info == GetUploadFileInfo(upload_file_info->upload_id)); |
| 235 DVLOG(1) << "Number of pending uploads=" << pending_uploads_.size(); | 244 DVLOG(1) << "Number of pending uploads=" << pending_uploads_.size(); |
| 236 | 245 |
| 237 // Determine number of bytes to read for this upload iteration, which cannot | 246 // Determine number of bytes to read for this upload iteration, which cannot |
| 238 // exceed size of buf i.e. buf_len. | 247 // exceed size of buf i.e. buf_len. |
| 239 const int64 bytes_remaining = upload_file_info->SizeRemaining(); | 248 const int64 bytes_remaining = upload_file_info->SizeRemaining(); |
| 240 const int bytes_to_read = std::min(upload_file_info->SizeRemaining(), | 249 const int bytes_to_read = std::min(upload_file_info->SizeRemaining(), |
| 241 upload_file_info->buf_len); | 250 upload_file_info->buf_len); |
| 242 | 251 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 263 bytes_to_read)); | 272 bytes_to_read)); |
| 264 } | 273 } |
| 265 | 274 |
| 266 void GDataUploader::ReadCompletionCallback( | 275 void GDataUploader::ReadCompletionCallback( |
| 267 int upload_id, | 276 int upload_id, |
| 268 int bytes_to_read, | 277 int bytes_to_read, |
| 269 int bytes_read) { | 278 int bytes_read) { |
| 270 // The Read is asynchronously executed on BrowserThread::UI, where | 279 // The Read is asynchronously executed on BrowserThread::UI, where |
| 271 // Read() was called. | 280 // Read() was called. |
| 272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 281 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 282 base::AutoLock lock(lock_); | |
| 283 | |
| 273 DVLOG(1) << "ReadCompletionCallback bytes read=" << bytes_read; | 284 DVLOG(1) << "ReadCompletionCallback bytes read=" << bytes_read; |
| 274 | 285 |
| 275 UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id); | 286 UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id); |
| 276 if (!upload_file_info) | 287 if (!upload_file_info) |
| 277 return; | 288 return; |
| 278 | 289 |
| 279 // TODO(achuith): Handle this error. | 290 // TODO(achuith): Handle this error. |
| 280 DCHECK_EQ(bytes_to_read, bytes_read); | 291 DCHECK_EQ(bytes_to_read, bytes_read); |
| 281 DCHECK_GT(bytes_read, 0) << "Error reading from file " | 292 DCHECK_GT(bytes_read, 0) << "Error reading from file " |
| 282 << upload_file_info->file_path.value(); | 293 << upload_file_info->file_path.value(); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 297 base::Bind(&GDataUploader::OnResumeUploadResponseReceived, | 308 base::Bind(&GDataUploader::OnResumeUploadResponseReceived, |
| 298 uploader_factory_.GetWeakPtr(), | 309 uploader_factory_.GetWeakPtr(), |
| 299 upload_file_info->upload_id)); | 310 upload_file_info->upload_id)); |
| 300 } | 311 } |
| 301 | 312 |
| 302 void GDataUploader::OnResumeUploadResponseReceived( | 313 void GDataUploader::OnResumeUploadResponseReceived( |
| 303 int upload_id, | 314 int upload_id, |
| 304 const ResumeUploadResponse& response, | 315 const ResumeUploadResponse& response, |
| 305 scoped_ptr<DocumentEntry> entry) { | 316 scoped_ptr<DocumentEntry> entry) { |
| 306 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 317 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 318 base::AutoLock lock(lock_); | |
| 307 | 319 |
| 308 UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id); | 320 UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id); |
| 309 if (!upload_file_info) | 321 if (!upload_file_info) |
| 310 return; | 322 return; |
| 311 | 323 |
| 312 if (response.code == HTTP_CREATED) { | 324 if (response.code == HTTP_CREATED) { |
| 313 DVLOG(1) << "Successfully created uploaded file=[" | 325 DVLOG(1) << "Successfully created uploaded file=[" |
| 314 << upload_file_info->title; | 326 << upload_file_info->title; |
| 315 | 327 |
| 316 // Done uploading. | 328 // Done uploading. |
| 317 upload_file_info->entry = entry.Pass(); | 329 upload_file_info->entry = entry.Pass(); |
| 318 if (!upload_file_info->completion_callback.is_null()) { | 330 if (!upload_file_info->completion_callback.is_null()) { |
| 319 upload_file_info->completion_callback.Run(base::PLATFORM_FILE_OK, | 331 upload_file_info->completion_callback.Run(base::PLATFORM_FILE_OK, |
| 320 upload_file_info); | 332 upload_file_info); |
| 321 } | 333 } |
| 322 // TODO(achuith): DeleteUpload() here and let clients call | 334 |
| 323 // GDataFileSystem::AddUploadedFile. | 335 // Remove |upload_file_info| from the UploadFileInfoMap. The UploadFileInfo |
| 336 // object will be deleted later upon transfer completion. | |
| 337 RemoveUpload(upload_file_info); | |
| 324 return; | 338 return; |
| 325 } | 339 } |
| 326 | 340 |
| 327 // If code is 308 (RESUME_INCOMPLETE) and range_received is what has been | 341 // 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 | 342 // previously uploaded (i.e. = upload_file_info->end_range), proceed to |
| 329 // upload the next chunk. | 343 // upload the next chunk. |
| 330 if (response.code != HTTP_RESUME_INCOMPLETE || | 344 if (response.code != HTTP_RESUME_INCOMPLETE || |
| 331 response.start_range_received != 0 || | 345 response.start_range_received != 0 || |
| 332 response.end_range_received != upload_file_info->end_range) { | 346 response.end_range_received != upload_file_info->end_range) { |
| 333 // TODO(achuith): Handle error cases, e.g. | 347 // TODO(achuith): Handle error cases, e.g. |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 347 DVLOG(1) << "Received range " << response.start_range_received | 361 DVLOG(1) << "Received range " << response.start_range_received |
| 348 << "-" << response.end_range_received | 362 << "-" << response.end_range_received |
| 349 << " for [" << upload_file_info->title << "]"; | 363 << " for [" << upload_file_info->title << "]"; |
| 350 | 364 |
| 351 // Continue uploading. | 365 // Continue uploading. |
| 352 UploadNextChunk(upload_file_info); | 366 UploadNextChunk(upload_file_info); |
| 353 } | 367 } |
| 354 | 368 |
| 355 void GDataUploader::MoveFileToCache(UploadFileInfo* upload_file_info) { | 369 void GDataUploader::MoveFileToCache(UploadFileInfo* upload_file_info) { |
| 356 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 370 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 371 lock_.AssertAcquired(); | |
| 372 | |
| 357 if (upload_file_info->entry == NULL) | 373 if (upload_file_info->entry == NULL) |
| 358 return; | 374 return; |
| 359 | 375 |
| 360 DVLOG(1) << "MoveFileToCache " << upload_file_info->file_path.value(); | 376 DVLOG(1) << "MoveFileToCache " << upload_file_info->file_path.value(); |
| 361 file_system_->AddUploadedFile( | 377 file_system_->AddUploadedFile( |
| 362 upload_file_info->gdata_path.DirName(), | 378 upload_file_info->gdata_path.DirName(), |
| 363 upload_file_info->entry.get(), | 379 upload_file_info->entry.get(), |
| 364 upload_file_info->file_path, | 380 upload_file_info->file_path, |
| 365 GDataCache::FILE_OPERATION_MOVE); | 381 GDataCache::FILE_OPERATION_MOVE, |
| 366 DeleteUpload(upload_file_info); | 382 base::Bind(&GDataUploader::OnAddUploadFileComplete, |
| 383 uploader_factory_.GetWeakPtr(), | |
| 384 upload_file_info)); | |
| 385 | |
| 386 // Remove |upload_file_info| from the UploadFileInfoMap. The UploadFileInfo | |
| 387 // object will be deleted in OnAddUploadFileComplete. | |
| 388 RemoveUpload(upload_file_info); | |
| 389 } | |
| 390 | |
| 391 void GDataUploader::OnAddUploadFileComplete(UploadFileInfo* upload_file_info) { | |
| 392 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 393 delete upload_file_info; | |
| 367 } | 394 } |
| 368 | 395 |
| 369 void GDataUploader::UploadFailed(UploadFileInfo* upload_file_info, | 396 void GDataUploader::UploadFailed(UploadFileInfo* upload_file_info, |
| 370 base::PlatformFileError error) { | 397 base::PlatformFileError error) { |
| 371 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 398 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 399 lock_.AssertAcquired(); | |
| 400 | |
| 372 LOG(ERROR) << "Upload failed " << upload_file_info->DebugString(); | 401 LOG(ERROR) << "Upload failed " << upload_file_info->DebugString(); |
| 373 if (!upload_file_info->completion_callback.is_null()) { | 402 if (!upload_file_info->completion_callback.is_null()) { |
| 374 upload_file_info->completion_callback.Run(error, | 403 upload_file_info->completion_callback.Run(error, |
| 375 upload_file_info); | 404 upload_file_info); |
| 376 } | 405 } |
| 377 DeleteUpload(upload_file_info); | |
| 378 } | |
| 379 | 406 |
| 380 void GDataUploader::DeleteUpload(UploadFileInfo* upload_file_info) { | 407 RemoveUpload(upload_file_info); |
| 381 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 382 | |
| 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; | 408 delete upload_file_info; |
| 389 } | 409 } |
| 390 | 410 |
| 411 void GDataUploader::RemoveUpload(UploadFileInfo* upload_file_info) { | |
| 412 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 413 lock_.AssertAcquired(); | |
| 414 | |
| 415 DVLOG(1) << "Removing upload " << upload_file_info->gdata_path.value(); | |
| 416 pending_uploads_.erase(upload_file_info->upload_id); | |
| 417 } | |
| 418 | |
| 391 } // namespace gdata | 419 } // namespace gdata |
| OLD | NEW |