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

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: asanka 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
« no previous file with comments | « chrome/browser/chromeos/gdata/gdata_uploader.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 30 matching lines...) Expand all
101 // rename on the FILE thread. Thus the new path is visible on the UI thread 109 // rename on the FILE thread. Thus the new path is visible on the UI thread
102 // before the renamed file is available on the file system. 110 // before the renamed file is available on the file system.
103 if (upload_file_info->should_retry_file_open) { 111 if (upload_file_info->should_retry_file_open) {
104 DCHECK(!download->IsComplete()); 112 DCHECK(!download->IsComplete());
105 // Disallow further retries. 113 // Disallow further retries.
106 upload_file_info->should_retry_file_open = false; 114 upload_file_info->should_retry_file_open = false;
107 OpenFile(upload_file_info); 115 OpenFile(upload_file_info);
108 } 116 }
109 117
110 if (download->IsComplete()) 118 if (download->IsComplete())
111 UploadComplete(upload_file_info); 119 MoveFileToCache(upload_file_info);
112 } 120 }
113 121
114 int64 GDataUploader::GetUploadedBytes(int upload_id) const { 122 int64 GDataUploader::GetUploadedBytes(int upload_id) const {
115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 123 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
116 UploadFileInfo* upload_info = GetUploadFileInfo(upload_id); 124 UploadFileInfo* upload_info = GetUploadFileInfo(upload_id);
117 // We return the start_range as the count of uploaded bytes since that is the 125 // We return the start_range as the count of uploaded bytes since that is the
118 // start of the next or currently uploading chunk. 126 // start of the next or currently uploading chunk.
119 // TODO(asanka): Use a finer grained progress value than this. We end up 127 // TODO(asanka): Use a finer grained progress value than this. We end up
120 // reporting progress in kUploadChunkSize increments. 128 // reporting progress in kUploadChunkSize increments.
121 return upload_info ? upload_info->start_range : 0; 129 return upload_info ? upload_info->start_range : 0;
122 } 130 }
123 131
124 UploadFileInfo* GDataUploader::GetUploadFileInfo(int upload_id) const { 132 UploadFileInfo* GDataUploader::GetUploadFileInfo(int upload_id) const {
125 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 133 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
126 134
127 UploadFileInfoMap::const_iterator it = pending_uploads_.find(upload_id); 135 UploadFileInfoMap::const_iterator it = pending_uploads_.find(upload_id);
128 DVLOG_IF(1, it == pending_uploads_.end()) << "No upload found for id " 136 DVLOG_IF(1, it == pending_uploads_.end()) << "No upload found for id "
129 << upload_id; 137 << upload_id;
130 return it != pending_uploads_.end() ? it->second : NULL; 138 return it != pending_uploads_.end() ? it->second : NULL;
131 } 139 }
132 140
133 void GDataUploader::RemovePendingUpload(UploadFileInfo* upload_file_info) {
134 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
135
136 pending_uploads_.erase(upload_file_info->upload_id);
137 if (!upload_file_info->completion_callback.is_null()) {
138 upload_file_info->completion_callback.Run(
139 base::PLATFORM_FILE_ERROR_ABORT, NULL);
140 }
141
142 file_system_->CancelOperation(upload_file_info->gdata_path);
143
144 // The file stream is closed by the destructor asynchronously.
145 delete upload_file_info->file_stream;
146 delete upload_file_info;
147 }
148
149 void GDataUploader::OpenFile(UploadFileInfo* upload_file_info) { 141 void GDataUploader::OpenFile(UploadFileInfo* upload_file_info) {
150 // Open the file asynchronously. 142 // Open the file asynchronously.
151 const int rv = upload_file_info->file_stream->Open( 143 const int rv = upload_file_info->file_stream->Open(
152 upload_file_info->file_path, 144 upload_file_info->file_path,
153 base::PLATFORM_FILE_OPEN | 145 base::PLATFORM_FILE_OPEN |
154 base::PLATFORM_FILE_READ | 146 base::PLATFORM_FILE_READ |
155 base::PLATFORM_FILE_ASYNC, 147 base::PLATFORM_FILE_ASYNC,
156 base::Bind(&GDataUploader::OpenCompletionCallback, 148 base::Bind(&GDataUploader::OpenCompletionCallback,
157 uploader_factory_.GetWeakPtr(), 149 uploader_factory_.GetWeakPtr(),
158 upload_file_info->upload_id)); 150 upload_file_info->upload_id));
(...skipping 17 matching lines...) Expand all
176 168
177 DVLOG(1) << "Error opening \"" << upload_file_info->file_path.value() 169 DVLOG(1) << "Error opening \"" << upload_file_info->file_path.value()
178 << "\" for reading: " << net::ErrorToString(result) 170 << "\" for reading: " << net::ErrorToString(result)
179 << ", tries=" << upload_file_info->num_file_open_tries; 171 << ", tries=" << upload_file_info->num_file_open_tries;
180 172
181 // Stop trying to open this file if we exceed kMaxFileOpenTries. 173 // Stop trying to open this file if we exceed kMaxFileOpenTries.
182 const bool exceeded_max_attempts = 174 const bool exceeded_max_attempts =
183 upload_file_info->num_file_open_tries >= kMaxFileOpenTries; 175 upload_file_info->num_file_open_tries >= kMaxFileOpenTries;
184 upload_file_info->should_retry_file_open = !exceeded_max_attempts; 176 upload_file_info->should_retry_file_open = !exceeded_max_attempts;
185 if (exceeded_max_attempts) 177 if (exceeded_max_attempts)
186 RemovePendingUpload(upload_file_info); 178 UploadFailed(upload_file_info);
187 179
188 return; 180 return;
189 } 181 }
190 182
191 // Open succeeded, initiate the upload. 183 // Open succeeded, initiate the upload.
192 upload_file_info->should_retry_file_open = false; 184 upload_file_info->should_retry_file_open = false;
193 file_system_->InitiateUpload( 185 file_system_->InitiateUpload(
194 upload_file_info->title, 186 upload_file_info->title,
195 upload_file_info->content_type, 187 upload_file_info->content_type,
196 upload_file_info->content_length, 188 upload_file_info->content_length,
(...skipping 12 matching lines...) Expand all
209 201
210 UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id); 202 UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id);
211 if (!upload_file_info) 203 if (!upload_file_info)
212 return; 204 return;
213 205
214 DVLOG(1) << "Got upload location [" << upload_location.spec() 206 DVLOG(1) << "Got upload location [" << upload_location.spec()
215 << "] for [" << upload_file_info->title << "]"; 207 << "] for [" << upload_file_info->title << "]";
216 208
217 if (code != HTTP_SUCCESS) { 209 if (code != HTTP_SUCCESS) {
218 // TODO(achuith): Handle error codes from Google Docs server. 210 // TODO(achuith): Handle error codes from Google Docs server.
219 RemovePendingUpload(upload_file_info); 211 UploadFailed(upload_file_info);
220 NOTREACHED();
221 return; 212 return;
222 } 213 }
223 214
224 upload_file_info->upload_location = upload_location; 215 upload_file_info->upload_location = upload_location;
225 216
226 // Start the upload from the beginning of the file. 217 // Start the upload from the beginning of the file.
227 UploadNextChunk(upload_file_info); 218 UploadNextChunk(upload_file_info);
228 } 219 }
229 220
230 void GDataUploader::UploadNextChunk(UploadFileInfo* upload_file_info) { 221 void GDataUploader::UploadNextChunk(UploadFileInfo* upload_file_info) {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 if (!upload_file_info) 299 if (!upload_file_info)
309 return; 300 return;
310 301
311 if (response.code == HTTP_CREATED) { 302 if (response.code == HTTP_CREATED) {
312 DVLOG(1) << "Successfully created uploaded file=[" 303 DVLOG(1) << "Successfully created uploaded file=["
313 << upload_file_info->title; 304 << upload_file_info->title;
314 305
315 // Done uploading. 306 // Done uploading.
316 upload_file_info->entry = entry.Pass(); 307 upload_file_info->entry = entry.Pass();
317 if (!upload_file_info->completion_callback.is_null()) { 308 if (!upload_file_info->completion_callback.is_null()) {
318 upload_file_info->completion_callback.Run( 309 upload_file_info->completion_callback.Run(base::PLATFORM_FILE_OK,
319 base::PLATFORM_FILE_OK, 310 upload_file_info);
320 upload_file_info->entry.get());
321 upload_file_info->completion_callback.Reset(); 311 upload_file_info->completion_callback.Reset();
322 } 312 }
313 // TODO(achuith): DeleteUpload() here and let clients call
314 // GDataFileSystem::AddUploadedFile.
323 return; 315 return;
324 } 316 }
325 317
326 // If code is 308 (RESUME_INCOMPLETE) and range_received is what has been 318 // If code is 308 (RESUME_INCOMPLETE) and range_received is what has been
327 // previously uploaded (i.e. = upload_file_info->end_range), proceed to 319 // previously uploaded (i.e. = upload_file_info->end_range), proceed to
328 // upload the next chunk. 320 // upload the next chunk.
329 if (response.code != HTTP_RESUME_INCOMPLETE || 321 if (response.code != HTTP_RESUME_INCOMPLETE ||
330 response.start_range_received != 0 || 322 response.start_range_received != 0 ||
331 response.end_range_received != upload_file_info->end_range) { 323 response.end_range_received != upload_file_info->end_range) {
332 // TODO(achuith): Handle error cases, e.g. 324 // TODO(achuith): Handle error cases, e.g.
333 // - when previously uploaded data wasn't received by Google Docs server, 325 // - when previously uploaded data wasn't received by Google Docs server,
334 // i.e. when end_range_received < upload_file_info->end_range 326 // i.e. when end_range_received < upload_file_info->end_range
335 // - when quota is exceeded, which is 1GB for files not converted to Google 327 // - when quota is exceeded, which is 1GB for files not converted to Google
336 // Docs format; even though the quota-exceeded content length 328 // Docs format; even though the quota-exceeded content length
337 // is specified in the header when posting request to get upload 329 // is specified in the header when posting request to get upload
338 // location, the server allows us to upload all chunks of entire file 330 // location, the server allows us to upload all chunks of entire file
339 // successfully, but instead of returning 201 (CREATED) status code after 331 // successfully, but instead of returning 201 (CREATED) status code after
340 // receiving the last chunk, it returns 403 (FORBIDDEN); response content 332 // receiving the last chunk, it returns 403 (FORBIDDEN); response content
341 // then will indicate quote exceeded exception. 333 // then will indicate quote exceeded exception.
342 NOTREACHED() << "UploadNextChunk http code=" << response.code 334 NOTREACHED() << "UploadNextChunk http code=" << response.code
343 << ", start_range_received=" << response.start_range_received 335 << ", start_range_received=" << response.start_range_received
344 << ", end_range_received=" << response.end_range_received 336 << ", end_range_received=" << response.end_range_received
345 << ", expected end range=" << upload_file_info->end_range; 337 << ", expected end range=" << upload_file_info->end_range;
346 338
347 RemovePendingUpload(upload_file_info); 339 UploadFailed(upload_file_info);
348 return; 340 return;
349 } 341 }
350 342
351 DVLOG(1) << "Received range " << response.start_range_received 343 DVLOG(1) << "Received range " << response.start_range_received
352 << "-" << response.end_range_received 344 << "-" << response.end_range_received
353 << " for [" << upload_file_info->title << "]"; 345 << " for [" << upload_file_info->title << "]";
354 346
355 // Continue uploading. 347 // Continue uploading.
356 UploadNextChunk(upload_file_info); 348 UploadNextChunk(upload_file_info);
357 } 349 }
358 350
359 void GDataUploader::UploadComplete(UploadFileInfo* upload_file_info) { 351 void GDataUploader::MoveFileToCache(UploadFileInfo* upload_file_info) {
360 DVLOG(1) << "UploadComplete " << upload_file_info->file_path.value(); 352 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
361 file_system_->AddUploadedFile(upload_file_info->gdata_path.DirName(), 353 if (upload_file_info->entry == NULL)
362 upload_file_info->entry.get(), 354 return;
363 upload_file_info->file_path, 355
364 GDataFileSystemInterface::FILE_OPERATION_MOVE); 356 DVLOG(1) << "MoveFileToCache " << upload_file_info->file_path.value();
365 RemovePendingUpload(upload_file_info); 357 file_system_->AddUploadedFile(
358 upload_file_info->gdata_path.DirName(),
359 upload_file_info->entry.get(),
360 upload_file_info->file_path,
361 GDataFileSystemInterface::FILE_OPERATION_MOVE);
362 DeleteUpload(upload_file_info);
363 }
364
365 void GDataUploader::UploadFailed(UploadFileInfo* upload_file_info) {
366 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
367 LOG(ERROR) << "Upload failed " << upload_file_info->DebugString();
368 if (!upload_file_info->completion_callback.is_null()) {
369 upload_file_info->completion_callback.Run(base::PLATFORM_FILE_ERROR_ABORT,
370 upload_file_info);
371 }
372 file_system_->CancelOperation(upload_file_info->gdata_path);
373 DeleteUpload(upload_file_info);
374 }
375
376 void GDataUploader::DeleteUpload(UploadFileInfo* upload_file_info) {
377 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
378
379 DVLOG(1) << "Deleting upload " << upload_file_info->gdata_path.value();
380 pending_uploads_.erase(upload_file_info->upload_id);
381
382 // The file stream is closed by the destructor asynchronously.
383 delete upload_file_info->file_stream;
384 delete upload_file_info;
366 } 385 }
367 386
368 } // namespace gdata 387 } // namespace gdata
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/gdata/gdata_uploader.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698