drive: Discard upload location when GetUploadStatus fails

GetUploadStatus for an unusable URL always results in an error.
Upload location should be discarded to initiate new upload in such cases.

BUG=267452
R=kinaba@chromium.org

Review URL: https://codereview.chromium.org/21790002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@215801 0039d316-1c4b-4281-b951-d872f2087c98
parent 4976ac75
...@@ -55,6 +55,7 @@ struct DriveUploader::UploadFileInfo { ...@@ -55,6 +55,7 @@ struct DriveUploader::UploadFileInfo {
completion_callback(callback), completion_callback(callback),
progress_callback(progress_callback), progress_callback(progress_callback),
content_length(0), content_length(0),
next_start_position(-1),
power_save_blocker(content::PowerSaveBlocker::Create( power_save_blocker(content::PowerSaveBlocker::Create(
content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
"Upload in progress")), "Upload in progress")),
...@@ -97,6 +98,8 @@ struct DriveUploader::UploadFileInfo { ...@@ -97,6 +98,8 @@ struct DriveUploader::UploadFileInfo {
// Header content-Length. // Header content-Length.
int64 content_length; int64 content_length;
int64 next_start_position;
// Blocks system suspend while upload is in progress. // Blocks system suspend while upload is in progress.
scoped_ptr<content::PowerSaveBlocker> power_save_blocker; scoped_ptr<content::PowerSaveBlocker> power_save_blocker;
...@@ -295,7 +298,8 @@ void DriveUploader::OnUploadLocationReceived( ...@@ -295,7 +298,8 @@ void DriveUploader::OnUploadLocationReceived(
} }
upload_file_info->upload_location = upload_location; upload_file_info->upload_location = upload_location;
UploadNextChunk(upload_file_info.Pass(), 0); // start_position upload_file_info->next_start_position = 0;
UploadNextChunk(upload_file_info.Pass());
} }
void DriveUploader::StartGetUploadStatus( void DriveUploader::StartGetUploadStatus(
...@@ -313,12 +317,12 @@ void DriveUploader::StartGetUploadStatus( ...@@ -313,12 +317,12 @@ void DriveUploader::StartGetUploadStatus(
} }
void DriveUploader::UploadNextChunk( void DriveUploader::UploadNextChunk(
scoped_ptr<UploadFileInfo> upload_file_info, scoped_ptr<UploadFileInfo> upload_file_info) {
int64 start_position) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(upload_file_info); DCHECK(upload_file_info);
DCHECK_GE(start_position, 0); DCHECK_GE(upload_file_info->next_start_position, 0);
DCHECK_LE(start_position, upload_file_info->content_length); DCHECK_LE(upload_file_info->next_start_position,
upload_file_info->content_length);
if (upload_file_info->cancelled) { if (upload_file_info->cancelled) {
UploadFailed(upload_file_info.Pass(), GDATA_CANCELLED); UploadFailed(upload_file_info.Pass(), GDATA_CANCELLED);
...@@ -326,13 +330,14 @@ void DriveUploader::UploadNextChunk( ...@@ -326,13 +330,14 @@ void DriveUploader::UploadNextChunk(
} }
// Limit the size of data uploaded per each request by kUploadChunkSize. // Limit the size of data uploaded per each request by kUploadChunkSize.
const int64 end_position = std::min(upload_file_info->content_length, const int64 end_position = std::min(
start_position + kUploadChunkSize); upload_file_info->content_length,
upload_file_info->next_start_position + kUploadChunkSize);
UploadFileInfo* info_ptr = upload_file_info.get(); UploadFileInfo* info_ptr = upload_file_info.get();
info_ptr->cancel_callback = drive_service_->ResumeUpload( info_ptr->cancel_callback = drive_service_->ResumeUpload(
info_ptr->upload_location, info_ptr->upload_location,
start_position, info_ptr->next_start_position,
end_position, end_position,
info_ptr->content_length, info_ptr->content_length,
info_ptr->content_type, info_ptr->content_type,
...@@ -343,7 +348,7 @@ void DriveUploader::UploadNextChunk( ...@@ -343,7 +348,7 @@ void DriveUploader::UploadNextChunk(
base::Bind(&DriveUploader::OnUploadProgress, base::Bind(&DriveUploader::OnUploadProgress,
weak_ptr_factory_.GetWeakPtr(), weak_ptr_factory_.GetWeakPtr(),
info_ptr->progress_callback, info_ptr->progress_callback,
start_position, info_ptr->next_start_position,
info_ptr->content_length)); info_ptr->content_length));
} }
...@@ -397,7 +402,8 @@ void DriveUploader::OnUploadRangeResponseReceived( ...@@ -397,7 +402,8 @@ void DriveUploader::OnUploadRangeResponseReceived(
<< "-" << response.end_position_received << "-" << response.end_position_received
<< " for [" << upload_file_info->file_path.value() << "]"; << " for [" << upload_file_info->file_path.value() << "]";
UploadNextChunk(upload_file_info.Pass(), response.end_position_received); upload_file_info->next_start_position = response.end_position_received;
UploadNextChunk(upload_file_info.Pass());
} }
void DriveUploader::OnUploadProgress(const ProgressCallback& callback, void DriveUploader::OnUploadProgress(const ProgressCallback& callback,
...@@ -415,6 +421,12 @@ void DriveUploader::UploadFailed(scoped_ptr<UploadFileInfo> upload_file_info, ...@@ -415,6 +421,12 @@ void DriveUploader::UploadFailed(scoped_ptr<UploadFileInfo> upload_file_info,
LOG(ERROR) << "Upload failed " << upload_file_info->DebugString(); LOG(ERROR) << "Upload failed " << upload_file_info->DebugString();
if (upload_file_info->next_start_position < 0) {
// Discard the upload location because no request could succeed with it.
// Maybe it's obsolete.
upload_file_info->upload_location = GURL();
}
upload_file_info->completion_callback.Run( upload_file_info->completion_callback.Run(
error, upload_file_info->upload_location, scoped_ptr<ResourceEntry>()); error, upload_file_info->upload_location, scoped_ptr<ResourceEntry>());
} }
......
...@@ -172,8 +172,7 @@ class DriveUploader : public DriveUploaderInterface { ...@@ -172,8 +172,7 @@ class DriveUploader : public DriveUploaderInterface {
void StartGetUploadStatus(scoped_ptr<UploadFileInfo> upload_file_info); void StartGetUploadStatus(scoped_ptr<UploadFileInfo> upload_file_info);
// Uploads the next chunk of data from the file. // Uploads the next chunk of data from the file.
void UploadNextChunk(scoped_ptr<UploadFileInfo> upload_file_info, void UploadNextChunk(scoped_ptr<UploadFileInfo> upload_file_info);
int64 start_position);
// DriveService callback for ResumeUpload. // DriveService callback for ResumeUpload.
void OnUploadRangeResponseReceived( void OnUploadRangeResponseReceived(
......
...@@ -286,6 +286,21 @@ class MockDriveServiceNoConnectionAtResume : public DummyDriveService { ...@@ -286,6 +286,21 @@ class MockDriveServiceNoConnectionAtResume : public DummyDriveService {
} }
}; };
// Mock DriveService that returns a failure at GetUploadStatus().
class MockDriveServiceNoConnectionAtGetUploadStatus : public DummyDriveService {
// Returns error.
virtual CancelCallback GetUploadStatus(
const GURL& upload_url,
int64 content_length,
const UploadRangeCallback& callback) OVERRIDE {
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(callback,
UploadRangeResponse(GDATA_NO_CONNECTION, -1, -1),
base::Passed(scoped_ptr<ResourceEntry>())));
return CancelCallback();
}
};
class DriveUploaderTest : public testing::Test { class DriveUploaderTest : public testing::Test {
public: public:
virtual void SetUp() OVERRIDE { virtual void SetUp() OVERRIDE {
...@@ -477,6 +492,31 @@ TEST_F(DriveUploaderTest, ResumeUploadFail) { ...@@ -477,6 +492,31 @@ TEST_F(DriveUploaderTest, ResumeUploadFail) {
EXPECT_EQ(GURL(kTestUploadExistingFileURL), upload_location); EXPECT_EQ(GURL(kTestUploadExistingFileURL), upload_location);
} }
TEST_F(DriveUploaderTest, GetUploadStatusFail) {
base::FilePath local_path;
std::string data;
ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
temp_dir_.path(), 512 * 1024, &local_path, &data));
GDataErrorCode error = HTTP_SUCCESS;
GURL upload_location;
scoped_ptr<ResourceEntry> resource_entry;
MockDriveServiceNoConnectionAtGetUploadStatus mock_service;
DriveUploader uploader(&mock_service,
base::MessageLoopProxy::current().get());
uploader.ResumeUploadFile(GURL(kTestUploadExistingFileURL),
local_path,
kTestMimeType,
test_util::CreateCopyResultCallback(
&error, &upload_location, &resource_entry),
google_apis::ProgressCallback());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(GDATA_NO_CONNECTION, error);
EXPECT_TRUE(upload_location.is_empty());
}
TEST_F(DriveUploaderTest, NonExistingSourceFile) { TEST_F(DriveUploaderTest, NonExistingSourceFile) {
GDataErrorCode error = GDATA_OTHER_ERROR; GDataErrorCode error = GDATA_OTHER_ERROR;
GURL upload_location; GURL upload_location;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment