Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(889)

Side by Side Diff: chrome/browser/chromeos/gdata/gdata_uploader.cc

Issue 9844006: GData downloads cleanup (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: benchan review feedback Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 21 matching lines...) Expand all
32 32
33 GDataUploader::GDataUploader(GDataFileSystem* file_system) 33 GDataUploader::GDataUploader(GDataFileSystem* file_system)
34 : file_system_(file_system), 34 : file_system_(file_system),
35 next_upload_id_(0), 35 next_upload_id_(0),
36 ALLOW_THIS_IN_INITIALIZER_LIST(uploader_factory_(this)) { 36 ALLOW_THIS_IN_INITIALIZER_LIST(uploader_factory_(this)) {
37 } 37 }
38 38
39 GDataUploader::~GDataUploader() { 39 GDataUploader::~GDataUploader() {
40 } 40 }
41 41
42 void GDataUploader::UploadFile(UploadFileInfo* upload_file_info) { 42 int GDataUploader::UploadFile(scoped_ptr<UploadFileInfo> upload_file_info) {
43 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 43 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
44 DCHECK(upload_file_info); 44 DCHECK(upload_file_info.get());
45 DCHECK_EQ(upload_file_info->upload_id, -1); 45 DCHECK_EQ(upload_file_info->upload_id, -1);
46 DCHECK(!upload_file_info->file_path.empty());
47 DCHECK_NE(upload_file_info->file_size, 0);
48 DCHECK(!upload_file_info->gdata_path.empty());
49 DCHECK(!upload_file_info->title.empty());
50 DCHECK(!upload_file_info->content_type.empty());
46 51
47 upload_file_info->upload_id = next_upload_id_++; 52 const int upload_id = next_upload_id_++;
53 upload_file_info->upload_id = upload_id;
48 // Add upload_file_info to our internal map and take ownership. 54 // Add upload_file_info to our internal map and take ownership.
49 pending_uploads_[upload_file_info->upload_id] = upload_file_info; 55 pending_uploads_[upload_id] = upload_file_info.release();
50 DVLOG(1) << "Uploading file: " << upload_file_info->DebugString(); 56
57 UploadFileInfo* info = GetUploadFileInfo(upload_id);
58 DVLOG(1) << "Uploading file: " << info->DebugString();
51 59
52 // Create a FileStream to make sure the file can be opened successfully. 60 // Create a FileStream to make sure the file can be opened successfully.
53 upload_file_info->file_stream = new net::FileStream(NULL); 61 info->file_stream = new net::FileStream(NULL);
54 62
55 // Create buffer to hold upload data. 63 // Create buffer to hold upload data.
56 upload_file_info->buf_len = std::min(upload_file_info->file_size, 64 info->buf_len = std::min(info->file_size, kUploadChunkSize);
57 kUploadChunkSize); 65 info->buf = new net::IOBuffer(info->buf_len);
58 upload_file_info->buf = new net::IOBuffer(upload_file_info->buf_len);
59 66
60 OpenFile(upload_file_info); 67 OpenFile(info);
68 return upload_id;
61 } 69 }
62 70
63 void GDataUploader::UpdateUpload(int upload_id, 71 void GDataUploader::UpdateUpload(int upload_id,
64 content::DownloadItem* download) { 72 content::DownloadItem* download) {
65 UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id); 73 UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id);
66 if (!upload_file_info) 74 if (!upload_file_info)
67 return; 75 return;
68 76
69 const int64 file_size = download->GetReceivedBytes(); 77 const int64 file_size = download->GetReceivedBytes();
70 78
(...skipping 23 matching lines...) Expand all
94 if (upload_file_info->file_path != download->GetFullPath()) 102 if (upload_file_info->file_path != download->GetFullPath())
95 upload_file_info->num_file_open_tries = 0; 103 upload_file_info->num_file_open_tries = 0;
96 upload_file_info->file_path = download->GetFullPath(); 104 upload_file_info->file_path = download->GetFullPath();
97 // Disallow further retries. 105 // Disallow further retries.
98 upload_file_info->should_retry_file_open = false; 106 upload_file_info->should_retry_file_open = false;
99 107
100 OpenFile(upload_file_info); 108 OpenFile(upload_file_info);
101 } 109 }
102 110
103 if (download->IsComplete()) 111 if (download->IsComplete())
104 UploadComplete(upload_file_info); 112 MoveFileToCache(upload_file_info);
105 } 113 }
106 114
107 int64 GDataUploader::GetUploadedBytes(int upload_id) const { 115 int64 GDataUploader::GetUploadedBytes(int upload_id) const {
108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
109 UploadFileInfo* upload_info = GetUploadFileInfo(upload_id); 117 UploadFileInfo* upload_info = GetUploadFileInfo(upload_id);
110 // We return the start_range as the count of uploaded bytes since that is the 118 // We return the start_range as the count of uploaded bytes since that is the
111 // start of the next or currently uploading chunk. 119 // start of the next or currently uploading chunk.
112 // TODO(asanka): Use a finer grained progress value than this. We end up 120 // TODO(asanka): Use a finer grained progress value than this. We end up
113 // reporting progress in kUploadChunkSize increments. 121 // reporting progress in kUploadChunkSize increments.
114 return upload_info ? upload_info->start_range : 0; 122 return upload_info ? upload_info->start_range : 0;
115 } 123 }
116 124
117 UploadFileInfo* GDataUploader::GetUploadFileInfo(int upload_id) const { 125 UploadFileInfo* GDataUploader::GetUploadFileInfo(int upload_id) const {
118 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
119 127
120 UploadFileInfoMap::const_iterator it = pending_uploads_.find(upload_id); 128 UploadFileInfoMap::const_iterator it = pending_uploads_.find(upload_id);
121 DVLOG_IF(1, it == pending_uploads_.end()) << "No upload found for id " 129 DVLOG_IF(1, it == pending_uploads_.end()) << "No upload found for id "
122 << upload_id; 130 << upload_id;
123 return it != pending_uploads_.end() ? it->second : NULL; 131 return it != pending_uploads_.end() ? it->second : NULL;
124 } 132 }
125 133
126 void GDataUploader::RemovePendingUpload(UploadFileInfo* upload_file_info) {
127 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
128
129 pending_uploads_.erase(upload_file_info->upload_id);
130 if (!upload_file_info->completion_callback.is_null()) {
131 upload_file_info->completion_callback.Run(
132 base::PLATFORM_FILE_ERROR_ABORT, NULL);
133 }
134
135 file_system_->CancelOperation(upload_file_info->gdata_path);
136
137 // The file stream is closed by the destructor asynchronously.
138 delete upload_file_info->file_stream;
139 delete upload_file_info;
140 }
141
142 void GDataUploader::OpenFile(UploadFileInfo* upload_file_info) { 134 void GDataUploader::OpenFile(UploadFileInfo* upload_file_info) {
143 // Open the file asynchronously. 135 // Open the file asynchronously.
144 const int rv = upload_file_info->file_stream->Open( 136 const int rv = upload_file_info->file_stream->Open(
145 upload_file_info->file_path, 137 upload_file_info->file_path,
146 base::PLATFORM_FILE_OPEN | 138 base::PLATFORM_FILE_OPEN |
147 base::PLATFORM_FILE_READ | 139 base::PLATFORM_FILE_READ |
148 base::PLATFORM_FILE_ASYNC, 140 base::PLATFORM_FILE_ASYNC,
149 base::Bind(&GDataUploader::OpenCompletionCallback, 141 base::Bind(&GDataUploader::OpenCompletionCallback,
150 uploader_factory_.GetWeakPtr(), 142 uploader_factory_.GetWeakPtr(),
151 upload_file_info->upload_id)); 143 upload_file_info->upload_id));
(...skipping 17 matching lines...) Expand all
169 161
170 DVLOG(1) << "Error opening \"" << upload_file_info->file_path.value() 162 DVLOG(1) << "Error opening \"" << upload_file_info->file_path.value()
171 << "\" for reading: " << net::ErrorToString(result) 163 << "\" for reading: " << net::ErrorToString(result)
172 << ", tries=" << upload_file_info->num_file_open_tries; 164 << ", tries=" << upload_file_info->num_file_open_tries;
173 165
174 // Stop trying to open this file if we exceed kMaxFileOpenTries. 166 // Stop trying to open this file if we exceed kMaxFileOpenTries.
175 const bool exceeded_max_attempts = 167 const bool exceeded_max_attempts =
176 upload_file_info->num_file_open_tries >= kMaxFileOpenTries; 168 upload_file_info->num_file_open_tries >= kMaxFileOpenTries;
177 upload_file_info->should_retry_file_open = !exceeded_max_attempts; 169 upload_file_info->should_retry_file_open = !exceeded_max_attempts;
178 if (exceeded_max_attempts) 170 if (exceeded_max_attempts)
179 RemovePendingUpload(upload_file_info); 171 UploadFailed(upload_file_info);
180 172
181 return; 173 return;
182 } 174 }
183 175
184 // Open succeeded, initiate the upload. 176 // Open succeeded, initiate the upload.
185 upload_file_info->should_retry_file_open = false; 177 upload_file_info->should_retry_file_open = false;
186 file_system_->InitiateUpload( 178 file_system_->InitiateUpload(
187 upload_file_info->title, 179 upload_file_info->title,
188 upload_file_info->content_type, 180 upload_file_info->content_type,
189 upload_file_info->content_length, 181 upload_file_info->content_length,
(...skipping 12 matching lines...) Expand all
202 194
203 UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id); 195 UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id);
204 if (!upload_file_info) 196 if (!upload_file_info)
205 return; 197 return;
206 198
207 DVLOG(1) << "Got upload location [" << upload_location.spec() 199 DVLOG(1) << "Got upload location [" << upload_location.spec()
208 << "] for [" << upload_file_info->title << "]"; 200 << "] for [" << upload_file_info->title << "]";
209 201
210 if (code != HTTP_SUCCESS) { 202 if (code != HTTP_SUCCESS) {
211 // TODO(achuith): Handle error codes from Google Docs server. 203 // TODO(achuith): Handle error codes from Google Docs server.
212 RemovePendingUpload(upload_file_info); 204 UploadFailed(upload_file_info);
213 NOTREACHED();
214 return; 205 return;
215 } 206 }
216 207
217 upload_file_info->upload_location = upload_location; 208 upload_file_info->upload_location = upload_location;
218 209
219 // Start the upload from the beginning of the file. 210 // Start the upload from the beginning of the file.
220 UploadNextChunk(upload_file_info); 211 UploadNextChunk(upload_file_info);
221 } 212 }
222 213
223 void GDataUploader::UploadNextChunk(UploadFileInfo* upload_file_info) { 214 void GDataUploader::UploadNextChunk(UploadFileInfo* upload_file_info) {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 if (!upload_file_info) 292 if (!upload_file_info)
302 return; 293 return;
303 294
304 if (response.code == HTTP_CREATED) { 295 if (response.code == HTTP_CREATED) {
305 DVLOG(1) << "Successfully created uploaded file=[" 296 DVLOG(1) << "Successfully created uploaded file=["
306 << upload_file_info->title; 297 << upload_file_info->title;
307 298
308 // Done uploading. 299 // Done uploading.
309 upload_file_info->entry = entry.Pass(); 300 upload_file_info->entry = entry.Pass();
310 if (!upload_file_info->completion_callback.is_null()) { 301 if (!upload_file_info->completion_callback.is_null()) {
311 upload_file_info->completion_callback.Run( 302 upload_file_info->completion_callback.Run(base::PLATFORM_FILE_OK,
312 base::PLATFORM_FILE_OK, 303 upload_file_info);
asanka 2012/03/28 22:02:33 Minor Nit: Perhaps have a way to assert that we on
achuithb 2012/03/28 23:27:11 I've put the Reset back in.
313 upload_file_info->entry.get());
314 upload_file_info->completion_callback.Reset();
315 } 304 }
305 // TODO(achuith): DeleteUpload() here and let clients call
306 // GDataFileSystem::AddUploadedFile.
316 return; 307 return;
317 } 308 }
318 309
319 // If code is 308 (RESUME_INCOMPLETE) and range_received is what has been 310 // If code is 308 (RESUME_INCOMPLETE) and range_received is what has been
320 // previously uploaded (i.e. = upload_file_info->end_range), proceed to 311 // previously uploaded (i.e. = upload_file_info->end_range), proceed to
321 // upload the next chunk. 312 // upload the next chunk.
322 if (response.code != HTTP_RESUME_INCOMPLETE || 313 if (response.code != HTTP_RESUME_INCOMPLETE ||
323 response.start_range_received != 0 || 314 response.start_range_received != 0 ||
324 response.end_range_received != upload_file_info->end_range) { 315 response.end_range_received != upload_file_info->end_range) {
325 // TODO(achuith): Handle error cases, e.g. 316 // TODO(achuith): Handle error cases, e.g.
326 // - when previously uploaded data wasn't received by Google Docs server, 317 // - when previously uploaded data wasn't received by Google Docs server,
327 // i.e. when end_range_received < upload_file_info->end_range 318 // i.e. when end_range_received < upload_file_info->end_range
328 // - when quota is exceeded, which is 1GB for files not converted to Google 319 // - when quota is exceeded, which is 1GB for files not converted to Google
329 // Docs format; even though the quota-exceeded content length 320 // Docs format; even though the quota-exceeded content length
330 // is specified in the header when posting request to get upload 321 // is specified in the header when posting request to get upload
331 // location, the server allows us to upload all chunks of entire file 322 // location, the server allows us to upload all chunks of entire file
332 // successfully, but instead of returning 201 (CREATED) status code after 323 // successfully, but instead of returning 201 (CREATED) status code after
333 // receiving the last chunk, it returns 403 (FORBIDDEN); response content 324 // receiving the last chunk, it returns 403 (FORBIDDEN); response content
334 // then will indicate quote exceeded exception. 325 // then will indicate quote exceeded exception.
335 NOTREACHED() << "UploadNextChunk http code=" << response.code 326 NOTREACHED() << "UploadNextChunk http code=" << response.code
336 << ", start_range_received=" << response.start_range_received 327 << ", start_range_received=" << response.start_range_received
337 << ", end_range_received=" << response.end_range_received 328 << ", end_range_received=" << response.end_range_received
338 << ", expected end range=" << upload_file_info->end_range; 329 << ", expected end range=" << upload_file_info->end_range;
339 330
340 RemovePendingUpload(upload_file_info); 331 UploadFailed(upload_file_info);
341 return; 332 return;
342 } 333 }
343 334
344 DVLOG(1) << "Received range " << response.start_range_received 335 DVLOG(1) << "Received range " << response.start_range_received
345 << "-" << response.end_range_received 336 << "-" << response.end_range_received
346 << " for [" << upload_file_info->title << "]"; 337 << " for [" << upload_file_info->title << "]";
347 338
348 // Continue uploading. 339 // Continue uploading.
349 UploadNextChunk(upload_file_info); 340 UploadNextChunk(upload_file_info);
350 } 341 }
351 342
352 void GDataUploader::UploadComplete(UploadFileInfo* upload_file_info) { 343 void GDataUploader::MoveFileToCache(UploadFileInfo* upload_file_info) {
353 DVLOG(1) << "UploadComplete " << upload_file_info->file_path.value(); 344 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
354 file_system_->AddUploadedFile(upload_file_info->gdata_path.DirName(), 345 if (upload_file_info->entry == NULL)
355 upload_file_info->entry.get(), 346 return;
356 upload_file_info->file_path, 347
357 GDataFileSystemInterface::FILE_OPERATION_MOVE); 348 DVLOG(1) << "MoveFileToCache " << upload_file_info->file_path.value();
358 RemovePendingUpload(upload_file_info); 349 file_system_->AddUploadedFile(
350 upload_file_info->gdata_path.DirName(),
351 upload_file_info->entry.get(),
352 upload_file_info->file_path,
353 GDataFileSystemInterface::FILE_OPERATION_MOVE);
354 DeleteUpload(upload_file_info);
355 }
356
357 void GDataUploader::UploadFailed(UploadFileInfo* upload_file_info) {
358 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
359 LOG(ERROR) << "Upload failed " << upload_file_info->DebugString();
360 if (!upload_file_info->completion_callback.is_null()) {
361 upload_file_info->completion_callback.Run(base::PLATFORM_FILE_ERROR_ABORT,
362 upload_file_info);
363 }
364 file_system_->CancelOperation(upload_file_info->gdata_path);
365 DeleteUpload(upload_file_info);
366 }
367
368 void GDataUploader::DeleteUpload(UploadFileInfo* upload_file_info) {
369 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
370
371 DVLOG(1) << "Deleting upload " << upload_file_info->gdata_path.value();
372 pending_uploads_.erase(upload_file_info->upload_id);
373
374 // The file stream is closed by the destructor asynchronously.
375 delete upload_file_info->file_stream;
376 delete upload_file_info;
359 } 377 }
360 378
361 } // namespace gdata 379 } // namespace gdata
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698