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

Unified Diff: chrome/browser/chromeos/gdata/gdata_file_system.cc

Issue 9662041: Implement copy and move operations within the same remote file system. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/gdata/gdata_file_system.cc
===================================================================
--- chrome/browser/chromeos/gdata/gdata_file_system.cc (revision 126271)
+++ chrome/browser/chromeos/gdata/gdata_file_system.cc (working copy)
@@ -14,16 +14,15 @@
#include "base/platform_file.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/profiles/profile_dependency_manager.h"
#include "chrome/browser/chromeos/gdata/gdata.h"
#include "chrome/browser/chromeos/gdata/gdata_download_observer.h"
#include "chrome/browser/chromeos/gdata/gdata_parser.h"
-#include "chrome/common/chrome_constants.h"
-#include "chrome/common/chrome_paths_internal.h"
#include "chrome/browser/download/download_service.h"
#include "chrome/browser/download/download_service_factory.h"
+#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_dependency_manager.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_paths_internal.h"
#include "content/public/browser/browser_thread.h"
#include "webkit/fileapi/file_system_file_util_proxy.h"
#include "webkit/fileapi/file_system_types.h"
@@ -535,7 +534,17 @@
GDataFileSystem::CreateDirectoryParams::~CreateDirectoryParams() {
}
+// GDataFileSystem::CopyMoveFileParams struct implementation.
+GDataFileSystem::CopyMoveFileParams::CopyMoveFileParams()
+ : is_directory(false),
+ is_root_directory(false),
+ is_hosted_document(false) {
+}
+
+GDataFileSystem::CopyMoveFileParams::~CopyMoveFileParams() {
+}
+
// GDataFileSystem class implementatsion.
GDataFileSystem::GDataFileSystem(Profile* profile,
@@ -608,6 +617,247 @@
ContinueDirectoryRefresh(params, feed_list.Pass());
}
+bool GDataFileSystem::GetCopyMoveFileParams(const FilePath& path,
+ CopyMoveFileParams* params) {
+ DCHECK(params);
+
+ scoped_refptr<ReadOnlyFindFileDelegate> delegate(
+ new ReadOnlyFindFileDelegate());
+
+ base::AutoLock lock(lock_);
+
+ UnsafeFindFileByPath(path, delegate);
+ GDataFileBase* file = delegate->file();
+ if (!file)
+ return false;
+
+ params->resource_id = file->resource_id();
+ params->self_url = file->self_url();
+ params->content_url = file->content_url();
+ params->is_directory = file->AsGDataDirectory();
+ params->is_root_directory = file->AsGDataRootDirectory();
+
+ GDataFile* gdata_file = file->AsGDataFile();
+ if (gdata_file) {
+ params->is_hosted_document = gdata_file->is_hosted_document();
+ params->document_extension = gdata_file->document_extension();
+ }
+
+ return true;
+}
+
+void GDataFileSystem::Copy(const FilePath& src_file_path,
+ const FilePath& dest_file_path,
+ const FileOperationCallback& callback) {
+ base::PlatformFileError error = base::PLATFORM_FILE_OK;
+ FilePath dest_parent_path = dest_file_path.DirName();
+ CopyMoveFileParams src_file_params, dest_parent_params;
+ if (!GetCopyMoveFileParams(src_file_path, &src_file_params) ||
+ !GetCopyMoveFileParams(dest_parent_path, &dest_parent_params)) {
+ error = base::PLATFORM_FILE_ERROR_NOT_FOUND;
+ } else {
+ // TODO(benchan): Implement copy for regular files and directories.
+ // To copy a regular file, we need to first download the file and
+ // then upload it, which is not yet implemented. Also, in the interim,
+ // we handle recursive directory copy in the file manager.
+ if (!src_file_params.is_hosted_document) {
+ error = base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
+ } else if (!dest_parent_params.is_directory) {
+ error = base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
+ }
+ }
+
+ if (error != base::PLATFORM_FILE_OK) {
+ if (!callback.is_null())
+ MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, error));
+
+ return;
+ }
+
+ FilePathUpdateCallback add_file_to_directory_callback =
+ base::Bind(&GDataFileSystem::AddFileToDirectory,
+ weak_ptr_factory_.GetWeakPtr(),
+ dest_parent_path,
+ callback);
+
+ documents_service_->CopyDocument(
+ src_file_params.self_url,
+ // Drop the document extension, which should not be in the document title.
+ dest_file_path.BaseName().RemoveExtension().value(),
+ base::Bind(&GDataFileSystem::OnCopyDocumentCompleted,
+ weak_ptr_factory_.GetWeakPtr(),
+ add_file_to_directory_callback));
+}
+
+void GDataFileSystem::Rename(const FilePath& file_path,
+ const FilePath::StringType& new_name,
+ const FilePathUpdateCallback& callback) {
+ // It is a no-op if the file is renamed to the same name.
+ if (file_path.BaseName().value() == new_name) {
+ if (!callback.is_null()) {
+ MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(callback, base::PLATFORM_FILE_OK, file_path));
+ }
+ return;
+ }
+
+ CopyMoveFileParams file_params;
+ if (!GetCopyMoveFileParams(file_path, &file_params)) {
+ if (!callback.is_null()) {
+ MessageLoop::current()->PostTask(FROM_HERE,
+ base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND, file_path));
+ }
+ 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.
+ FilePath::StringType file_name = new_name;
+ if (file_params.is_hosted_document) {
+ FilePath new_file(file_name);
+ if (new_file.Extension() == file_params.document_extension) {
+ file_name = new_file.RemoveExtension().value();
+ }
+ }
+
+ documents_service_->RenameResource(
+ file_params.self_url,
+ file_name,
+ base::Bind(&GDataFileSystem::OnRenameResourceCompleted,
+ weak_ptr_factory_.GetWeakPtr(),
+ file_path,
+ file_name,
+ callback));
+}
+
+void GDataFileSystem::Move(const FilePath& src_file_path,
+ const FilePath& dest_file_path,
+ const FileOperationCallback& callback) {
+ base::PlatformFileError error = base::PLATFORM_FILE_OK;
+ FilePath dest_parent_path = dest_file_path.DirName();
+ CopyMoveFileParams src_file_params, dest_parent_params;
+ if (!GetCopyMoveFileParams(src_file_path, &src_file_params) ||
+ !GetCopyMoveFileParams(dest_parent_path, &dest_parent_params)) {
+ error = base::PLATFORM_FILE_ERROR_NOT_FOUND;
+ } else {
+ if (!dest_parent_params.is_directory)
+ error = base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
+ }
+
+ if (error != base::PLATFORM_FILE_OK) {
+ if (!callback.is_null())
+ MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, error));
+
+ return;
+ }
+
+ // If the file/directory is moved to the same directory, just rename it.
+ if (src_file_path.DirName() == dest_parent_path) {
+ FilePathUpdateCallback final_file_path_update_callback =
+ base::Bind(&GDataFileSystem::OnFilePathUpdated,
+ weak_ptr_factory_.GetWeakPtr(),
+ callback);
+
+ Rename(src_file_path, dest_file_path.BaseName().value(),
+ final_file_path_update_callback);
+ return;
+ }
+
+ // Otherwise, the move operation involves three steps:
+ // 1. Renames the file at |src_file_path| to basename(|dest_file_path|)
+ // within the same directory. The rename operation is a no-op if
+ // basename(|src_file_path|) equals to basename(|dest_file_path|).
+ // 2. Removes the file from its parent directory (the file is not deleted),
+ // which effectively moves the file to the root directory.
+ // 3. Adds the file to the parent directory of |dest_file_path|, which
+ // effectively moves the file from the root directory to the parent
+ // directory of |dest_file_path|.
satorux1 2012/03/13 01:12:17 Thank you for adding this!
+ FilePathUpdateCallback add_file_to_directory_callback =
+ base::Bind(&GDataFileSystem::AddFileToDirectory,
+ weak_ptr_factory_.GetWeakPtr(),
+ dest_file_path.DirName(),
+ callback);
+
+ FilePathUpdateCallback remove_file_from_directory_callback =
+ base::Bind(&GDataFileSystem::RemoveFileFromDirectory,
+ weak_ptr_factory_.GetWeakPtr(),
+ src_file_path.DirName(),
+ add_file_to_directory_callback);
+
+ Rename(src_file_path, dest_file_path.BaseName().value(),
+ remove_file_from_directory_callback);
+}
+
+void GDataFileSystem::AddFileToDirectory(const FilePath& dir_path,
+ const FileOperationCallback& callback,
+ base::PlatformFileError error,
+ const FilePath& file_path) {
+ CopyMoveFileParams file_params, dir_params;
+ if (error == base::PLATFORM_FILE_OK) {
+ if (!GetCopyMoveFileParams(file_path, &file_params) ||
+ !GetCopyMoveFileParams(dir_path, &dir_params)) {
+ error = base::PLATFORM_FILE_ERROR_NOT_FOUND;
+ } else {
+ if (!dir_params.is_directory)
+ error = base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
+ }
+ }
+
+ // Returns if there is an error or |dir_path| is the root directory.
+ if (error != base::PLATFORM_FILE_OK || dir_params.is_root_directory) {
+ if (!callback.is_null())
+ MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, error));
+
+ return;
+ }
+
+ documents_service_->AddResourceToDirectory(
+ dir_params.content_url,
+ file_params.self_url,
+ base::Bind(&GDataFileSystem::OnAddFileToDirectoryCompleted,
+ weak_ptr_factory_.GetWeakPtr(),
+ callback,
+ file_path,
+ dir_path));
+}
+
+void GDataFileSystem::RemoveFileFromDirectory(
+ const FilePath& dir_path,
+ const FilePathUpdateCallback& callback,
+ base::PlatformFileError error,
+ const FilePath& file_path) {
+ CopyMoveFileParams file_params, dir_params;
+ if (error == base::PLATFORM_FILE_OK) {
+ if (!GetCopyMoveFileParams(file_path, &file_params) ||
+ !GetCopyMoveFileParams(dir_path, &dir_params)) {
+ error = base::PLATFORM_FILE_ERROR_NOT_FOUND;
+ } else {
+ if (!dir_params.is_directory)
+ error = base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
+ }
+ }
+
+ // Returns if there is an error or |dir_path| is the root directory.
+ if (error != base::PLATFORM_FILE_OK || dir_params.is_root_directory) {
+ if (!callback.is_null()) {
+ MessageLoop::current()->PostTask(FROM_HERE,
+ base::Bind(callback, error, file_path));
+ }
+ return;
+ }
+
+ documents_service_->RemoveResourceFromDirectory(
+ dir_params.content_url,
+ file_params.self_url,
+ file_params.resource_id,
+ base::Bind(&GDataFileSystem::OnRemoveFileFromDirectoryCompleted,
+ weak_ptr_factory_.GetWeakPtr(),
+ callback,
+ file_path,
+ dir_path));
+}
+
void GDataFileSystem::Remove(const FilePath& file_path,
bool is_recursive,
const FileOperationCallback& callback) {
@@ -873,7 +1123,7 @@
return cache_file_path;
GDataFile* file = file_base->AsGDataFile();
- resource = file->resource();
+ resource = file->resource_id();
md5 = file->file_md5();
}
@@ -999,6 +1249,109 @@
params.delegate);
}
+void GDataFileSystem::OnFilePathUpdated(const FileOperationCallback& callback,
+ base::PlatformFileError error,
+ const FilePath& file_path) {
+ if (!callback.is_null())
+ callback.Run(error);
+}
+
+void GDataFileSystem::OnRenameResourceCompleted(
+ const FilePath& file_path,
+ const FilePath::StringType& new_name,
+ const FilePathUpdateCallback& callback,
+ GDataErrorCode status,
+ const GURL& document_url) {
+ FilePath updated_file_path;
+ base::PlatformFileError error = GDataToPlatformError(status);
+ if (error == base::PLATFORM_FILE_OK)
+ error = RenameFileOnFilesystem(file_path, new_name, &updated_file_path);
+
+ if (!callback.is_null())
+ callback.Run(error, updated_file_path);
+}
+
+void GDataFileSystem::OnCopyDocumentCompleted(
+ const FilePathUpdateCallback& callback,
+ GDataErrorCode status,
+ scoped_ptr<base::Value> data) {
+ base::PlatformFileError error = GDataToPlatformError(status);
+ if (error != base::PLATFORM_FILE_OK) {
+ if (!callback.is_null())
+ callback.Run(error, FilePath());
+
+ return;
+ }
+
+ base::DictionaryValue* dict_value = NULL;
+ base::Value* entry_value = NULL;
+ if (data.get() && data->GetAsDictionary(&dict_value) && dict_value)
+ dict_value->Get("entry", &entry_value);
+
+ if (!entry_value) {
+ if (!callback.is_null())
+ callback.Run(base::PLATFORM_FILE_ERROR_FAILED, FilePath());
+
+ return;
+ }
+
+ scoped_ptr<DocumentEntry> entry(DocumentEntry::CreateFrom(entry_value));
+ if (!entry.get()) {
+ if (!callback.is_null())
+ callback.Run(base::PLATFORM_FILE_ERROR_FAILED, FilePath());
+
+ return;
+ }
+
+ FilePath file_path;
+ {
+ base::AutoLock lock(lock_);
+ GDataFileBase* file =
+ GDataFileBase::FromDocumentEntry(root_.get(), entry.get());
+ if (!file) {
+ if (!callback.is_null())
+ callback.Run(base::PLATFORM_FILE_ERROR_FAILED, FilePath());
+
+ return;
+ }
+ root_->AddFile(file);
+ file_path = file->GetFilePath();
+ }
+
+ if (!callback.is_null())
+ callback.Run(error, file_path);
+}
+
+void GDataFileSystem::OnAddFileToDirectoryCompleted(
+ const FileOperationCallback& callback,
+ const FilePath& file_path,
+ const FilePath& dir_path,
+ GDataErrorCode status,
+ const GURL& document_url) {
+ base::PlatformFileError error = GDataToPlatformError(status);
+ if (error == base::PLATFORM_FILE_OK)
+ error = AddFileToDirectoryOnFilesystem(file_path, dir_path);
+
+ if (!callback.is_null())
+ callback.Run(error);
+}
+
+void GDataFileSystem::OnRemoveFileFromDirectoryCompleted(
+ const FilePathUpdateCallback& callback,
+ const FilePath& file_path,
+ const FilePath& dir_path,
+ GDataErrorCode status,
+ const GURL& document_url) {
+ FilePath updated_file_path = file_path;
+ base::PlatformFileError error = GDataToPlatformError(status);
+ if (error == base::PLATFORM_FILE_OK)
+ error = RemoveFileFromDirectoryOnFilesystem(file_path, dir_path,
+ &updated_file_path);
+
+ if (!callback.is_null())
+ callback.Run(error, updated_file_path);
+}
+
void GDataFileSystem::SaveRootFeeds(scoped_ptr<base::ListValue> feed_vector) {
BrowserThread::PostBlockingPoolTask(FROM_HERE,
base::Bind(&GDataFileSystem::SaveRootFeedsOnIOThreadPool,
@@ -1063,6 +1416,98 @@
}
}
+base::PlatformFileError GDataFileSystem::RenameFileOnFilesystem(
+ const FilePath& file_path,
+ const FilePath::StringType& new_name,
+ FilePath* updated_file_path) {
+ DCHECK(updated_file_path);
+
+ base::AutoLock lock(lock_);
+
+ scoped_refptr<ReadOnlyFindFileDelegate> find_file_delegate(
+ new ReadOnlyFindFileDelegate());
+ UnsafeFindFileByPath(file_path, find_file_delegate);
+
+ GDataFileBase* file = find_file_delegate->file();
+ if (!file)
+ return base::PLATFORM_FILE_ERROR_NOT_FOUND;
+
+ DCHECK(file->parent());
+ file->set_original_file_name(new_name);
+ // After changing the original file name, call TakeFile() to remove the
+ // file from its parent directory and then add it back in order to go
+ // through the file name de-duplication.
+ if (!file->parent()->TakeFile(file))
+ return base::PLATFORM_FILE_ERROR_FAILED;
+
+ *updated_file_path = file->GetFilePath();
+ return base::PLATFORM_FILE_OK;
+}
+
+base::PlatformFileError GDataFileSystem::AddFileToDirectoryOnFilesystem(
+ const FilePath& file_path, const FilePath& dir_path) {
+ base::AutoLock lock(lock_);
+
+ scoped_refptr<ReadOnlyFindFileDelegate> find_file_delegate(
+ new ReadOnlyFindFileDelegate());
+ UnsafeFindFileByPath(file_path, find_file_delegate);
+
+ GDataFileBase* file = find_file_delegate->file();
+ if (!file)
+ return base::PLATFORM_FILE_ERROR_NOT_FOUND;
+
+ DCHECK_EQ(root_.get(), file->parent());
+
+ scoped_refptr<ReadOnlyFindFileDelegate> find_dir_delegate(
+ new ReadOnlyFindFileDelegate());
+ UnsafeFindFileByPath(dir_path, find_dir_delegate);
+ GDataFileBase* dir = find_dir_delegate->file();
+ if (!dir)
+ return base::PLATFORM_FILE_ERROR_NOT_FOUND;
+
+ if (!dir->AsGDataDirectory())
+ return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
+
+ if (!dir->AsGDataDirectory()->TakeFile(file))
+ return base::PLATFORM_FILE_ERROR_FAILED;
+
+ return base::PLATFORM_FILE_OK;
+}
+
+base::PlatformFileError GDataFileSystem::RemoveFileFromDirectoryOnFilesystem(
+ const FilePath& file_path, const FilePath& dir_path,
+ FilePath* updated_file_path) {
+ DCHECK(updated_file_path);
+
+ base::AutoLock lock(lock_);
+
+ scoped_refptr<ReadOnlyFindFileDelegate> find_file_delegate(
+ new ReadOnlyFindFileDelegate());
+ UnsafeFindFileByPath(file_path, find_file_delegate);
+
+ GDataFileBase* file = find_file_delegate->file();
+ if (!file)
+ return base::PLATFORM_FILE_ERROR_NOT_FOUND;
+
+ scoped_refptr<ReadOnlyFindFileDelegate> find_dir_delegate(
+ new ReadOnlyFindFileDelegate());
+ UnsafeFindFileByPath(dir_path, find_dir_delegate);
+ GDataFileBase* dir = find_dir_delegate->file();
+ if (!dir)
+ return base::PLATFORM_FILE_ERROR_NOT_FOUND;
+
+ if (!dir->AsGDataDirectory())
+ return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
+
+ DCHECK_EQ(dir->AsGDataDirectory(), file->parent());
+
+ if (!root_->TakeFile(file))
+ return base::PLATFORM_FILE_ERROR_FAILED;
+
+ *updated_file_path = file->GetFilePath();
+ return base::PLATFORM_FILE_OK;
+}
+
base::PlatformFileError GDataFileSystem::RemoveFileFromFileSystem(
const FilePath& file_path) {
// We need to lock here as well (despite FindFileByPath lock) since directory
@@ -1081,7 +1526,7 @@
// If it's a file (only files have resource), remove it from cache.
if (file->AsGDataFile()) {
- RemoveFromCache(file->AsGDataFile()->resource(),
+ RemoveFromCache(file->AsGDataFile()->resource_id(),
base::Bind(&GDataFileSystem::OnRemovedFromCache,
weak_ptr_factory_.GetWeakPtr()));
}
« no previous file with comments | « chrome/browser/chromeos/gdata/gdata_file_system.h ('k') | chrome/browser/chromeos/gdata/gdata_file_system_proxy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698