summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkinaba@chromium.org <kinaba@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-18 02:32:20 +0000
committerkinaba@chromium.org <kinaba@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-18 02:32:20 +0000
commit736f781feb0118e15842ffc1768e9f894c035c6e (patch)
tree0e476a225fd1f70824181941d27275332051e40b
parent43dcd3546ef707f3552bfbf0666381571a46bbc8 (diff)
downloadchromium_src-736f781feb0118e15842ffc1768e9f894c035c6e.zip
chromium_src-736f781feb0118e15842ffc1768e9f894c035c6e.tar.gz
chromium_src-736f781feb0118e15842ffc1768e9f894c035c6e.tar.bz2
Remove upload_id and everything else unused in DriveUploader.
* Remove |upload_id|, |next_upload_id_|, |pending_uploads_|, and |RemoveUpload()|. The integer ID was used to indirectly expose UploadFileInfo to DriveDownloadObserver, but we don't need it now. * Remove unimplemented declaration of |InitiateUpload()|. * Remove unused |FileOpenType| enum. * Remove |UploadFileInfo::buf_len|. It is always 512KB. * Remove |UploadFileInfo::entry|. It is almost unused. * Remove |UploadFileInfo::start_position|. It is almost unused. * Moved UploadFileInfo to .cc and added bunch of const's. * Potential Fix: Change ReadSync to ReadUntilComplete, otherwise we can satisfy the WAPI requirement. BUG=165110 TBR=tzik@chromium.org Review URL: https://codereview.chromium.org/11592007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@173628 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chromeos/drive/drive_file_system_unittest.cc14
-rw-r--r--chrome/browser/google_apis/drive_uploader.cc461
-rw-r--r--chrome/browser/google_apis/drive_uploader.h157
-rw-r--r--chrome/browser/sync_file_system/drive_file_sync_client_unittest.cc6
4 files changed, 249 insertions, 389 deletions
diff --git a/chrome/browser/chromeos/drive/drive_file_system_unittest.cc b/chrome/browser/chromeos/drive/drive_file_system_unittest.cc
index 0b73433..ae7c012 100644
--- a/chrome/browser/chromeos/drive/drive_file_system_unittest.cc
+++ b/chrome/browser/chromeos/drive/drive_file_system_unittest.cc
@@ -124,7 +124,7 @@ class FakeDriveUploader : public google_apis::DriveUploaderInterface {
// Pretends that a new file was uploaded successfully, and returns the
// contents of "gdata/uploaded_file.json" to the caller.
- virtual int UploadNewFile(
+ virtual void UploadNewFile(
const GURL& upload_location,
const FilePath& drive_file_path,
const FilePath& local_file_path,
@@ -145,15 +145,12 @@ class FakeDriveUploader : public google_apis::DriveUploaderInterface {
drive_file_path,
local_file_path,
base::Passed(&resource_entry)));
-
- const int kUploadId = 123;
- return kUploadId;
}
// Pretends that an existing file ("drive/File 1.txt") was uploaded
// successfully, and returns an entry for the file in
// "gdata/root_feed.json" to the caller.
- virtual int UploadExistingFile(
+ virtual void UploadExistingFile(
const GURL& upload_location,
const FilePath& drive_file_path,
const FilePath& local_file_path,
@@ -173,7 +170,7 @@ class FakeDriveUploader : public google_apis::DriveUploaderInterface {
scoped_ptr<base::Value> value =
google_apis::test_util::LoadJSONFile("gdata/root_feed.json");
if (!value.get())
- return -1;
+ return;
base::DictionaryValue* as_dict = NULL;
base::ListValue* entry_list = NULL;
@@ -190,7 +187,7 @@ class FakeDriveUploader : public google_apis::DriveUploaderInterface {
}
}
if (!resource_entry)
- return -1;
+ return;
base::MessageLoopProxy::current()->PostTask(
FROM_HERE,
@@ -199,9 +196,6 @@ class FakeDriveUploader : public google_apis::DriveUploaderInterface {
drive_file_path,
local_file_path,
base::Passed(&resource_entry)));
-
- const int kUploadId = 123;
- return kUploadId;
}
};
diff --git a/chrome/browser/google_apis/drive_uploader.cc b/chrome/browser/google_apis/drive_uploader.cc
index 830b9a42..143cb12 100644
--- a/chrome/browser/google_apis/drive_uploader.cc
+++ b/chrome/browser/google_apis/drive_uploader.cc
@@ -8,8 +8,10 @@
#include "base/bind.h"
#include "base/callback.h"
+#include "base/message_loop.h"
#include "base/string_number_conversions.h"
#include "chrome/browser/google_apis/drive_service_interface.h"
+#include "chrome/browser/google_apis/drive_upload_mode.h"
#include "chrome/browser/google_apis/gdata_wapi_parser.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/file_stream.h"
@@ -22,13 +24,6 @@ namespace {
// Google Documents List API requires uploading in chunks of 512kB.
const int64 kUploadChunkSize = 512 * 1024;
-// Reads |bytes_to_read| bytes from |file_stream| to |buf|.
-int ReadFileStreamOnBlockingPool(net::FileStream* file_stream,
- scoped_refptr<net::IOBuffer> buf,
- int bytes_to_read) {
- return file_stream->ReadSync(buf->data(), bytes_to_read);
-}
-
// Opens |path| with |file_stream| and returns the file size.
// If failed, returns an error code in a negative value.
int64 OpenFileStreamAndGetSizeOnBlockingPool(net::FileStream* file_stream,
@@ -44,79 +39,135 @@ int64 OpenFileStreamAndGetSizeOnBlockingPool(net::FileStream* file_stream,
namespace google_apis {
-DriveUploader::DriveUploader(DriveServiceInterface* drive_service)
- : drive_service_(drive_service),
- next_upload_id_(0),
- ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
- base::SequencedWorkerPool* blocking_pool = BrowserThread::GetBlockingPool();
- blocking_task_runner_ = blocking_pool->GetSequencedTaskRunner(
- blocking_pool->GetSequenceToken());
-}
+// Structure containing current upload information of file, passed between
+// DriveServiceInterface methods and callbacks.
+struct DriveUploader::UploadFileInfo {
+ UploadFileInfo(scoped_refptr<base::SequencedTaskRunner> task_runner,
+ UploadMode upload_mode,
+ const GURL& initial_upload_location,
+ const FilePath& drive_path,
+ const FilePath& local_path,
+ const std::string& title,
+ const std::string& content_type,
+ const UploadCompletionCallback& callback)
+ : upload_mode(upload_mode),
+ initial_upload_location(initial_upload_location),
+ drive_path(drive_path),
+ file_path(local_path),
+ title(title),
+ content_type(content_type),
+ completion_callback(callback),
+ content_length(0),
+ next_send_position(0),
+ file_stream(new net::FileStream(NULL)),
+ buf(new net::IOBuffer(kUploadChunkSize)),
+ blocking_task_runner(task_runner) {
+ }
-DriveUploader::~DriveUploader() {
- for (UploadFileInfoMap::iterator iter = pending_uploads_.begin();
- iter != pending_uploads_.end();
- ++iter) {
- // FileStream must be closed on a file-access-allowed thread.
- blocking_task_runner_->DeleteSoon(
- FROM_HERE, iter->second->file_stream.release());
- delete iter->second;
+ ~UploadFileInfo() {
+ blocking_task_runner->DeleteSoon(FROM_HERE, file_stream.release());
}
-}
-int DriveUploader::UploadNewFile(const GURL& upload_location,
- const FilePath& drive_file_path,
- const FilePath& local_file_path,
- const std::string& title,
- const std::string& content_type,
- const UploadCompletionCallback& callback) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(!upload_location.is_empty());
- DCHECK(!drive_file_path.empty());
- DCHECK(!local_file_path.empty());
- DCHECK(!title.empty());
- DCHECK(!content_type.empty());
- DCHECK(!callback.is_null());
-
- scoped_ptr<UploadFileInfo> upload_file_info(new UploadFileInfo);
- upload_file_info->upload_mode = UPLOAD_NEW_FILE;
- upload_file_info->initial_upload_location = upload_location;
- upload_file_info->drive_path = drive_file_path;
- upload_file_info->file_path = local_file_path;
- upload_file_info->title = title;
- upload_file_info->content_type = content_type;
- upload_file_info->completion_callback = callback;
- return StartUploadFile(upload_file_info.Pass());
-}
+ // Bytes left to upload.
+ int64 SizeRemaining() const {
+ DCHECK(content_length >= next_send_position);
+ return content_length - next_send_position;
+ }
-int DriveUploader::StartUploadFile(
- scoped_ptr<UploadFileInfo> upload_file_info) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(upload_file_info.get());
- DCHECK_EQ(upload_file_info->upload_id, -1);
- DCHECK_NE(UPLOAD_INVALID, upload_file_info->upload_mode);
+ // Useful for printf debugging.
+ std::string DebugString() const {
+ return "title=[" + title +
+ "], file_path=[" + file_path.AsUTF8Unsafe() +
+ "], content_type=[" + content_type +
+ "], content_length=[" + base::UintToString(content_length) +
+ "], drive_path=[" + drive_path.AsUTF8Unsafe() +
+ "]";
+ }
+
+ // Whether this is uploading a new file or updating an existing file.
+ const UploadMode upload_mode;
+
+ // Location URL used to get |upload_location| with InitiateUpload.
+ const GURL initial_upload_location;
+
+ // Final path in gdata. Looks like /special/drive/MyFolder/MyFile.
+ const FilePath drive_path;
- const int upload_id = next_upload_id_++;
- upload_file_info->upload_id = upload_id;
+ // The local file path of the file to be uploaded.
+ const FilePath file_path;
- // Add upload_file_info to our internal map and take ownership.
- pending_uploads_[upload_id] = upload_file_info.release();
- UploadFileInfo* info = GetUploadFileInfo(upload_id);
- DVLOG(1) << "Uploading file: " << info->DebugString();
+ // Title to be used for file to be uploaded.
+ const std::string title;
- // Create a FileStream to make sure the file can be opened successfully.
- info->file_stream.reset(new net::FileStream(NULL));
+ // Content-Type of file.
+ const std::string content_type;
- // Create buffer to hold upload data. The full file size may not be known at
- // this point, so it may not be appropriate to use info->file_size.
- info->buf_len = kUploadChunkSize;
- info->buf = new net::IOBuffer(info->buf_len);
+ // Callback to be invoked once the upload has finished.
+ const UploadCompletionCallback completion_callback;
+
+ // Location URL where file is to be uploaded to, returned from
+ // InitiateUpload. Used for the subsequent ResumeUpload requests.
+ GURL upload_location;
+
+ // Header content-Length.
+ int64 content_length;
+
+ // The start position of the contents to be sent as the next upload chunk.
+ int64 next_send_position;
+
+ // For opening and reading from physical file.
+ //
+ // File operations are posted to |blocking_task_runner|, while the ownership
+ // of the stream is held in UI thread. At the point when this UploadFileInfo
+ // is destroyed, the ownership of the stream is passed to the worker pool.
+ // TODO(kinaba): We should switch to async API of FileStream once
+ // crbug.com/164312 is fixed.
+ scoped_ptr<net::FileStream> file_stream;
+
+ // Holds current content to be uploaded.
+ const scoped_refptr<net::IOBuffer> buf;
+
+ // Runner for net::FileStream tasks.
+ const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner;
+};
+
+DriveUploader::DriveUploader(DriveServiceInterface* drive_service)
+ : drive_service_(drive_service),
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
+ base::SequencedWorkerPool* blocking_pool = BrowserThread::GetBlockingPool();
+ blocking_task_runner_ = blocking_pool->GetSequencedTaskRunner(
+ blocking_pool->GetSequenceToken());
+}
+
+DriveUploader::~DriveUploader() {}
+
+void DriveUploader::UploadNewFile(const GURL& upload_location,
+ const FilePath& drive_file_path,
+ const FilePath& local_file_path,
+ const std::string& title,
+ const std::string& content_type,
+ const UploadCompletionCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!upload_location.is_empty());
+ DCHECK(!drive_file_path.empty());
+ DCHECK(!local_file_path.empty());
+ DCHECK(!title.empty());
+ DCHECK(!content_type.empty());
+ DCHECK(!callback.is_null());
- OpenFile(info, FILE_OPEN_START_UPLOAD);
- return upload_id;
+ StartUploadFile(scoped_ptr<UploadFileInfo>(new UploadFileInfo(
+ blocking_task_runner_,
+ UPLOAD_NEW_FILE,
+ upload_location,
+ drive_file_path,
+ local_file_path,
+ title,
+ content_type,
+ callback
+ )));
}
-int DriveUploader::UploadExistingFile(
+void DriveUploader::UploadExistingFile(
const GURL& upload_location,
const FilePath& drive_file_path,
const FilePath& local_file_path,
@@ -129,207 +180,161 @@ int DriveUploader::UploadExistingFile(
DCHECK(!content_type.empty());
DCHECK(!callback.is_null());
- scoped_ptr<UploadFileInfo> upload_file_info(new UploadFileInfo);
- upload_file_info->upload_mode = UPLOAD_EXISTING_FILE;
- upload_file_info->initial_upload_location = upload_location;
- upload_file_info->drive_path = drive_file_path;
- upload_file_info->file_path = local_file_path;
- upload_file_info->content_type = content_type;
- upload_file_info->completion_callback = callback;
- return StartUploadFile(upload_file_info.Pass());
+ StartUploadFile(scoped_ptr<UploadFileInfo>(new UploadFileInfo(
+ blocking_task_runner_,
+ UPLOAD_EXISTING_FILE,
+ upload_location,
+ drive_file_path,
+ local_file_path,
+ "", // title : not necessary for update of an existing file.
+ content_type,
+ callback
+ )));
}
-DriveUploader::UploadFileInfo* DriveUploader::GetUploadFileInfo(
- int upload_id) const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- UploadFileInfoMap::const_iterator it = pending_uploads_.find(upload_id);
- DVLOG_IF(1, it == pending_uploads_.end()) << "No upload found for id "
- << upload_id;
- return it != pending_uploads_.end() ? it->second : NULL;
-}
-
-void DriveUploader::OpenFile(UploadFileInfo* upload_file_info,
- FileOpenType open_type) {
+void DriveUploader::StartUploadFile(
+ scoped_ptr<UploadFileInfo> upload_file_info) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK_NE(UPLOAD_INVALID, upload_file_info->upload_mode);
+ DVLOG(1) << "Uploading file: " << upload_file_info->DebugString();
- // Passing a raw net::FileStream* from upload_file_info->file_stream.get() is
- // safe, because the FileStream is always deleted by posting the task to the
- // same sequenced task runner. (See RemoveUpload() and ~DriveUploader()).
- // That is, deletion won't happen until this task completes.
+ // Passing a raw net::FileStream* to the blocking pool is safe, because it is
+ // owned by |upload_file_info| in the reply callback.
+ UploadFileInfo* info_ptr = upload_file_info.get();
base::PostTaskAndReplyWithResult(
blocking_task_runner_.get(),
FROM_HERE,
base::Bind(&OpenFileStreamAndGetSizeOnBlockingPool,
- base::Unretained(upload_file_info->file_stream.get()),
- upload_file_info->file_path),
+ info_ptr->file_stream.get(),
+ info_ptr->file_path),
base::Bind(&DriveUploader::OpenCompletionCallback,
weak_ptr_factory_.GetWeakPtr(),
- open_type,
- upload_file_info->upload_id));
+ base::Passed(&upload_file_info)));
}
-void DriveUploader::OpenCompletionCallback(FileOpenType open_type,
- int upload_id,
- int64 file_size) {
+void DriveUploader::OpenCompletionCallback(
+ scoped_ptr<UploadFileInfo> upload_file_info, int64 file_size) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id);
- if (!upload_file_info)
- return;
-
if (file_size < 0) {
- UploadFailed(upload_file_info, DRIVE_UPLOAD_ERROR_NOT_FOUND);
+ UploadFailed(upload_file_info.Pass(), DRIVE_UPLOAD_ERROR_NOT_FOUND);
return;
}
- if (upload_file_info->initial_upload_location.is_empty()) {
- UploadFailed(upload_file_info, DRIVE_UPLOAD_ERROR_ABORT);
- return;
- }
+ upload_file_info->content_length = file_size;
// Open succeeded, initiate the upload.
- upload_file_info->content_length = file_size;
+ UploadFileInfo* info_ptr = upload_file_info.get();
drive_service_->InitiateUpload(
- InitiateUploadParams(upload_file_info->upload_mode,
- upload_file_info->title,
- upload_file_info->content_type,
- upload_file_info->content_length,
- upload_file_info->initial_upload_location,
- upload_file_info->drive_path),
+ InitiateUploadParams(info_ptr->upload_mode,
+ info_ptr->title,
+ info_ptr->content_type,
+ info_ptr->content_length,
+ info_ptr->initial_upload_location,
+ info_ptr->drive_path),
base::Bind(&DriveUploader::OnUploadLocationReceived,
weak_ptr_factory_.GetWeakPtr(),
- upload_file_info->upload_id));
+ base::Passed(&upload_file_info)));
}
-void DriveUploader::OnUploadLocationReceived(int upload_id,
- GDataErrorCode code,
- const GURL& upload_location) {
+void DriveUploader::OnUploadLocationReceived(
+ scoped_ptr<UploadFileInfo> upload_file_info,
+ GDataErrorCode code,
+ const GURL& upload_location) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id);
- if (!upload_file_info)
- return;
-
DVLOG(1) << "Got upload location [" << upload_location.spec()
<< "] for [" << upload_file_info->title << "]";
if (code != HTTP_SUCCESS) {
// TODO(achuith): Handle error codes from Google Docs server.
- UploadFailed(upload_file_info, DRIVE_UPLOAD_ERROR_ABORT);
+ UploadFailed(upload_file_info.Pass(), DRIVE_UPLOAD_ERROR_ABORT);
return;
}
upload_file_info->upload_location = upload_location;
// Start the upload from the beginning of the file.
- UploadNextChunk(upload_file_info);
+ UploadNextChunk(upload_file_info.Pass());
}
-void DriveUploader::UploadNextChunk(UploadFileInfo* upload_file_info) {
+void DriveUploader::UploadNextChunk(
+ scoped_ptr<UploadFileInfo> upload_file_info) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- // Check that |upload_file_info| is in pending_uploads_.
- DCHECK(upload_file_info == GetUploadFileInfo(upload_file_info->upload_id));
- DVLOG(1) << "Number of pending uploads=" << pending_uploads_.size();
- // Determine number of bytes to read for this upload iteration, which cannot
- // exceed size of buf i.e. buf_len.
+ // Determine number of bytes to read for this upload iteration.
const int bytes_to_read = std::min(upload_file_info->SizeRemaining(),
- upload_file_info->buf_len);
+ kUploadChunkSize);
if (bytes_to_read == 0) {
- // This should only happen when the actual file size is 0.
- DCHECK(upload_file_info->content_length == 0);
-
- upload_file_info->start_position = 0;
- upload_file_info->end_position = 0;
- // Skips file_stream->Read and error checks for 0-byte case. Immediately
- // proceeds to ResumeUpload.
- // TODO(kinaba): http://crbug.com/134814
- // Replace the following PostTask() to an direct method call. This is needed
- // because we have to ResumeUpload after the previous InitiateUpload or
- // ResumeUpload is completely finished; at this point, we are inside the
- // callback function from the previous operation, which is not treated as
- // finished yet.
- base::MessageLoopProxy::current()->PostTask(
+ // net::FileStream doesn't allow to read 0 bytes, so directly proceed to the
+ // completion callback. PostTask is necessary because we have to finish
+ // InitiateUpload's callback before calling ResumeUpload, due to the
+ // implementation of OperationRegistry. (http://crbug.com/134814)
+ MessageLoop::current()->PostTask(
FROM_HERE,
- base::Bind(&DriveUploader::ResumeUpload,
+ base::Bind(&DriveUploader::ReadCompletionCallback,
weak_ptr_factory_.GetWeakPtr(),
- upload_file_info->upload_id));
+ base::Passed(&upload_file_info), 0, 0));
return;
}
- // Passing a raw net::FileStream* from upload_file_info->file_stream.get() is
- // safe. See the comment in OpenFile().
+ // Passing a raw |file_stream| and |buf| to the blocking pool is safe, because
+ // they are owned by |upload_file_info| in the reply callback.
+ UploadFileInfo* info_ptr = upload_file_info.get();
base::PostTaskAndReplyWithResult(
blocking_task_runner_.get(),
FROM_HERE,
- base::Bind(&ReadFileStreamOnBlockingPool,
- upload_file_info->file_stream.get(),
- upload_file_info->buf,
+ base::Bind(&net::FileStream::ReadUntilComplete,
+ base::Unretained(info_ptr->file_stream.get()),
+ info_ptr->buf->data(),
bytes_to_read),
base::Bind(&DriveUploader::ReadCompletionCallback,
weak_ptr_factory_.GetWeakPtr(),
- upload_file_info->upload_id,
+ base::Passed(&upload_file_info),
bytes_to_read));
}
-void DriveUploader::ReadCompletionCallback(int upload_id,
- int bytes_to_read,
- int bytes_read) {
+void DriveUploader::ReadCompletionCallback(
+ scoped_ptr<UploadFileInfo> upload_file_info,
+ int bytes_to_read,
+ int bytes_read) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- // Should be non-zero. FileStream::Read() returns 0 only at end-of-file,
- // but we don't try to read from end-of-file.
- DCHECK_NE(0, bytes_read);
+ DCHECK_EQ(bytes_to_read, bytes_read);
DVLOG(1) << "ReadCompletionCallback bytes read=" << bytes_read;
- UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id);
- if (!upload_file_info)
- return;
-
if (bytes_read < 0) {
LOG(ERROR) << "Error reading from file "
<< upload_file_info->file_path.value();
- UploadFailed(upload_file_info, DRIVE_UPLOAD_ERROR_ABORT);
+ UploadFailed(upload_file_info.Pass(), DRIVE_UPLOAD_ERROR_ABORT);
return;
}
- upload_file_info->start_position = upload_file_info->end_position;
- upload_file_info->end_position =
- upload_file_info->start_position + bytes_read;
-
- ResumeUpload(upload_id);
-}
-
-void DriveUploader::ResumeUpload(int upload_id) {
- UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id);
- if (!upload_file_info)
- return;
+ int64 start_position = upload_file_info->next_send_position;
+ upload_file_info->next_send_position += bytes_read;
+ int64 end_position = upload_file_info->next_send_position;
+ UploadFileInfo* info_ptr = upload_file_info.get();
drive_service_->ResumeUpload(
- ResumeUploadParams(upload_file_info->upload_mode,
- upload_file_info->start_position,
- upload_file_info->end_position,
- upload_file_info->content_length,
- upload_file_info->content_type,
- upload_file_info->buf,
- upload_file_info->upload_location,
- upload_file_info->drive_path),
+ ResumeUploadParams(info_ptr->upload_mode,
+ start_position,
+ end_position,
+ info_ptr->content_length,
+ info_ptr->content_type,
+ info_ptr->buf,
+ info_ptr->upload_location,
+ info_ptr->drive_path),
base::Bind(&DriveUploader::OnResumeUploadResponseReceived,
weak_ptr_factory_.GetWeakPtr(),
- upload_file_info->upload_id));
+ base::Passed(&upload_file_info)));
}
void DriveUploader::OnResumeUploadResponseReceived(
- int upload_id,
+ scoped_ptr<UploadFileInfo> upload_file_info,
const ResumeUploadResponse& response,
scoped_ptr<ResourceEntry> entry) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- UploadFileInfo* upload_file_info = GetUploadFileInfo(upload_id);
- if (!upload_file_info)
- return;
-
const UploadMode upload_mode = upload_file_info->upload_mode;
if ((upload_mode == UPLOAD_NEW_FILE && response.code == HTTP_CREATED) ||
(upload_mode == UPLOAD_EXISTING_FILE && response.code == HTTP_SUCCESS)) {
@@ -337,15 +342,10 @@ void DriveUploader::OnResumeUploadResponseReceived(
<< upload_file_info->title << "]";
// Done uploading.
- upload_file_info->entry = entry.Pass();
- upload_file_info->completion_callback.Run(
- DRIVE_UPLOAD_OK,
- upload_file_info->drive_path,
- upload_file_info->file_path,
- upload_file_info->entry.Pass());
-
- // This will delete |upload_file_info|.
- RemoveUpload(scoped_ptr<UploadFileInfo>(upload_file_info));
+ upload_file_info->completion_callback.Run(DRIVE_UPLOAD_OK,
+ upload_file_info->drive_path,
+ upload_file_info->file_path,
+ entry.Pass());
return;
}
@@ -354,18 +354,17 @@ void DriveUploader::OnResumeUploadResponseReceived(
// upload the next chunk.
if (response.code != HTTP_RESUME_INCOMPLETE ||
response.start_position_received != 0 ||
- response.end_position_received != upload_file_info->end_position) {
+ response.end_position_received != upload_file_info->next_send_position) {
// TODO(achuith): Handle error cases, e.g.
// - when previously uploaded data wasn't received by Google Docs server,
// i.e. when end_position_received < upload_file_info->end_position
LOG(ERROR) << "UploadNextChunk http code=" << response.code
<< ", start_position_received=" << response.start_position_received
<< ", end_position_received=" << response.end_position_received
- << ", expected end range=" << upload_file_info->end_position;
- UploadFailed(
- upload_file_info,
- response.code == HTTP_FORBIDDEN ?
- DRIVE_UPLOAD_ERROR_NO_SPACE : DRIVE_UPLOAD_ERROR_ABORT);
+ << ", expected end range=" << upload_file_info->next_send_position;
+ UploadFailed(upload_file_info.Pass(),
+ response.code == HTTP_FORBIDDEN ?
+ DRIVE_UPLOAD_ERROR_NO_SPACE : DRIVE_UPLOAD_ERROR_ABORT);
return;
}
@@ -374,57 +373,19 @@ void DriveUploader::OnResumeUploadResponseReceived(
<< " for [" << upload_file_info->title << "]";
// Continue uploading.
- UploadNextChunk(upload_file_info);
+ UploadNextChunk(upload_file_info.Pass());
}
-void DriveUploader::UploadFailed(UploadFileInfo* upload_file_info,
+void DriveUploader::UploadFailed(scoped_ptr<UploadFileInfo> upload_file_info,
DriveUploadError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
LOG(ERROR) << "Upload failed " << upload_file_info->DebugString();
- upload_file_info->completion_callback.Run(
- error,
- upload_file_info->drive_path,
- upload_file_info->file_path,
- upload_file_info->entry.Pass());
-
- // This will delete |upload_file_info|.
- RemoveUpload(scoped_ptr<UploadFileInfo>(upload_file_info));
-}
-
-void DriveUploader::RemoveUpload(scoped_ptr<UploadFileInfo> upload_file_info) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- // FileStream must be closed on a file-access-allowed thread.
- blocking_task_runner_->DeleteSoon(
- FROM_HERE, upload_file_info->file_stream.release());
- pending_uploads_.erase(upload_file_info->upload_id);
-}
-
-DriveUploader::UploadFileInfo::UploadFileInfo()
- : upload_id(-1),
- content_length(0),
- upload_mode(UPLOAD_INVALID),
- file_stream(NULL),
- buf_len(0),
- start_position(0),
- end_position(0) {
-}
-
-DriveUploader::UploadFileInfo::~UploadFileInfo() { }
-
-int64 DriveUploader::UploadFileInfo::SizeRemaining() const {
- DCHECK(content_length >= end_position);
- return content_length - end_position;
-}
-
-std::string DriveUploader::UploadFileInfo::DebugString() const {
- return "title=[" + title +
- "], file_path=[" + file_path.AsUTF8Unsafe() +
- "], content_type=[" + content_type +
- "], content_length=[" + base::UintToString(content_length) +
- "], drive_path=[" + drive_path.AsUTF8Unsafe() +
- "]";
+ upload_file_info->completion_callback.Run(error,
+ upload_file_info->drive_path,
+ upload_file_info->file_path,
+ scoped_ptr<ResourceEntry>());
}
} // namespace google_apis
diff --git a/chrome/browser/google_apis/drive_uploader.h b/chrome/browser/google_apis/drive_uploader.h
index a08195f..b2f5000 100644
--- a/chrome/browser/google_apis/drive_uploader.h
+++ b/chrome/browser/google_apis/drive_uploader.h
@@ -5,20 +5,17 @@
#ifndef CHROME_BROWSER_GOOGLE_APIS_DRIVE_UPLOADER_H_
#define CHROME_BROWSER_GOOGLE_APIS_DRIVE_UPLOADER_H_
-#include <map>
#include <string>
#include "base/basictypes.h"
+#include "base/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/sequenced_worker_pool.h"
#include "chrome/browser/google_apis/drive_upload_error.h"
-#include "chrome/browser/google_apis/drive_upload_mode.h"
#include "chrome/browser/google_apis/gdata_errorcode.h"
#include "chrome/browser/google_apis/gdata_wapi_parser.h"
-#include "net/base/file_stream.h"
-#include "net/base/completion_callback.h"
-#include "net/base/file_stream.h"
+class FilePath;
class GURL;
namespace google_apis {
@@ -57,21 +54,21 @@ class DriveUploaderInterface {
// callback:
// Called when an upload is done regardless of it was successful or not.
// Must not be null.
- virtual int UploadNewFile(const GURL& upload_location,
- const FilePath& drive_file_path,
- const FilePath& local_file_path,
- const std::string& title,
- const std::string& content_type,
- const UploadCompletionCallback& callback) = 0;
+ virtual void UploadNewFile(const GURL& upload_location,
+ const FilePath& drive_file_path,
+ const FilePath& local_file_path,
+ const std::string& title,
+ const std::string& content_type,
+ const UploadCompletionCallback& callback) = 0;
// Uploads an existing file (a file that already exists on Drive).
//
// See comments at UploadNewFile() about common parameters.
- virtual int UploadExistingFile(const GURL& upload_location,
- const FilePath& drive_file_path,
- const FilePath& local_file_path,
- const std::string& content_type,
- const UploadCompletionCallback& callback) = 0;
+ virtual void UploadExistingFile(const GURL& upload_location,
+ const FilePath& drive_file_path,
+ const FilePath& local_file_path,
+ const std::string& content_type,
+ const UploadCompletionCallback& callback) = 0;
};
class DriveUploader : public DriveUploaderInterface {
@@ -80,13 +77,13 @@ class DriveUploader : public DriveUploaderInterface {
virtual ~DriveUploader();
// DriveUploaderInterface overrides.
- virtual int UploadNewFile(const GURL& upload_location,
- const FilePath& drive_file_path,
- const FilePath& local_file_path,
- const std::string& title,
- const std::string& content_type,
- const UploadCompletionCallback& callback) OVERRIDE;
- virtual int UploadExistingFile(
+ virtual void UploadNewFile(const GURL& upload_location,
+ const FilePath& drive_file_path,
+ const FilePath& local_file_path,
+ const std::string& title,
+ const std::string& content_type,
+ const UploadCompletionCallback& callback) OVERRIDE;
+ virtual void UploadExistingFile(
const GURL& upload_location,
const FilePath& drive_file_path,
const FilePath& local_file_path,
@@ -94,138 +91,48 @@ class DriveUploader : public DriveUploaderInterface {
const UploadCompletionCallback& callback) OVERRIDE;
private:
- // Structure containing current upload information of file, passed between
- // DriveServiceInterface methods and callbacks.
- struct UploadFileInfo {
- // To be able to access UploadFileInfo from tests.
- UploadFileInfo();
- ~UploadFileInfo();
-
- // Bytes left to upload.
- int64 SizeRemaining() const;
-
- // Useful for printf debugging.
- std::string DebugString() const;
-
- int upload_id; // id of this upload.
- FilePath file_path; // The path of the file to be uploaded.
-
- // TODO(zelirag, achuith): Make this string16.
- std::string title; // Title to be used for file to be uploaded.
- std::string content_type; // Content-Type of file.
- int64 content_length; // Header content-Length.
-
- UploadMode upload_mode;
-
- // Location URL used to get |upload_location| with InitiateUpload.
- GURL initial_upload_location;
-
- // Location URL where file is to be uploaded to, returned from
- // InitiateUpload. Used for the subsequent ResumeUpload requests.
- GURL upload_location;
-
- // Final path in gdata. Looks like /special/drive/MyFolder/MyFile.
- FilePath drive_path;
-
- // TODO(achuith): Use generic stream object after FileStream is refactored
- // to extend a generic stream.
- //
- // TODO(kinaba): We should switch to async API of FileStream once
- // crbug.com/164312 is fixed.
- //
- // For opening and reading from physical file.
- // Every file operation is posted to the sequenced worker pool, while the
- // ownership of |file_stream| is held by DriveUploader in UI thread. At the
- // point when DriveUploader deletes UploadFileInfo, it passes the ownership
- // of the stream to sequenced worker pool.
- scoped_ptr<net::FileStream> file_stream;
- scoped_refptr<net::IOBuffer> buf; // Holds current content to be uploaded.
- // Size of |buf|, max is 512KB; Google Docs requires size of each upload
- // chunk to be a multiple of 512KB.
- int64 buf_len;
-
- // The start and the end position of the range of contents currently stored
- // in |buf|. Note that end_position is exclusive, so start_position = 0 and
- // end_position = 9 means 9 bytes.
- int64 start_position;
- int64 end_position;
-
- // Will be set once the upload is complete.
- scoped_ptr<ResourceEntry> entry;
-
- // Callback to be invoked once the upload has finished.
- UploadCompletionCallback completion_callback;
- };
-
- // Indicates step in which we try to open a file.
- // Retrying happens in FILE_OPEN_UPDATE_UPLOAD step.
- enum FileOpenType {
- FILE_OPEN_START_UPLOAD,
- FILE_OPEN_UPDATE_UPLOAD
- };
-
- // Lookup UploadFileInfo* in pending_uploads_.
- UploadFileInfo* GetUploadFileInfo(int upload_id) const;
-
- // Open the file.
- void OpenFile(UploadFileInfo* upload_file_info, FileOpenType open_type);
+ struct UploadFileInfo;
+
+ // Starts uploading a file with |upload_file_info|.
+ void StartUploadFile(scoped_ptr<UploadFileInfo> upload_file_info);
// net::FileStream::Open completion callback. The result of the file open
// operation is passed as |result|, and the size is stored in |file_size|.
- void OpenCompletionCallback(FileOpenType open_type,
- int upload_id,
+ void OpenCompletionCallback(scoped_ptr<UploadFileInfo> upload_file_info,
int64 file_size);
// DriveService callback for InitiateUpload.
- void OnUploadLocationReceived(int upload_id,
+ void OnUploadLocationReceived(scoped_ptr<UploadFileInfo> upload_file_info,
GDataErrorCode code,
const GURL& upload_location);
// Uploads the next chunk of data from the file.
- void UploadNextChunk(UploadFileInfo* upload_file_info);
+ void UploadNextChunk(scoped_ptr<UploadFileInfo> upload_file_info);
// net::FileStream::Read completion callback.
- void ReadCompletionCallback(int upload_id,
+ void ReadCompletionCallback(scoped_ptr<UploadFileInfo> upload_file_info,
int bytes_to_read,
int bytes_read);
// Calls DriveService's ResumeUpload with the current upload info.
- void ResumeUpload(int upload_id);
+ void ResumeUpload(scoped_ptr<UploadFileInfo> upload_file_info,
+ int bytes_to_send);
// DriveService callback for ResumeUpload.
void OnResumeUploadResponseReceived(
- int upload_id,
+ scoped_ptr<UploadFileInfo> upload_file_info,
const ResumeUploadResponse& response,
scoped_ptr<ResourceEntry> entry);
- // Initiate the upload.
- void InitiateUpload(UploadFileInfo* uploader_file_info);
-
// Handle failed uploads.
- void UploadFailed(UploadFileInfo* upload_file_info,
+ void UploadFailed(scoped_ptr<UploadFileInfo> upload_file_info,
DriveUploadError error);
- // Removes |upload_file_info| from UploadFileInfoMap |pending_uploads_|.
- // After its removal from the map, |upload_file_info| is deleted.
- void RemoveUpload(scoped_ptr<UploadFileInfo> upload_file_info);
-
- // Starts uploading a file with |upload_file_info|. Returns a new upload
- // ID assigned to |upload_file_info|. |upload_file_info| is added to
- // |pending_uploads_map_|.
- int StartUploadFile(scoped_ptr<UploadFileInfo> upload_file_info);
-
// Pointers to DriveServiceInterface object owned by DriveSystemService.
// The lifetime of this object is guaranteed to exceed that of the
// DriveUploader instance.
DriveServiceInterface* drive_service_;
- int next_upload_id_; // id counter.
-
- typedef std::map<int, UploadFileInfo*> UploadFileInfoMap;
- // Upload file infos added to the map are deleted either in |RemoveUpload| or
- // in DriveUploader dtor (i.e. we can assume |this| takes their ownership).
- UploadFileInfoMap pending_uploads_;
-
// TaskRunner for opening, reading, and closing files.
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
diff --git a/chrome/browser/sync_file_system/drive_file_sync_client_unittest.cc b/chrome/browser/sync_file_system/drive_file_sync_client_unittest.cc
index 7f93dcf..9c92d880 100644
--- a/chrome/browser/sync_file_system/drive_file_sync_client_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_file_sync_client_unittest.cc
@@ -45,7 +45,7 @@ class FakeDriveUploader : public google_apis::DriveUploaderInterface {
// Pretends that a new file was uploaded successfully, and returns the
// contents of "gdata/file_entry.json" to the caller.
- virtual int UploadNewFile(
+ virtual void UploadNewFile(
const GURL& upload_location,
const FilePath& drive_file_path,
const FilePath& local_file_path,
@@ -67,13 +67,12 @@ class FakeDriveUploader : public google_apis::DriveUploaderInterface {
drive_file_path,
local_file_path,
base::Passed(&file_entry)));
- return 1; // Return dummy upload ID.
}
// Pretends that an existing file ("file:resource_id") was uploaded
// successfully, and returns the contents of "gdata/file_entry.json" to the
// caller.
- virtual int UploadExistingFile(
+ virtual void UploadExistingFile(
const GURL& upload_location,
const FilePath& drive_file_path,
const FilePath& local_file_path,
@@ -94,7 +93,6 @@ class FakeDriveUploader : public google_apis::DriveUploaderInterface {
drive_file_path,
local_file_path,
base::Passed(&file_entry)));
- return 1; // Return dummy upload ID.
}
};