1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/chromeos/drive/fake_file_system.h" 6 7 #include "base/bind.h" 8 #include "base/bind_helpers.h" 9 #include "base/callback.h" 10 #include "base/files/file_path.h" 11 #include "base/files/file_util.h" 12 #include "base/logging.h" 13 #include "chrome/browser/chromeos/drive/drive.pb.h" 14 #include "chrome/browser/chromeos/drive/file_errors.h" 15 #include "chrome/browser/chromeos/drive/file_system_util.h" 16 #include "chrome/browser/chromeos/drive/resource_entry_conversion.h" 17 #include "chrome/browser/drive/drive_service_interface.h" 18 #include "content/public/browser/browser_thread.h" 19 #include "google_apis/drive/drive_api_parser.h" 20 21 namespace drive { 22 namespace test_util { 23 24 using content::BrowserThread; 25 26 FakeFileSystem::FakeFileSystem(DriveServiceInterface* drive_service) 27 : drive_service_(drive_service), 28 weak_ptr_factory_(this) { 29 CHECK(cache_dir_.CreateUniqueTempDir()); 30 } 31 32 FakeFileSystem::~FakeFileSystem() { 33 } 34 35 void FakeFileSystem::AddObserver(FileSystemObserver* observer) { 36 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 37 } 38 39 void FakeFileSystem::RemoveObserver(FileSystemObserver* observer) { 40 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 41 } 42 43 void FakeFileSystem::CheckForUpdates() { 44 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 45 } 46 47 void FakeFileSystem::TransferFileFromLocalToRemote( 48 const base::FilePath& local_src_file_path, 49 const base::FilePath& remote_dest_file_path, 50 const FileOperationCallback& callback) { 51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 52 } 53 54 void FakeFileSystem::OpenFile(const base::FilePath& file_path, 55 OpenMode open_mode, 56 const std::string& mime_type, 57 const OpenFileCallback& callback) { 58 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 59 } 60 61 void FakeFileSystem::Copy(const base::FilePath& src_file_path, 62 const base::FilePath& dest_file_path, 63 bool preserve_last_modified, 64 const FileOperationCallback& callback) { 65 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 66 } 67 68 void FakeFileSystem::Move(const base::FilePath& src_file_path, 69 const base::FilePath& dest_file_path, 70 const FileOperationCallback& callback) { 71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 72 } 73 74 void FakeFileSystem::Remove(const base::FilePath& file_path, 75 bool is_recursive, 76 const FileOperationCallback& callback) { 77 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 78 } 79 80 void FakeFileSystem::CreateDirectory( 81 const base::FilePath& directory_path, 82 bool is_exclusive, 83 bool is_recursive, 84 const FileOperationCallback& callback) { 85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 86 } 87 88 void FakeFileSystem::CreateFile(const base::FilePath& file_path, 89 bool is_exclusive, 90 const std::string& mime_type, 91 const FileOperationCallback& callback) { 92 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 93 } 94 95 void FakeFileSystem::TouchFile(const base::FilePath& file_path, 96 const base::Time& last_access_time, 97 const base::Time& last_modified_time, 98 const FileOperationCallback& callback) { 99 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 100 } 101 102 void FakeFileSystem::TruncateFile(const base::FilePath& file_path, 103 int64 length, 104 const FileOperationCallback& callback) { 105 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 106 } 107 108 void FakeFileSystem::Pin(const base::FilePath& file_path, 109 const FileOperationCallback& callback) { 110 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 111 } 112 113 void FakeFileSystem::Unpin(const base::FilePath& file_path, 114 const FileOperationCallback& callback) { 115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 116 } 117 118 void FakeFileSystem::GetFile(const base::FilePath& file_path, 119 const GetFileCallback& callback) { 120 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 121 } 122 123 void FakeFileSystem::GetFileForSaving(const base::FilePath& file_path, 124 const GetFileCallback& callback) { 125 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 126 } 127 128 base::Closure FakeFileSystem::GetFileContent( 129 const base::FilePath& file_path, 130 const GetFileContentInitializedCallback& initialized_callback, 131 const google_apis::GetContentCallback& get_content_callback, 132 const FileOperationCallback& completion_callback) { 133 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 134 135 GetResourceEntry( 136 file_path, 137 base::Bind(&FakeFileSystem::GetFileContentAfterGetResourceEntry, 138 weak_ptr_factory_.GetWeakPtr(), 139 initialized_callback, get_content_callback, 140 completion_callback)); 141 return base::Bind(&base::DoNothing); 142 } 143 144 void FakeFileSystem::GetResourceEntry( 145 const base::FilePath& file_path, 146 const GetResourceEntryCallback& callback) { 147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 148 149 if (file_path == util::GetDriveMyDriveRootPath()) { 150 // Specialized for the root entry. 151 drive_service_->GetAboutResource( 152 base::Bind( 153 &FakeFileSystem::GetResourceEntryAfterGetAboutResource, 154 weak_ptr_factory_.GetWeakPtr(), callback)); 155 return; 156 } 157 158 // Now, we only support files under my drive. 159 DCHECK(util::GetDriveMyDriveRootPath().IsParent(file_path)); 160 GetResourceEntry( 161 file_path.DirName(), 162 base::Bind( 163 &FakeFileSystem::GetResourceEntryAfterGetParentEntryInfo, 164 weak_ptr_factory_.GetWeakPtr(), file_path.BaseName(), callback)); 165 } 166 167 void FakeFileSystem::ReadDirectory( 168 const base::FilePath& file_path, 169 const ReadDirectoryEntriesCallback& entries_callback, 170 const FileOperationCallback& completion_callback) { 171 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 172 } 173 174 void FakeFileSystem::Search(const std::string& search_query, 175 const GURL& next_link, 176 const SearchCallback& callback) { 177 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 178 } 179 180 void FakeFileSystem::SearchMetadata( 181 const std::string& query, 182 int options, 183 int at_most_num_matches, 184 const SearchMetadataCallback& callback) { 185 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 186 } 187 188 void FakeFileSystem::GetAvailableSpace( 189 const GetAvailableSpaceCallback& callback) { 190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 191 } 192 193 void FakeFileSystem::GetShareUrl( 194 const base::FilePath& file_path, 195 const GURL& embed_origin, 196 const GetShareUrlCallback& callback) { 197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 198 } 199 200 void FakeFileSystem::GetMetadata( 201 const GetFilesystemMetadataCallback& callback) { 202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 203 } 204 205 void FakeFileSystem::MarkCacheFileAsMounted( 206 const base::FilePath& drive_file_path, 207 const MarkMountedCallback& callback) { 208 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 209 } 210 211 void FakeFileSystem::MarkCacheFileAsUnmounted( 212 const base::FilePath& cache_file_path, 213 const FileOperationCallback& callback) { 214 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 215 } 216 217 void FakeFileSystem::AddPermission(const base::FilePath& drive_file_path, 218 const std::string& email, 219 google_apis::drive::PermissionRole role, 220 const FileOperationCallback& callback) { 221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 222 } 223 224 void FakeFileSystem::Reset(const FileOperationCallback& callback) { 225 } 226 227 void FakeFileSystem::GetPathFromResourceId( 228 const std::string& resource_id, 229 const GetFilePathCallback& callback) { 230 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 231 } 232 233 // Implementation of GetFileContent. 234 void FakeFileSystem::GetFileContentAfterGetResourceEntry( 235 const GetFileContentInitializedCallback& initialized_callback, 236 const google_apis::GetContentCallback& get_content_callback, 237 const FileOperationCallback& completion_callback, 238 FileError error, 239 scoped_ptr<ResourceEntry> entry) { 240 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 241 242 if (error != FILE_ERROR_OK) { 243 completion_callback.Run(error); 244 return; 245 } 246 DCHECK(entry); 247 248 // We're only interested in a file. 249 if (entry->file_info().is_directory()) { 250 completion_callback.Run(FILE_ERROR_NOT_A_FILE); 251 return; 252 } 253 254 // Fetch google_apis::FileResource for its |download_url|. 255 drive_service_->GetFileResource( 256 entry->resource_id(), 257 base::Bind( 258 &FakeFileSystem::GetFileContentAfterGetFileResource, 259 weak_ptr_factory_.GetWeakPtr(), 260 initialized_callback, 261 get_content_callback, 262 completion_callback)); 263 } 264 265 void FakeFileSystem::GetFileContentAfterGetFileResource( 266 const GetFileContentInitializedCallback& initialized_callback, 267 const google_apis::GetContentCallback& get_content_callback, 268 const FileOperationCallback& completion_callback, 269 google_apis::GDataErrorCode gdata_error, 270 scoped_ptr<google_apis::FileResource> gdata_entry) { 271 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 272 273 FileError error = GDataToFileError(gdata_error); 274 if (error != FILE_ERROR_OK) { 275 completion_callback.Run(error); 276 return; 277 } 278 DCHECK(gdata_entry); 279 280 scoped_ptr<ResourceEntry> entry(new ResourceEntry); 281 std::string parent_resource_id; 282 bool converted = ConvertFileResourceToResourceEntry( 283 *gdata_entry, entry.get(), &parent_resource_id); 284 DCHECK(converted); 285 entry->set_parent_local_id(parent_resource_id); 286 287 base::FilePath cache_path = 288 cache_dir_.path().AppendASCII(entry->resource_id()); 289 if (entry->file_specific_info().is_hosted_document()) { 290 // For hosted documents return a dummy cache without server request. 291 int result = base::WriteFile(cache_path, "", 0); 292 DCHECK_EQ(0, result); 293 } 294 if (base::PathExists(cache_path)) { 295 // Cache file is found. 296 initialized_callback.Run(FILE_ERROR_OK, cache_path, entry.Pass()); 297 completion_callback.Run(FILE_ERROR_OK); 298 return; 299 } 300 301 initialized_callback.Run(FILE_ERROR_OK, base::FilePath(), entry.Pass()); 302 drive_service_->DownloadFile( 303 cache_path, 304 gdata_entry->file_id(), 305 base::Bind(&FakeFileSystem::GetFileContentAfterDownloadFile, 306 weak_ptr_factory_.GetWeakPtr(), 307 completion_callback), 308 get_content_callback, 309 google_apis::ProgressCallback()); 310 } 311 312 void FakeFileSystem::GetFileContentAfterDownloadFile( 313 const FileOperationCallback& completion_callback, 314 google_apis::GDataErrorCode gdata_error, 315 const base::FilePath& temp_file) { 316 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 317 completion_callback.Run(GDataToFileError(gdata_error)); 318 } 319 320 // Implementation of GetResourceEntry. 321 void FakeFileSystem::GetResourceEntryAfterGetAboutResource( 322 const GetResourceEntryCallback& callback, 323 google_apis::GDataErrorCode gdata_error, 324 scoped_ptr<google_apis::AboutResource> about_resource) { 325 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 326 327 FileError error = GDataToFileError(gdata_error); 328 if (error != FILE_ERROR_OK) { 329 callback.Run(error, scoped_ptr<ResourceEntry>()); 330 return; 331 } 332 333 DCHECK(about_resource); 334 scoped_ptr<ResourceEntry> root(new ResourceEntry); 335 root->mutable_file_info()->set_is_directory(true); 336 root->set_resource_id(about_resource->root_folder_id()); 337 root->set_title(util::kDriveMyDriveRootDirName); 338 callback.Run(error, root.Pass()); 339 } 340 341 void FakeFileSystem::GetResourceEntryAfterGetParentEntryInfo( 342 const base::FilePath& base_name, 343 const GetResourceEntryCallback& callback, 344 FileError error, 345 scoped_ptr<ResourceEntry> parent_entry) { 346 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 347 348 if (error != FILE_ERROR_OK) { 349 callback.Run(error, scoped_ptr<ResourceEntry>()); 350 return; 351 } 352 353 DCHECK(parent_entry); 354 drive_service_->GetFileListInDirectory( 355 parent_entry->resource_id(), 356 base::Bind( 357 &FakeFileSystem::GetResourceEntryAfterGetFileList, 358 weak_ptr_factory_.GetWeakPtr(), base_name, callback)); 359 } 360 361 void FakeFileSystem::GetResourceEntryAfterGetFileList( 362 const base::FilePath& base_name, 363 const GetResourceEntryCallback& callback, 364 google_apis::GDataErrorCode gdata_error, 365 scoped_ptr<google_apis::FileList> file_list) { 366 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 367 368 FileError error = GDataToFileError(gdata_error); 369 if (error != FILE_ERROR_OK) { 370 callback.Run(error, scoped_ptr<ResourceEntry>()); 371 return; 372 } 373 374 DCHECK(file_list); 375 const ScopedVector<google_apis::FileResource>& entries = file_list->items(); 376 for (size_t i = 0; i < entries.size(); ++i) { 377 scoped_ptr<ResourceEntry> entry(new ResourceEntry); 378 std::string parent_resource_id; 379 bool converted = ConvertFileResourceToResourceEntry( 380 *entries[i], entry.get(), &parent_resource_id); 381 DCHECK(converted); 382 entry->set_parent_local_id(parent_resource_id); 383 384 if (entry->base_name() == base_name.AsUTF8Unsafe()) { 385 // Found the target entry. 386 callback.Run(FILE_ERROR_OK, entry.Pass()); 387 return; 388 } 389 } 390 391 callback.Run(FILE_ERROR_NOT_FOUND, scoped_ptr<ResourceEntry>()); 392 } 393 394 } // namespace test_util 395 } // namespace drive 396