drive: Use UploadNewFile from EntryUpdatePerformer
Add UploadNewFileOptions argument to JobScheduler::UploadNewFile().
Pass ChangeListLoader* to SyncClient and EntryUpdatePerformer to lock the loader while creating new files.
Upload an empty file if the locally created file doesn't have a cache file.
BUG=260539
TEST=unit_tests
[email protected]
Review URL: https://codereview.chromium.org/148233006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@247660 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/chromeos/drive/file_system.cc b/chrome/browser/chromeos/drive/file_system.cc
index d2957c8..24af2b3 100644
--- a/chrome/browser/chromeos/drive/file_system.cc
+++ b/chrome/browser/chromeos/drive/file_system.cc
@@ -307,19 +307,20 @@
cache_,
temporary_file_directory_));
- sync_client_.reset(new internal::SyncClient(blocking_task_runner_.get(),
- observer,
- scheduler_,
- resource_metadata_,
- cache_,
- temporary_file_directory_));
-
change_list_loader_.reset(new internal::ChangeListLoader(
blocking_task_runner_.get(),
resource_metadata_,
scheduler_,
drive_service_));
change_list_loader_->AddObserver(this);
+
+ sync_client_.reset(new internal::SyncClient(blocking_task_runner_.get(),
+ observer,
+ scheduler_,
+ resource_metadata_,
+ cache_,
+ change_list_loader_.get(),
+ temporary_file_directory_));
}
void FileSystem::CheckForUpdates() {
diff --git a/chrome/browser/chromeos/drive/file_system.h b/chrome/browser/chromeos/drive/file_system.h
index 28f608a..9d13730 100644
--- a/chrome/browser/chromeos/drive/file_system.h
+++ b/chrome/browser/chromeos/drive/file_system.h
@@ -255,11 +255,11 @@
// Error of the last update check.
FileError last_update_check_error_;
- scoped_ptr<internal::SyncClient> sync_client_;
-
// The loader is used to load the change lists.
scoped_ptr<internal::ChangeListLoader> change_list_loader_;
+ scoped_ptr<internal::SyncClient> sync_client_;
+
ObserverList<FileSystemObserver> observers_;
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
diff --git a/chrome/browser/chromeos/drive/file_system/operation_test_base.h b/chrome/browser/chromeos/drive/file_system/operation_test_base.h
index 4707f2b..e47c85d 100644
--- a/chrome/browser/chromeos/drive/file_system/operation_test_base.h
+++ b/chrome/browser/chromeos/drive/file_system/operation_test_base.h
@@ -117,6 +117,9 @@
return fake_free_disk_space_getter_.get();
}
internal::FileCache* cache() { return cache_.get(); }
+ internal::ChangeListLoader* change_list_loader() {
+ return change_list_loader_.get();
+ }
private:
content::TestBrowserThreadBundle thread_bundle_;
diff --git a/chrome/browser/chromeos/drive/job_scheduler.cc b/chrome/browser/chromeos/drive/job_scheduler.cc
index 68c666fd..3163d565 100644
--- a/chrome/browser/chromeos/drive/job_scheduler.cc
+++ b/chrome/browser/chromeos/drive/job_scheduler.cc
@@ -73,6 +73,7 @@
base::FilePath local_file_path;
std::string title;
std::string content_type;
+ drive::DriveUploader::UploadNewFileOptions options;
UploadCompletionCallback callback;
google_apis::ProgressCallback progress_callback;
};
@@ -85,7 +86,7 @@
params.local_file_path,
params.title,
params.content_type,
- DriveUploader::UploadNewFileOptions(),
+ params.options,
params.callback,
params.progress_callback);
}
@@ -618,6 +619,7 @@
const base::FilePath& local_file_path,
const std::string& title,
const std::string& content_type,
+ const drive::DriveUploader::UploadNewFileOptions& options,
const ClientContext& context,
const google_apis::GetResourceEntryCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -631,6 +633,7 @@
params.local_file_path = local_file_path;
params.title = title;
params.content_type = content_type;
+ params.options = options;
ResumeUploadParams resume_params;
resume_params.local_file_path = params.local_file_path;
diff --git a/chrome/browser/chromeos/drive/job_scheduler.h b/chrome/browser/chromeos/drive/job_scheduler.h
index 3d807e48..81cf0030 100644
--- a/chrome/browser/chromeos/drive/job_scheduler.h
+++ b/chrome/browser/chromeos/drive/job_scheduler.h
@@ -175,6 +175,7 @@
const base::FilePath& local_file_path,
const std::string& title,
const std::string& content_type,
+ const drive::DriveUploader::UploadNewFileOptions& options,
const ClientContext& context,
const google_apis::GetResourceEntryCallback& callback);
diff --git a/chrome/browser/chromeos/drive/job_scheduler_unittest.cc b/chrome/browser/chromeos/drive/job_scheduler_unittest.cc
index fb58dced..c1b123c 100644
--- a/chrome/browser/chromeos/drive/job_scheduler_unittest.cc
+++ b/chrome/browser/chromeos/drive/job_scheduler_unittest.cc
@@ -971,6 +971,7 @@
path,
"dummy title",
"plain/plain",
+ DriveUploader::UploadNewFileOptions(),
ClientContext(BACKGROUND),
google_apis::test_util::CreateCopyResultCallback(&upload_error, &entry));
base::RunLoop().RunUntilIdle();
@@ -1003,6 +1004,7 @@
upload_path,
"dummy title 1",
"text/plain",
+ DriveUploader::UploadNewFileOptions(),
ClientContext(BACKGROUND),
google_apis::test_util::CreateCopyResultCallback(&error1, &entry));
@@ -1019,6 +1021,7 @@
upload_path,
"dummy title 2",
"text/plain",
+ DriveUploader::UploadNewFileOptions(),
ClientContext(BACKGROUND),
google_apis::test_util::CreateCopyResultCallback(&error2, &entry));
@@ -1051,6 +1054,7 @@
upload_path,
"dummy title 1",
"text/plain",
+ DriveUploader::UploadNewFileOptions(),
ClientContext(USER_INITIATED),
google_apis::test_util::CreateCopyResultCallback(&error1, &entry));
@@ -1068,6 +1072,7 @@
upload_path,
"dummy title 2",
"text/plain",
+ DriveUploader::UploadNewFileOptions(),
ClientContext(USER_INITIATED),
google_apis::test_util::CreateCopyResultCallback(&error2, &entry));
diff --git a/chrome/browser/chromeos/drive/sync/entry_update_performer.cc b/chrome/browser/chromeos/drive/sync/entry_update_performer.cc
index 22357d9..e34367d 100644
--- a/chrome/browser/chromeos/drive/sync/entry_update_performer.cc
+++ b/chrome/browser/chromeos/drive/sync/entry_update_performer.cc
@@ -4,6 +4,9 @@
#include "chrome/browser/chromeos/drive/sync/entry_update_performer.h"
+#include "base/callback_helpers.h"
+#include "base/file_util.h"
+#include "chrome/browser/chromeos/drive/change_list_loader.h"
#include "chrome/browser/chromeos/drive/drive.pb.h"
#include "chrome/browser/chromeos/drive/file_cache.h"
#include "chrome/browser/chromeos/drive/file_system_util.h"
@@ -50,11 +53,23 @@
if (local_state->drive_file_path.empty())
return FILE_ERROR_NOT_FOUND;
- // Check if content update is needed or not.
FileCacheEntry cache_entry;
- if (cache->GetCacheEntry(local_id, &cache_entry) &&
- cache_entry.is_dirty() &&
- !cache->IsOpenedForWrite(local_id)) {
+ cache->GetCacheEntry(local_id, &cache_entry);
+ if (!cache_entry.is_present() && local_state->entry.resource_id().empty()) {
+ // Locally created file with no cache file, store an empty file.
+ base::FilePath empty_file;
+ if (!base::CreateTemporaryFile(&empty_file))
+ return FILE_ERROR_FAILED;
+ error = cache->Store(local_id, std::string(), empty_file,
+ FileCache::FILE_OPERATION_MOVE);
+ if (error != FILE_ERROR_OK)
+ return error;
+ if (!cache->GetCacheEntry(local_id, &cache_entry))
+ return FILE_ERROR_NOT_FOUND;
+ }
+
+ // Check if content update is needed or not.
+ if (cache_entry.is_dirty() && !cache->IsOpenedForWrite(local_id)) {
// Update cache entry's MD5 if needed.
if (cache_entry.md5().empty()) {
error = cache->UpdateMd5(local_id);
@@ -114,6 +129,7 @@
}
if (!entry.file_info().is_directory())
entry.mutable_file_specific_info()->set_md5(resource_entry->file_md5());
+ entry.set_resource_id(resource_entry->resource_id());
error = metadata->RefreshEntry(entry);
if (error != FILE_ERROR_OK)
return error;
@@ -136,11 +152,13 @@
file_system::OperationObserver* observer,
JobScheduler* scheduler,
ResourceMetadata* metadata,
- FileCache* cache)
+ FileCache* cache,
+ ChangeListLoader* change_list_loader)
: blocking_task_runner_(blocking_task_runner),
scheduler_(scheduler),
metadata_(metadata),
cache_(cache),
+ change_list_loader_(change_list_loader),
remove_performer_(new RemovePerformer(blocking_task_runner,
observer,
scheduler,
@@ -200,23 +218,44 @@
// Perform content update.
if (local_state->should_content_update) {
- drive::DriveUploader::UploadExistingFileOptions options;
- options.title = local_state->entry.title();
- options.parent_resource_id = local_state->parent_entry.resource_id();
- options.modified_date = last_modified;
- options.last_viewed_by_me_date = last_accessed;
- scheduler_->UploadExistingFile(
- local_state->entry.resource_id(),
- local_state->drive_file_path,
- local_state->cache_file_path,
- local_state->entry.file_specific_info().content_mime_type(),
- options,
- context,
- base::Bind(&EntryUpdatePerformer::UpdateEntryAfterUpdateResource,
- weak_ptr_factory_.GetWeakPtr(),
- context,
- callback,
- local_state->entry.local_id()));
+ if (local_state->entry.resource_id().empty()) {
+ drive::DriveUploader::UploadNewFileOptions options;
+ options.modified_date = last_modified;
+ options.last_viewed_by_me_date = last_accessed;
+ scheduler_->UploadNewFile(
+ local_state->parent_entry.resource_id(),
+ local_state->drive_file_path,
+ local_state->cache_file_path,
+ local_state->entry.title(),
+ local_state->entry.file_specific_info().content_mime_type(),
+ options,
+ context,
+ base::Bind(&EntryUpdatePerformer::UpdateEntryAfterUpdateResource,
+ weak_ptr_factory_.GetWeakPtr(),
+ context,
+ callback,
+ local_state->entry.local_id(),
+ base::Passed(change_list_loader_->GetLock())));
+ } else {
+ drive::DriveUploader::UploadExistingFileOptions options;
+ options.title = local_state->entry.title();
+ options.parent_resource_id = local_state->parent_entry.resource_id();
+ options.modified_date = last_modified;
+ options.last_viewed_by_me_date = last_accessed;
+ scheduler_->UploadExistingFile(
+ local_state->entry.resource_id(),
+ local_state->drive_file_path,
+ local_state->cache_file_path,
+ local_state->entry.file_specific_info().content_mime_type(),
+ options,
+ context,
+ base::Bind(&EntryUpdatePerformer::UpdateEntryAfterUpdateResource,
+ weak_ptr_factory_.GetWeakPtr(),
+ context,
+ callback,
+ local_state->entry.local_id(),
+ base::Passed(scoped_ptr<base::ScopedClosureRunner>())));
+ }
return;
}
@@ -233,13 +272,15 @@
context,
base::Bind(&EntryUpdatePerformer::UpdateEntryAfterUpdateResource,
weak_ptr_factory_.GetWeakPtr(),
- context, callback, local_state->entry.local_id()));
+ context, callback, local_state->entry.local_id(),
+ base::Passed(scoped_ptr<base::ScopedClosureRunner>())));
}
void EntryUpdatePerformer::UpdateEntryAfterUpdateResource(
const ClientContext& context,
const FileOperationCallback& callback,
const std::string& local_id,
+ scoped_ptr<base::ScopedClosureRunner> change_list_loader_lock,
google_apis::GDataErrorCode status,
scoped_ptr<google_apis::ResourceEntry> resource_entry) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
diff --git a/chrome/browser/chromeos/drive/sync/entry_update_performer.h b/chrome/browser/chromeos/drive/sync/entry_update_performer.h
index b09a877b..a4a2735 100644
--- a/chrome/browser/chromeos/drive/sync/entry_update_performer.h
+++ b/chrome/browser/chromeos/drive/sync/entry_update_performer.h
@@ -13,6 +13,7 @@
#include "google_apis/drive/gdata_errorcode.h"
namespace base {
+class ScopedClosureRunner;
class SequencedTaskRunner;
} // namespace base
@@ -32,6 +33,7 @@
namespace internal {
+class ChangeListLoader;
class EntryRevertPerformer;
class FileCache;
class RemovePerformer;
@@ -44,7 +46,8 @@
file_system::OperationObserver* observer,
JobScheduler* scheduler,
ResourceMetadata* metadata,
- FileCache* cache);
+ FileCache* cache,
+ ChangeListLoader* change_list_loader);
~EntryUpdatePerformer();
// Requests the server to update the metadata of the entry specified by
@@ -69,6 +72,7 @@
const ClientContext& context,
const FileOperationCallback& callback,
const std::string& local_id,
+ scoped_ptr<base::ScopedClosureRunner> change_list_loader_lock,
google_apis::GDataErrorCode status,
scoped_ptr<google_apis::ResourceEntry> resource_entry);
@@ -76,6 +80,7 @@
JobScheduler* scheduler_;
ResourceMetadata* metadata_;
FileCache* cache_;
+ ChangeListLoader* change_list_loader_;
scoped_ptr<RemovePerformer> remove_performer_;
scoped_ptr<EntryRevertPerformer> entry_revert_performer_;
diff --git a/chrome/browser/chromeos/drive/sync/entry_update_performer_unittest.cc b/chrome/browser/chromeos/drive/sync/entry_update_performer_unittest.cc
index ceb69926..8e4bcca 100644
--- a/chrome/browser/chromeos/drive/sync/entry_update_performer_unittest.cc
+++ b/chrome/browser/chromeos/drive/sync/entry_update_performer_unittest.cc
@@ -25,12 +25,13 @@
class EntryUpdatePerformerTest : public file_system::OperationTestBase {
protected:
virtual void SetUp() OVERRIDE {
- OperationTestBase::SetUp();
- performer_.reset(new EntryUpdatePerformer(blocking_task_runner(),
- observer(),
- scheduler(),
- metadata(),
- cache()));
+ OperationTestBase::SetUp();
+ performer_.reset(new EntryUpdatePerformer(blocking_task_runner(),
+ observer(),
+ scheduler(),
+ metadata(),
+ cache(),
+ change_list_loader()));
}
// Stores |content| to the cache and mark it as dirty.
@@ -360,5 +361,61 @@
EXPECT_FALSE(cache_entry.is_dirty());
}
+TEST_F(EntryUpdatePerformerTest, UpdateEntry_UploadNewFile) {
+ // Create a new file locally.
+ const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/root/New File.txt"));
+
+ ResourceEntry parent;
+ EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kFilePath.DirName(), &parent));
+
+ ResourceEntry entry;
+ entry.set_parent_local_id(parent.local_id());
+ entry.set_title(kFilePath.BaseName().AsUTF8Unsafe());
+ entry.mutable_file_specific_info()->set_content_mime_type("text/plain");
+ entry.set_metadata_edit_state(ResourceEntry::DIRTY);
+
+ FileError error = FILE_ERROR_FAILED;
+ std::string local_id;
+ base::PostTaskAndReplyWithResult(
+ blocking_task_runner(),
+ FROM_HERE,
+ base::Bind(&internal::ResourceMetadata::AddEntry,
+ base::Unretained(metadata()),
+ entry,
+ &local_id),
+ google_apis::test_util::CreateCopyResultCallback(&error));
+ test_util::RunBlockingPoolTask();
+ EXPECT_EQ(FILE_ERROR_OK, error);
+
+ // Update. This should result in creating a new file on the server.
+ error = FILE_ERROR_FAILED;
+ performer_->UpdateEntry(
+ local_id,
+ ClientContext(USER_INITIATED),
+ google_apis::test_util::CreateCopyResultCallback(&error));
+ test_util::RunBlockingPoolTask();
+ EXPECT_EQ(FILE_ERROR_OK, error);
+
+ // The entry got a resource ID.
+ EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kFilePath, &entry));
+ EXPECT_FALSE(entry.resource_id().empty());
+ EXPECT_EQ(ResourceEntry::CLEAN, entry.metadata_edit_state());
+
+ // Make sure that the cache is no longer dirty.
+ bool success = false;
+ FileCacheEntry cache_entry;
+ base::PostTaskAndReplyWithResult(
+ blocking_task_runner(),
+ FROM_HERE,
+ base::Bind(&FileCache::GetCacheEntry,
+ base::Unretained(cache()),
+ local_id,
+ &cache_entry),
+ google_apis::test_util::CreateCopyResultCallback(&success));
+ test_util::RunBlockingPoolTask();
+ EXPECT_TRUE(success);
+ EXPECT_FALSE(cache_entry.is_dirty());
+}
+
} // namespace internal
} // namespace drive
diff --git a/chrome/browser/chromeos/drive/sync_client.cc b/chrome/browser/chromeos/drive/sync_client.cc
index a679f3f8..a8bddb6 100644
--- a/chrome/browser/chromeos/drive/sync_client.cc
+++ b/chrome/browser/chromeos/drive/sync_client.cc
@@ -136,6 +136,7 @@
JobScheduler* scheduler,
ResourceMetadata* metadata,
FileCache* cache,
+ ChangeListLoader* change_list_loader,
const base::FilePath& temporary_file_directory)
: blocking_task_runner_(blocking_task_runner),
operation_observer_(observer),
@@ -152,7 +153,8 @@
observer,
scheduler,
metadata,
- cache)),
+ cache,
+ change_list_loader)),
delay_(base::TimeDelta::FromSeconds(kDelaySeconds)),
long_delay_(base::TimeDelta::FromSeconds(kLongDelaySeconds)),
weak_ptr_factory_(this) {
diff --git a/chrome/browser/chromeos/drive/sync_client.h b/chrome/browser/chromeos/drive/sync_client.h
index 677ff1a..5f7f811 100644
--- a/chrome/browser/chromeos/drive/sync_client.h
+++ b/chrome/browser/chromeos/drive/sync_client.h
@@ -33,6 +33,7 @@
namespace internal {
+class ChangeListLoader;
class EntryUpdatePerformer;
class FileCache;
class ResourceMetadata;
@@ -50,6 +51,7 @@
JobScheduler* scheduler,
ResourceMetadata* metadata,
FileCache* cache,
+ ChangeListLoader* change_list_loader,
const base::FilePath& temporary_file_directory);
virtual ~SyncClient();
diff --git a/chrome/browser/chromeos/drive/sync_client_unittest.cc b/chrome/browser/chromeos/drive/sync_client_unittest.cc
index 77da5459..4698b96 100644
--- a/chrome/browser/chromeos/drive/sync_client_unittest.cc
+++ b/chrome/browser/chromeos/drive/sync_client_unittest.cc
@@ -135,6 +135,11 @@
NULL /* free_disk_space_getter */));
ASSERT_TRUE(cache_->Initialize());
+ change_list_loader_.reset(new ChangeListLoader(
+ base::MessageLoopProxy::current().get(),
+ metadata_.get(),
+ scheduler_.get(),
+ drive_service_.get()));
ASSERT_NO_FATAL_FAILURE(SetUpTestData());
sync_client_.reset(new SyncClient(base::MessageLoopProxy::current().get(),
@@ -142,6 +147,7 @@
scheduler_.get(),
metadata_.get(),
cache_.get(),
+ change_list_loader_.get(),
temp_dir_.path()));
// Disable delaying so that DoSyncLoop() starts immediately.
@@ -184,12 +190,7 @@
// Load data from the service to the metadata.
FileError error = FILE_ERROR_FAILED;
- internal::ChangeListLoader change_list_loader(
- base::MessageLoopProxy::current().get(),
- metadata_.get(),
- scheduler_.get(),
- drive_service_.get());
- change_list_loader.LoadForTesting(
+ change_list_loader_->LoadForTesting(
google_apis::test_util::CreateCopyResultCallback(&error));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(FILE_ERROR_OK, error);
@@ -256,6 +257,7 @@
test_util::DestroyHelperForTests> metadata_storage_;
scoped_ptr<ResourceMetadata, test_util::DestroyHelperForTests> metadata_;
scoped_ptr<FileCache, test_util::DestroyHelperForTests> cache_;
+ scoped_ptr<ChangeListLoader> change_list_loader_;
scoped_ptr<SyncClient> sync_client_;
std::map<std::string, std::string> resource_ids_; // Name-to-id map.