| // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/drive/chromeos/fake_file_system.h" |
| |
| #include <stddef.h> |
| |
| #include <memory> |
| #include <set> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| #include "base/callback.h" |
| #include "base/files/file_path.h" |
| #include "base/files/file_util.h" |
| #include "base/logging.h" |
| #include "components/drive/drive.pb.h" |
| #include "components/drive/file_errors.h" |
| #include "components/drive/file_system_core_util.h" |
| #include "components/drive/resource_entry_conversion.h" |
| #include "components/drive/service/drive_service_interface.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "google_apis/drive/drive_api_parser.h" |
| |
| namespace drive { |
| namespace test_util { |
| |
| using content::BrowserThread; |
| |
| FakeFileSystem::FakeFileSystem(DriveServiceInterface* drive_service) |
| : drive_service_(drive_service) { |
| CHECK(cache_dir_.CreateUniqueTempDir()); |
| } |
| |
| FakeFileSystem::~FakeFileSystem() = default; |
| |
| void FakeFileSystem::AddObserver(FileSystemObserver* observer) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::RemoveObserver(FileSystemObserver* observer) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::CheckForUpdates() { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::CheckForUpdates(const std::set<std::string>& ids) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::TransferFileFromLocalToRemote( |
| const base::FilePath& local_src_file_path, |
| const base::FilePath& remote_dest_file_path, |
| const FileOperationCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::OpenFile(const base::FilePath& file_path, |
| OpenMode open_mode, |
| const std::string& mime_type, |
| OpenFileCallback callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::Copy(const base::FilePath& src_file_path, |
| const base::FilePath& dest_file_path, |
| bool preserve_last_modified, |
| const FileOperationCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::Move(const base::FilePath& src_file_path, |
| const base::FilePath& dest_file_path, |
| const FileOperationCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::Remove(const base::FilePath& file_path, |
| bool is_recursive, |
| const FileOperationCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::CreateDirectory( |
| const base::FilePath& directory_path, |
| bool is_exclusive, |
| bool is_recursive, |
| const FileOperationCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::CreateFile(const base::FilePath& file_path, |
| bool is_exclusive, |
| const std::string& mime_type, |
| const FileOperationCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::TouchFile(const base::FilePath& file_path, |
| const base::Time& last_access_time, |
| const base::Time& last_modified_time, |
| const FileOperationCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::TruncateFile(const base::FilePath& file_path, |
| int64_t length, |
| const FileOperationCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::Pin(const base::FilePath& file_path, |
| const FileOperationCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::Unpin(const base::FilePath& file_path, |
| const FileOperationCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::GetFile(const base::FilePath& file_path, |
| GetFileCallback callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::GetFileForSaving(const base::FilePath& file_path, |
| GetFileCallback callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::IsCacheFileMarkedAsMounted( |
| const base::FilePath& drive_file_path, |
| IsMountedCallback callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| base::Closure FakeFileSystem::GetFileContent( |
| const base::FilePath& file_path, |
| GetFileContentInitializedCallback initialized_callback, |
| const google_apis::GetContentCallback& get_content_callback, |
| const FileOperationCallback& completion_callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| |
| GetResourceEntry( |
| file_path, |
| base::Bind(&FakeFileSystem::GetFileContentAfterGetResourceEntry, |
| weak_ptr_factory_.GetWeakPtr(), |
| base::Passed(std::move(initialized_callback)), |
| get_content_callback, completion_callback)); |
| return base::DoNothing(); |
| } |
| |
| void FakeFileSystem::GetResourceEntry(const base::FilePath& file_path, |
| GetResourceEntryCallback callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| |
| if (file_path == util::GetDriveMyDriveRootPath()) { |
| // Specialized for the root entry. |
| drive_service_->GetAboutResource(base::Bind( |
| &FakeFileSystem::GetResourceEntryAfterGetAboutResource, |
| weak_ptr_factory_.GetWeakPtr(), base::Passed(std::move(callback)))); |
| return; |
| } |
| |
| // Now, we only support files under my drive. |
| DCHECK(util::GetDriveMyDriveRootPath().IsParent(file_path)); |
| GetResourceEntry( |
| file_path.DirName(), |
| base::BindOnce(&FakeFileSystem::GetResourceEntryAfterGetParentEntryInfo, |
| weak_ptr_factory_.GetWeakPtr(), file_path.BaseName(), |
| std::move(callback))); |
| } |
| |
| void FakeFileSystem::ReadDirectory( |
| const base::FilePath& file_path, |
| ReadDirectoryEntriesCallback entries_callback, |
| const FileOperationCallback& completion_callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::Search(const std::string& search_query, |
| const GURL& next_link, |
| SearchCallback callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::SearchMetadata(const std::string& query, |
| int options, |
| int at_most_num_matches, |
| MetadataSearchOrder order, |
| SearchMetadataCallback callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::SearchByHashes(const std::set<std::string>& hashes, |
| SearchByHashesCallback callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::GetAvailableSpace(GetAvailableSpaceCallback callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::GetMetadata(GetFilesystemMetadataCallback callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::MarkCacheFileAsMounted( |
| const base::FilePath& drive_file_path, |
| MarkMountedCallback callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::MarkCacheFileAsUnmounted( |
| const base::FilePath& cache_file_path, |
| const FileOperationCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::AddPermission(const base::FilePath& drive_file_path, |
| const std::string& email, |
| google_apis::drive::PermissionRole role, |
| const FileOperationCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::SetProperty( |
| const base::FilePath& drive_file_path, |
| google_apis::drive::Property::Visibility visibility, |
| const std::string& key, |
| const std::string& value, |
| const FileOperationCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::Reset(const FileOperationCallback& callback) { |
| } |
| |
| void FakeFileSystem::GetPathFromResourceId( |
| const std::string& resource_id, |
| const GetFilePathCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::FreeDiskSpaceIfNeededFor( |
| int64_t num_bytes, |
| const FreeDiskSpaceCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::CalculateCacheSize(const CacheSizeCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| void FakeFileSystem::CalculateEvictableCacheSize( |
| const CacheSizeCallback& callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| } |
| |
| // Implementation of GetFileContent. |
| void FakeFileSystem::GetFileContentAfterGetResourceEntry( |
| GetFileContentInitializedCallback initialized_callback, |
| const google_apis::GetContentCallback& get_content_callback, |
| const FileOperationCallback& completion_callback, |
| FileError error, |
| std::unique_ptr<ResourceEntry> entry) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| |
| if (error != FILE_ERROR_OK) { |
| completion_callback.Run(error); |
| return; |
| } |
| DCHECK(entry); |
| |
| // We're only interested in a file. |
| if (entry->file_info().is_directory()) { |
| completion_callback.Run(FILE_ERROR_NOT_A_FILE); |
| return; |
| } |
| |
| // Fetch google_apis::FileResource for its |download_url|. |
| drive_service_->GetFileResource( |
| entry->resource_id(), |
| base::Bind(&FakeFileSystem::GetFileContentAfterGetFileResource, |
| weak_ptr_factory_.GetWeakPtr(), |
| base::Passed(std::move(initialized_callback)), |
| get_content_callback, completion_callback)); |
| } |
| |
| void FakeFileSystem::GetFileContentAfterGetFileResource( |
| GetFileContentInitializedCallback initialized_callback, |
| const google_apis::GetContentCallback& get_content_callback, |
| const FileOperationCallback& completion_callback, |
| google_apis::DriveApiErrorCode gdata_error, |
| std::unique_ptr<google_apis::FileResource> gdata_entry) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| |
| FileError error = GDataToFileError(gdata_error); |
| if (error != FILE_ERROR_OK) { |
| completion_callback.Run(error); |
| return; |
| } |
| DCHECK(gdata_entry); |
| |
| std::unique_ptr<ResourceEntry> entry(new ResourceEntry); |
| std::string parent_resource_id; |
| ConvertFileResourceToResourceEntry(*gdata_entry, entry.get(), |
| &parent_resource_id); |
| entry->set_parent_local_id(parent_resource_id); |
| |
| base::FilePath cache_path = |
| cache_dir_.GetPath().AppendASCII(entry->resource_id()); |
| if (entry->file_specific_info().is_hosted_document()) { |
| // For hosted documents return a dummy cache without server request. |
| int result = base::WriteFile(cache_path, "", 0); |
| DCHECK_EQ(0, result); |
| } |
| if (base::PathExists(cache_path)) { |
| // Cache file is found. |
| std::move(initialized_callback) |
| .Run(FILE_ERROR_OK, cache_path, std::move(entry)); |
| completion_callback.Run(FILE_ERROR_OK); |
| return; |
| } |
| |
| std::move(initialized_callback) |
| .Run(FILE_ERROR_OK, base::FilePath(), std::move(entry)); |
| drive_service_->DownloadFile( |
| cache_path, |
| gdata_entry->file_id(), |
| base::Bind(&FakeFileSystem::GetFileContentAfterDownloadFile, |
| weak_ptr_factory_.GetWeakPtr(), |
| completion_callback), |
| get_content_callback, |
| google_apis::ProgressCallback()); |
| } |
| |
| void FakeFileSystem::GetFileContentAfterDownloadFile( |
| const FileOperationCallback& completion_callback, |
| google_apis::DriveApiErrorCode gdata_error, |
| const base::FilePath& temp_file) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| completion_callback.Run(GDataToFileError(gdata_error)); |
| } |
| |
| // Implementation of GetResourceEntry. |
| void FakeFileSystem::GetResourceEntryAfterGetAboutResource( |
| GetResourceEntryCallback callback, |
| google_apis::DriveApiErrorCode gdata_error, |
| std::unique_ptr<google_apis::AboutResource> about_resource) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| |
| FileError error = GDataToFileError(gdata_error); |
| if (error != FILE_ERROR_OK) { |
| std::move(callback).Run(error, std::unique_ptr<ResourceEntry>()); |
| return; |
| } |
| |
| DCHECK(about_resource); |
| std::unique_ptr<ResourceEntry> root(new ResourceEntry); |
| root->mutable_file_info()->set_is_directory(true); |
| root->set_resource_id(about_resource->root_folder_id()); |
| root->set_title(util::kDriveMyDriveRootDirName); |
| std::move(callback).Run(error, std::move(root)); |
| } |
| |
| void FakeFileSystem::GetResourceEntryAfterGetParentEntryInfo( |
| const base::FilePath& base_name, |
| GetResourceEntryCallback callback, |
| FileError error, |
| std::unique_ptr<ResourceEntry> parent_entry) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| |
| if (error != FILE_ERROR_OK) { |
| std::move(callback).Run(error, std::unique_ptr<ResourceEntry>()); |
| return; |
| } |
| |
| DCHECK(parent_entry); |
| drive_service_->GetFileListInDirectory( |
| parent_entry->resource_id(), |
| base::Bind(&FakeFileSystem::GetResourceEntryAfterGetFileList, |
| weak_ptr_factory_.GetWeakPtr(), base_name, |
| base::Passed(std::move(callback)))); |
| } |
| |
| void FakeFileSystem::GetResourceEntryAfterGetFileList( |
| const base::FilePath& base_name, |
| GetResourceEntryCallback callback, |
| google_apis::DriveApiErrorCode gdata_error, |
| std::unique_ptr<google_apis::FileList> file_list) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| |
| FileError error = GDataToFileError(gdata_error); |
| if (error != FILE_ERROR_OK) { |
| std::move(callback).Run(error, std::unique_ptr<ResourceEntry>()); |
| return; |
| } |
| |
| DCHECK(file_list); |
| const std::vector<std::unique_ptr<google_apis::FileResource>>& entries = |
| file_list->items(); |
| for (size_t i = 0; i < entries.size(); ++i) { |
| std::unique_ptr<ResourceEntry> entry(new ResourceEntry); |
| std::string parent_resource_id; |
| ConvertFileResourceToResourceEntry(*entries[i], entry.get(), |
| &parent_resource_id); |
| entry->set_parent_local_id(parent_resource_id); |
| |
| if (entry->base_name() == base_name.AsUTF8Unsafe()) { |
| // Found the target entry. |
| std::move(callback).Run(FILE_ERROR_OK, std::move(entry)); |
| return; |
| } |
| } |
| |
| std::move(callback).Run(FILE_ERROR_NOT_FOUND, |
| std::unique_ptr<ResourceEntry>()); |
| } |
| |
| } // namespace test_util |
| } // namespace drive |