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

Unified Diff: chrome/browser/chromeos/drive/file_system/move_operation.cc

Issue 22920004: Reimplement MoveOperation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/drive/file_system/move_operation.cc
diff --git a/chrome/browser/chromeos/drive/file_system/move_operation.cc b/chrome/browser/chromeos/drive/file_system/move_operation.cc
index ded4aacddd9668d48da29b44169c80364f35dfb3..8620ce31f58ba34c27552de342848fe2000234c4 100644
--- a/chrome/browser/chromeos/drive/file_system/move_operation.cc
+++ b/chrome/browser/chromeos/drive/file_system/move_operation.cc
@@ -14,14 +14,72 @@ using content::BrowserThread;
namespace drive {
namespace file_system {
+namespace {
+
+// Looks up ResourceEntry for source entry and the destination directory.
+FileError PrepareMove(internal::ResourceMetadata* metadata,
+ const base::FilePath& src_path,
+ const base::FilePath& dest_parent_path,
+ ResourceEntry* src_entry,
+ ResourceEntry* dest_parent_entry) {
+ DCHECK(metadata);
hashimoto 2013/08/21 07:49:08 nit: Do we need this? At least, two functions belo
hidehiko 2013/08/21 08:07:00 Ok, removed.
+ DCHECK(src_entry);
+ DCHECK(dest_parent_entry);
+
+ FileError error = metadata->GetResourceEntryByPath(src_path, src_entry);
+ if (error != FILE_ERROR_OK)
+ return error;
+
+ return metadata->GetResourceEntryByPath(dest_parent_path, dest_parent_entry);
+}
+
+// Applies renaming to the local metadata.
+FileError RenameLocally(internal::ResourceMetadata* metadata,
+ const std::string& resource_id,
+ const std::string& new_title) {
+ ResourceEntry entry;
+ FileError error = metadata->GetResourceEntryById(resource_id, &entry);
+ if (error != FILE_ERROR_OK)
+ return error;
+
+ entry.set_title(new_title);
+ return metadata->RefreshEntry(entry);
+}
+
+// Applies directory-moving to the local metadata.
+FileError MoveDirectoryLocally(internal::ResourceMetadata* metadata,
+ const std::string& resource_id,
+ const std::string& parent_resource_id) {
+ ResourceEntry entry;
+ FileError error = metadata->GetResourceEntryById(resource_id, &entry);
+ if (error != FILE_ERROR_OK)
+ return error;
+
+ // Make sure that the parent exists and it is actually a directory.
hashimoto 2013/08/21 07:49:08 ResourceMetadata::RefreshEntry does this check.
hidehiko 2013/08/21 08:07:00 Removed. Instead, edit ResourceMetadata::RefreshEn
+ ResourceEntry parent_entry;
+ error = metadata->GetResourceEntryById(parent_resource_id, &parent_entry);
+ if (error != FILE_ERROR_OK)
+ return error;
+
+ if (!parent_entry.file_info().is_directory())
+ return FILE_ERROR_NOT_A_DIRECTORY;
+
+ // Update the parent.
+ entry.set_parent_resource_id(parent_resource_id);
+ return metadata->RefreshEntry(entry);
+}
-MoveOperation::MoveOperation(OperationObserver* observer,
+} // namespace
+
+MoveOperation::MoveOperation(base::SequencedTaskRunner* blocking_task_runner,
+ OperationObserver* observer,
JobScheduler* scheduler,
internal::ResourceMetadata* metadata)
- : observer_(observer),
- scheduler_(scheduler),
- metadata_(metadata),
- weak_ptr_factory_(this) {
+ : blocking_task_runner_(blocking_task_runner),
+ observer_(observer),
+ scheduler_(scheduler),
+ metadata_(metadata),
+ weak_ptr_factory_(this) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
@@ -35,175 +93,198 @@ void MoveOperation::Move(const base::FilePath& src_file_path,
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
- metadata_->GetResourceEntryPairByPathsOnUIThread(
- src_file_path,
- dest_file_path.DirName(),
- base::Bind(&MoveOperation::MoveAfterGetResourceEntryPair,
+ scoped_ptr<ResourceEntry> src_entry(new ResourceEntry);
+ scoped_ptr<ResourceEntry> dest_parent_entry(new ResourceEntry);
+ ResourceEntry* src_entry_ptr = src_entry.get();
+ ResourceEntry* dest_parent_entry_ptr = dest_parent_entry.get();
+ base::PostTaskAndReplyWithResult(
+ blocking_task_runner_.get(),
+ FROM_HERE,
+ base::Bind(&PrepareMove,
+ metadata_, src_file_path, dest_file_path.DirName(),
+ src_entry_ptr, dest_parent_entry_ptr),
+ base::Bind(&MoveOperation::MoveAfterPrepare,
weak_ptr_factory_.GetWeakPtr(),
- dest_file_path,
- callback));
+ src_file_path, dest_file_path, callback,
+ base::Passed(&src_entry),
+ base::Passed(&dest_parent_entry)));
}
-void MoveOperation::MoveAfterGetResourceEntryPair(
+void MoveOperation::MoveAfterPrepare(
+ const base::FilePath& src_file_path,
const base::FilePath& dest_file_path,
const FileOperationCallback& callback,
- scoped_ptr<EntryInfoPairResult> src_dest_info) {
+ scoped_ptr<ResourceEntry> src_entry,
+ scoped_ptr<ResourceEntry> dest_parent_entry,
+ FileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
- DCHECK(src_dest_info.get());
- if (src_dest_info->first.error != FILE_ERROR_OK) {
- callback.Run(src_dest_info->first.error);
- return;
- }
- if (src_dest_info->second.error != FILE_ERROR_OK) {
- callback.Run(src_dest_info->second.error);
+ if (error != FILE_ERROR_OK) {
+ callback.Run(error);
return;
}
- if (!src_dest_info->second.entry->file_info().is_directory()) {
+
+ if (!dest_parent_entry->file_info().is_directory()) {
+ // The parent of the destination is not a directory.
callback.Run(FILE_ERROR_NOT_A_DIRECTORY);
return;
}
- const std::string& src_id = src_dest_info->first.entry->resource_id();
- const base::FilePath& src_path = src_dest_info->first.path;
- const base::FilePath new_name = dest_file_path.BaseName();
- const bool new_name_has_hosted_extension =
- src_dest_info->first.entry->has_file_specific_info() &&
- src_dest_info->first.entry->file_specific_info().is_hosted_document() &&
- new_name.Extension() ==
- src_dest_info->first.entry->file_specific_info().document_extension();
-
- Rename(src_id, src_path, new_name, new_name_has_hosted_extension,
+ // Strip the extension for a hosted document if necessary.
+ const bool has_hosted_document_extension =
+ src_entry->has_file_specific_info() &&
+ src_entry->file_specific_info().is_hosted_document() &&
+ dest_file_path.Extension() ==
+ src_entry->file_specific_info().document_extension();
+ const std::string new_title =
+ has_hosted_document_extension ?
+ dest_file_path.BaseName().RemoveExtension().AsUTF8Unsafe() :
+ dest_file_path.BaseName().AsUTF8Unsafe();
+
+ // TODO(hidehiko): On Drive API v2, we can move a resource by only one
+ // server request. Implement here. crbug.com/241814
+
+ ResourceEntry* src_entry_ptr = src_entry.get();
+ Rename(*src_entry_ptr, new_title,
base::Bind(&MoveOperation::MoveAfterRename,
weak_ptr_factory_.GetWeakPtr(),
- callback,
- base::Passed(&src_dest_info)));
+ src_file_path, dest_file_path, callback,
+ base::Passed(&src_entry),
+ base::Passed(&dest_parent_entry)));
}
void MoveOperation::MoveAfterRename(
+ const base::FilePath& src_file_path,
+ const base::FilePath& dest_file_path,
const FileOperationCallback& callback,
- scoped_ptr<EntryInfoPairResult> src_dest_info,
- FileError error,
- const base::FilePath& src_path) {
+ scoped_ptr<ResourceEntry> src_entry,
+ scoped_ptr<ResourceEntry> dest_parent_entry,
+ FileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!callback.is_null());
if (error != FILE_ERROR_OK) {
callback.Run(error);
return;
}
- const std::string& src_id = src_dest_info->first.entry->resource_id();
- const std::string& dest_dir_id = src_dest_info->second.entry->resource_id();
- const base::FilePath& dest_dir_path = src_dest_info->second.path;
-
// The source and the destination directory are the same. Nothing more to do.
- if (src_path.DirName() == dest_dir_path) {
- observer_->OnDirectoryChangedByOperation(dest_dir_path);
+ if (src_entry->parent_resource_id() == dest_parent_entry->resource_id()) {
+ observer_->OnDirectoryChangedByOperation(dest_file_path.DirName());
callback.Run(FILE_ERROR_OK);
return;
}
- AddToDirectory(src_id, dest_dir_id, src_path, dest_dir_path,
+ AddToDirectory(src_entry->resource_id(),
+ dest_parent_entry->resource_id(),
base::Bind(&MoveOperation::MoveAfterAddToDirectory,
weak_ptr_factory_.GetWeakPtr(),
- callback,
- base::Passed(&src_dest_info)));
+ src_file_path, dest_file_path, callback,
+ src_entry->resource_id(),
+ src_entry->parent_resource_id()));
}
void MoveOperation::MoveAfterAddToDirectory(
+ const base::FilePath& src_file_path,
+ const base::FilePath& dest_file_path,
const FileOperationCallback& callback,
- scoped_ptr<EntryInfoPairResult> src_dest_info,
- FileError error,
- const base::FilePath& new_path) {
+ const std::string& resource_id,
+ const std::string& parent_resource_id,
+ FileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!callback.is_null());
if (error != FILE_ERROR_OK) {
callback.Run(error);
return;
}
- const base::FilePath& src_path = src_dest_info->first.path;
- observer_->OnDirectoryChangedByOperation(src_path.DirName());
- observer_->OnDirectoryChangedByOperation(new_path.DirName());
+ // Notify to the observers.
+ observer_->OnDirectoryChangedByOperation(src_file_path.DirName());
+ observer_->OnDirectoryChangedByOperation(dest_file_path.DirName());
- RemoveFromDirectory(src_dest_info->first.entry->resource_id(),
- src_dest_info->first.entry->parent_resource_id(),
- callback);
+ RemoveFromDirectory(resource_id, parent_resource_id, callback);
}
-void MoveOperation::Rename(const std::string& src_id,
- const base::FilePath& src_path,
- const base::FilePath& new_name,
- bool new_name_has_hosted_extension,
- const FileMoveCallback& callback) {
+void MoveOperation::Rename(const ResourceEntry& entry,
+ const std::string& new_title,
+ const FileOperationCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!callback.is_null());
- // It is a no-op if the file is renamed to the same name.
- if (src_path.BaseName() == new_name) {
- callback.Run(FILE_ERROR_OK, src_path);
+ if (entry.title() == new_title) {
+ // We have nothing to do.
+ callback.Run(FILE_ERROR_OK);
return;
}
- // Drop the .g<something> extension from |new_name| if the file being
- // renamed is a hosted document and |new_name| has the same .g<something>
- // extension as the file.
- const std::string new_title = new_name_has_hosted_extension ?
- new_name.RemoveExtension().AsUTF8Unsafe() :
- new_name.AsUTF8Unsafe();
-
- // Rename on the server.
- scheduler_->RenameResource(src_id,
- new_title,
- base::Bind(&MoveOperation::RenameLocally,
- weak_ptr_factory_.GetWeakPtr(),
- src_path,
- new_title,
- callback));
+ // Send a rename request to the server.
+ scheduler_->RenameResource(
+ entry.resource_id(),
+ new_title,
+ base::Bind(&MoveOperation::RenameAfterRenameResource,
+ weak_ptr_factory_.GetWeakPtr(),
+ entry.resource_id(), new_title, callback));
}
-void MoveOperation::RenameLocally(const base::FilePath& src_path,
- const std::string& new_title,
- const FileMoveCallback& callback,
- google_apis::GDataErrorCode status) {
+void MoveOperation::RenameAfterRenameResource(
+ const std::string& resource_id,
+ const std::string& new_title,
+ const FileOperationCallback& callback,
+ google_apis::GDataErrorCode status) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!callback.is_null());
const FileError error = GDataToFileError(status);
if (error != FILE_ERROR_OK) {
- callback.Run(error, base::FilePath());
+ callback.Run(error);
return;
}
- metadata_->RenameEntryOnUIThread(src_path, new_title, callback);
+
+ // Server side renaming is done. Update the local metadata.
+ base::PostTaskAndReplyWithResult(
+ blocking_task_runner_.get(),
+ FROM_HERE,
+ base::Bind(&RenameLocally, metadata_, resource_id, new_title),
+ callback);
}
-void MoveOperation::AddToDirectory(const std::string& src_id,
- const std::string& dest_dir_id,
- const base::FilePath& src_path,
- const base::FilePath& dest_dir_path,
- const FileMoveCallback& callback) {
+void MoveOperation::AddToDirectory(
+ const std::string& resource_id,
+ const std::string& parent_resource_id,
+ const FileOperationCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!callback.is_null());
scheduler_->AddResourceToDirectory(
- dest_dir_id, src_id,
- base::Bind(&MoveOperation::AddToDirectoryLocally,
+ parent_resource_id, resource_id,
+ base::Bind(&MoveOperation::AddToDirectoryAfterAddResourceToDirectory,
weak_ptr_factory_.GetWeakPtr(),
- src_path,
- dest_dir_path,
- callback));
+ resource_id, parent_resource_id, callback));
}
-void MoveOperation::AddToDirectoryLocally(const base::FilePath& src_path,
- const base::FilePath& dest_dir_path,
- const FileMoveCallback& callback,
- google_apis::GDataErrorCode status) {
+void MoveOperation::AddToDirectoryAfterAddResourceToDirectory(
+ const std::string& resource_id,
+ const std::string& parent_resource_id,
+ const FileOperationCallback& callback,
+ google_apis::GDataErrorCode status) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!callback.is_null());
const FileError error = GDataToFileError(status);
if (error != FILE_ERROR_OK) {
- callback.Run(error, base::FilePath());
+ callback.Run(error);
return;
}
- metadata_->MoveEntryToDirectoryOnUIThread(src_path, dest_dir_path, callback);
+
+ // Server side moving is done. Update the local metadata.
+ base::PostTaskAndReplyWithResult(
+ blocking_task_runner_.get(),
+ FROM_HERE,
+ base::Bind(&MoveDirectoryLocally,
+ metadata_, resource_id, parent_resource_id),
+ callback);
}
void MoveOperation::RemoveFromDirectory(
@@ -211,6 +292,7 @@ void MoveOperation::RemoveFromDirectory(
const std::string& directory_resource_id,
const FileOperationCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!callback.is_null());
// Moving files out from "drive/other" special folder for storing orphan files
// has no meaning in the server. Just skip the step.
@@ -222,15 +304,16 @@ void MoveOperation::RemoveFromDirectory(
scheduler_->RemoveResourceFromDirectory(
directory_resource_id,
resource_id,
- base::Bind(&MoveOperation::RemoveFromDirectoryCompleted,
- weak_ptr_factory_.GetWeakPtr(),
- callback));
+ base::Bind(
+ &MoveOperation::RemoveFromDirectoryAfterRemoveResourceFromDirectory,
+ weak_ptr_factory_.GetWeakPtr(), callback));
}
-void MoveOperation::RemoveFromDirectoryCompleted(
+void MoveOperation::RemoveFromDirectoryAfterRemoveResourceFromDirectory(
const FileOperationCallback& callback,
google_apis::GDataErrorCode status) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!callback.is_null());
callback.Run(GDataToFileError(status));
}

Powered by Google App Engine
This is Rietveld 408576698