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/file_util.h" 11 #include "base/files/file_path.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 // Now, we only support files under my drive. 150 DCHECK(!util::IsUnderDriveMountPoint(file_path)); 151 152 if (file_path == util::GetDriveMyDriveRootPath()) { 153 // Specialized for the root entry. 154 drive_service_->GetAboutResource( 155 base::Bind( 156 &FakeFileSystem::GetResourceEntryAfterGetAboutResource, 157 weak_ptr_factory_.GetWeakPtr(), callback)); 158 return; 159 } 160 161 GetResourceEntry( 162 file_path.DirName(), 163 base::Bind( 164 &FakeFileSystem::GetResourceEntryAfterGetParentEntryInfo, 165 weak_ptr_factory_.GetWeakPtr(), file_path.BaseName(), callback)); 166 } 167 168 void FakeFileSystem::ReadDirectory( 169 const base::FilePath& file_path, 170 const ReadDirectoryEntriesCallback& entries_callback, 171 const FileOperationCallback& completion_callback) { 172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 173 } 174 175 void FakeFileSystem::Search(const std::string& search_query, 176 const GURL& next_link, 177 const SearchCallback& callback) { 178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 179 } 180 181 void FakeFileSystem::SearchMetadata( 182 const std::string& query, 183 int options, 184 int at_most_num_matches, 185 const SearchMetadataCallback& callback) { 186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 187 } 188 189 void FakeFileSystem::GetAvailableSpace( 190 const GetAvailableSpaceCallback& callback) { 191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 192 } 193 194 void FakeFileSystem::GetShareUrl( 195 const base::FilePath& file_path, 196 const GURL& embed_origin, 197 const GetShareUrlCallback& callback) { 198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 199 } 200 201 void FakeFileSystem::GetMetadata( 202 const GetFilesystemMetadataCallback& callback) { 203 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 204 } 205 206 void FakeFileSystem::MarkCacheFileAsMounted( 207 const base::FilePath& drive_file_path, 208 const MarkMountedCallback& callback) { 209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 210 } 211 212 void FakeFileSystem::MarkCacheFileAsUnmounted( 213 const base::FilePath& cache_file_path, 214 const FileOperationCallback& callback) { 215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 216 } 217 218 void FakeFileSystem::AddPermission(const base::FilePath& drive_file_path, 219 const std::string& email, 220 google_apis::drive::PermissionRole role, 221 const FileOperationCallback& callback) { 222 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 223 } 224 225 void FakeFileSystem::Reset(const FileOperationCallback& callback) { 226 } 227 228 void FakeFileSystem::GetPathFromResourceId( 229 const std::string& resource_id, 230 const GetFilePathCallback& callback) { 231 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 232 } 233 234 // Implementation of GetFileContent. 235 void FakeFileSystem::GetFileContentAfterGetResourceEntry( 236 const GetFileContentInitializedCallback& initialized_callback, 237 const google_apis::GetContentCallback& get_content_callback, 238 const FileOperationCallback& completion_callback, 239 FileError error, 240 scoped_ptr<ResourceEntry> entry) { 241 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 242 243 if (error != FILE_ERROR_OK) { 244 completion_callback.Run(error); 245 return; 246 } 247 DCHECK(entry); 248 249 // We're only interested in a file. 250 if (entry->file_info().is_directory()) { 251 completion_callback.Run(FILE_ERROR_NOT_A_FILE); 252 return; 253 } 254 255 // Fetch google_apis::FileResource for its |download_url|. 256 drive_service_->GetFileResource( 257 entry->resource_id(), 258 base::Bind( 259 &FakeFileSystem::GetFileContentAfterGetFileResource, 260 weak_ptr_factory_.GetWeakPtr(), 261 initialized_callback, 262 get_content_callback, 263 completion_callback)); 264 } 265 266 void FakeFileSystem::GetFileContentAfterGetFileResource( 267 const GetFileContentInitializedCallback& initialized_callback, 268 const google_apis::GetContentCallback& get_content_callback, 269 const FileOperationCallback& completion_callback, 270 google_apis::GDataErrorCode gdata_error, 271 scoped_ptr<google_apis::FileResource> gdata_entry) { 272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 273 274 FileError error = GDataToFileError(gdata_error); 275 if (error != FILE_ERROR_OK) { 276 completion_callback.Run(error); 277 return; 278 } 279 DCHECK(gdata_entry); 280 281 scoped_ptr<ResourceEntry> entry(new ResourceEntry); 282 std::string parent_resource_id; 283 bool converted = ConvertFileResourceToResourceEntry( 284 *gdata_entry, entry.get(), &parent_resource_id); 285 DCHECK(converted); 286 entry->set_parent_local_id(parent_resource_id); 287 288 base::FilePath cache_path = 289 cache_dir_.path().AppendASCII(entry->resource_id()); 290 if (base::PathExists(cache_path)) { 291 // Cache file is found. 292 initialized_callback.Run(FILE_ERROR_OK, cache_path, entry.Pass()); 293 completion_callback.Run(FILE_ERROR_OK); 294 return; 295 } 296 297 initialized_callback.Run(FILE_ERROR_OK, base::FilePath(), entry.Pass()); 298 drive_service_->DownloadFile( 299 cache_path, 300 gdata_entry->file_id(), 301 base::Bind(&FakeFileSystem::GetFileContentAfterDownloadFile, 302 weak_ptr_factory_.GetWeakPtr(), 303 completion_callback), 304 get_content_callback, 305 google_apis::ProgressCallback()); 306 } 307 308 void FakeFileSystem::GetFileContentAfterDownloadFile( 309 const FileOperationCallback& completion_callback, 310 google_apis::GDataErrorCode gdata_error, 311 const base::FilePath& temp_file) { 312 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 313 completion_callback.Run(GDataToFileError(gdata_error)); 314 } 315 316 // Implementation of GetResourceEntry. 317 void FakeFileSystem::GetResourceEntryAfterGetAboutResource( 318 const GetResourceEntryCallback& callback, 319 google_apis::GDataErrorCode gdata_error, 320 scoped_ptr<google_apis::AboutResource> about_resource) { 321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 322 323 FileError error = GDataToFileError(gdata_error); 324 if (error != FILE_ERROR_OK) { 325 callback.Run(error, scoped_ptr<ResourceEntry>()); 326 return; 327 } 328 329 DCHECK(about_resource); 330 scoped_ptr<ResourceEntry> root(new ResourceEntry); 331 root->mutable_file_info()->set_is_directory(true); 332 root->set_resource_id(about_resource->root_folder_id()); 333 root->set_title(util::kDriveMyDriveRootDirName); 334 callback.Run(error, root.Pass()); 335 } 336 337 void FakeFileSystem::GetResourceEntryAfterGetParentEntryInfo( 338 const base::FilePath& base_name, 339 const GetResourceEntryCallback& callback, 340 FileError error, 341 scoped_ptr<ResourceEntry> parent_entry) { 342 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 343 344 if (error != FILE_ERROR_OK) { 345 callback.Run(error, scoped_ptr<ResourceEntry>()); 346 return; 347 } 348 349 DCHECK(parent_entry); 350 drive_service_->GetFileListInDirectory( 351 parent_entry->resource_id(), 352 base::Bind( 353 &FakeFileSystem::GetResourceEntryAfterGetFileList, 354 weak_ptr_factory_.GetWeakPtr(), base_name, callback)); 355 } 356 357 void FakeFileSystem::GetResourceEntryAfterGetFileList( 358 const base::FilePath& base_name, 359 const GetResourceEntryCallback& callback, 360 google_apis::GDataErrorCode gdata_error, 361 scoped_ptr<google_apis::FileList> file_list) { 362 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 363 364 FileError error = GDataToFileError(gdata_error); 365 if (error != FILE_ERROR_OK) { 366 callback.Run(error, scoped_ptr<ResourceEntry>()); 367 return; 368 } 369 370 DCHECK(file_list); 371 const ScopedVector<google_apis::FileResource>& entries = file_list->items(); 372 for (size_t i = 0; i < entries.size(); ++i) { 373 scoped_ptr<ResourceEntry> entry(new ResourceEntry); 374 std::string parent_resource_id; 375 bool converted = ConvertFileResourceToResourceEntry( 376 *entries[i], entry.get(), &parent_resource_id); 377 DCHECK(converted); 378 entry->set_parent_local_id(parent_resource_id); 379 380 if (entry->base_name() == base_name.AsUTF8Unsafe()) { 381 // Found the target entry. 382 callback.Run(FILE_ERROR_OK, entry.Pass()); 383 return; 384 } 385 } 386 387 callback.Run(FILE_ERROR_NOT_FOUND, scoped_ptr<ResourceEntry>()); 388 } 389 390 } // namespace test_util 391 } // namespace drive 392