| Index: chrome/browser/chromeos/gdata/gdata_file_system.cc
|
| ===================================================================
|
| --- chrome/browser/chromeos/gdata/gdata_file_system.cc (revision 126358)
|
| +++ 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,6 @@
|
| GDataFileSystem::CreateDirectoryParams::~CreateDirectoryParams() {
|
| }
|
|
|
| -
|
| // GDataFileSystem class implementatsion.
|
|
|
| GDataFileSystem::GDataFileSystem(Profile* profile,
|
| @@ -608,6 +606,230 @@
|
| ContinueDirectoryRefresh(params, feed_list.Pass());
|
| }
|
|
|
| +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();
|
| +
|
| + base::AutoLock lock(lock_);
|
| + GDataFileBase* src_file = GetGDataFileInfoFromPath(src_file_path);
|
| + GDataFileBase* dest_parent = GetGDataFileInfoFromPath(dest_parent_path);
|
| + if (!src_file || !dest_parent) {
|
| + 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->AsGDataFile() ||
|
| + !src_file->AsGDataFile()->is_hosted_document()) {
|
| + error = base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
|
| + } else if (!dest_parent->AsGDataDirectory()) {
|
| + 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->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;
|
| + }
|
| +
|
| + base::AutoLock lock(lock_);
|
| + GDataFileBase* file = GetGDataFileInfoFromPath(file_path);
|
| + if (!file) {
|
| + 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->AsGDataFile() && file->AsGDataFile()->is_hosted_document()) {
|
| + FilePath new_file(file_name);
|
| + if (new_file.Extension() == file->AsGDataFile()->document_extension()) {
|
| + file_name = new_file.RemoveExtension().value();
|
| + }
|
| + }
|
| +
|
| + documents_service_->RenameResource(
|
| + file->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();
|
| +
|
| + {
|
| + // This scoped lock needs to be released before calling Rename() below.
|
| + base::AutoLock lock(lock_);
|
| + GDataFileBase* src_file = GetGDataFileInfoFromPath(src_file_path);
|
| + GDataFileBase* dest_parent = GetGDataFileInfoFromPath(dest_parent_path);
|
| + if (!src_file || !dest_parent) {
|
| + error = base::PLATFORM_FILE_ERROR_NOT_FOUND;
|
| + } else {
|
| + if (!dest_parent->AsGDataDirectory())
|
| + 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|.
|
| + 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) {
|
| + base::AutoLock lock(lock_);
|
| + GDataFileBase* file = GetGDataFileInfoFromPath(file_path);
|
| + GDataFileBase* dir = GetGDataFileInfoFromPath(dir_path);
|
| + if (error == base::PLATFORM_FILE_OK) {
|
| + if (!file || !dir) {
|
| + error = base::PLATFORM_FILE_ERROR_NOT_FOUND;
|
| + } else {
|
| + if (!dir->AsGDataDirectory())
|
| + 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->AsGDataRootDirectory()) {
|
| + if (!callback.is_null())
|
| + MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, error));
|
| +
|
| + return;
|
| + }
|
| +
|
| + documents_service_->AddResourceToDirectory(
|
| + dir->content_url(),
|
| + file->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) {
|
| + base::AutoLock lock(lock_);
|
| + GDataFileBase* file = GetGDataFileInfoFromPath(file_path);
|
| + GDataFileBase* dir = GetGDataFileInfoFromPath(dir_path);
|
| + if (error == base::PLATFORM_FILE_OK) {
|
| + if (!file || !dir) {
|
| + error = base::PLATFORM_FILE_ERROR_NOT_FOUND;
|
| + } else {
|
| + if (!dir->AsGDataDirectory())
|
| + 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->AsGDataRootDirectory()) {
|
| + if (!callback.is_null()) {
|
| + MessageLoop::current()->PostTask(FROM_HERE,
|
| + base::Bind(callback, error, file_path));
|
| + }
|
| + return;
|
| + }
|
| +
|
| + documents_service_->RemoveResourceFromDirectory(
|
| + dir->content_url(),
|
| + file->self_url(),
|
| + file->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) {
|
| @@ -999,6 +1221,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 +1388,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_title(new_name);
|
| + // After changing the title of the file, 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
|
|
|