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 "chrome/browser/google_apis/drive_api_parser.h" 19 #include "chrome/browser/google_apis/gdata_wapi_parser.h" 20 #include "content/public/browser/browser_thread.h" 21 22 namespace drive { 23 namespace test_util { 24 25 using content::BrowserThread; 26 27 FakeFileSystem::FakeFileSystem(DriveServiceInterface* drive_service) 28 : drive_service_(drive_service), 29 weak_ptr_factory_(this) { 30 } 31 32 FakeFileSystem::~FakeFileSystem() { 33 } 34 35 bool FakeFileSystem::InitializeForTesting() { 36 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 37 return cache_dir_.CreateUniqueTempDir(); 38 } 39 40 void FakeFileSystem::Initialize() { 41 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 42 InitializeForTesting(); 43 } 44 45 void FakeFileSystem::AddObserver(FileSystemObserver* observer) { 46 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 47 } 48 49 void FakeFileSystem::RemoveObserver(FileSystemObserver* observer) { 50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 51 } 52 53 void FakeFileSystem::CheckForUpdates() { 54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 55 } 56 57 void FakeFileSystem::TransferFileFromRemoteToLocal( 58 const base::FilePath& remote_src_file_path, 59 const base::FilePath& local_dest_file_path, 60 const FileOperationCallback& callback) { 61 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 62 } 63 64 void FakeFileSystem::TransferFileFromLocalToRemote( 65 const base::FilePath& local_src_file_path, 66 const base::FilePath& remote_dest_file_path, 67 const FileOperationCallback& callback) { 68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 69 } 70 71 void FakeFileSystem::OpenFile(const base::FilePath& file_path, 72 OpenMode open_mode, 73 const OpenFileCallback& callback) { 74 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 75 } 76 77 void FakeFileSystem::Copy(const base::FilePath& src_file_path, 78 const base::FilePath& dest_file_path, 79 const FileOperationCallback& callback) { 80 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 81 } 82 83 void FakeFileSystem::Move(const base::FilePath& src_file_path, 84 const base::FilePath& dest_file_path, 85 const FileOperationCallback& callback) { 86 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 87 } 88 89 void FakeFileSystem::Remove(const base::FilePath& file_path, 90 bool is_recursive, 91 const FileOperationCallback& callback) { 92 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 93 } 94 95 void FakeFileSystem::CreateDirectory( 96 const base::FilePath& directory_path, 97 bool is_exclusive, 98 bool is_recursive, 99 const FileOperationCallback& callback) { 100 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 101 } 102 103 void FakeFileSystem::CreateFile(const base::FilePath& file_path, 104 bool is_exclusive, 105 const FileOperationCallback& callback) { 106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 107 } 108 109 void FakeFileSystem::TouchFile(const base::FilePath& file_path, 110 const base::Time& last_access_time, 111 const base::Time& last_modified_time, 112 const FileOperationCallback& callback) { 113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 114 } 115 116 void FakeFileSystem::TruncateFile(const base::FilePath& file_path, 117 int64 length, 118 const FileOperationCallback& callback) { 119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 120 } 121 122 void FakeFileSystem::Pin(const base::FilePath& file_path, 123 const FileOperationCallback& callback) { 124 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 125 } 126 127 void FakeFileSystem::Unpin(const base::FilePath& file_path, 128 const FileOperationCallback& callback) { 129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 130 } 131 132 void FakeFileSystem::GetFileByPath(const base::FilePath& file_path, 133 const GetFileCallback& callback) { 134 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 135 } 136 137 void FakeFileSystem::GetFileByPathForSaving(const base::FilePath& file_path, 138 const GetFileCallback& callback) { 139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 140 } 141 142 void FakeFileSystem::GetFileContentByPath( 143 const base::FilePath& file_path, 144 const GetFileContentInitializedCallback& initialized_callback, 145 const google_apis::GetContentCallback& get_content_callback, 146 const FileOperationCallback& completion_callback) { 147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 148 149 GetResourceEntryByPath( 150 file_path, 151 base::Bind(&FakeFileSystem::GetFileContentByPathAfterGetResourceEntry, 152 weak_ptr_factory_.GetWeakPtr(), 153 initialized_callback, get_content_callback, 154 completion_callback)); 155 } 156 157 void FakeFileSystem::GetResourceEntryByPath( 158 const base::FilePath& file_path, 159 const GetResourceEntryCallback& callback) { 160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 161 162 // Now, we only support files under my drive. 163 DCHECK(!util::IsUnderDriveMountPoint(file_path)); 164 165 if (file_path == util::GetDriveMyDriveRootPath()) { 166 // Specialized for the root entry. 167 drive_service_->GetAboutResource( 168 base::Bind( 169 &FakeFileSystem::GetResourceEntryByPathAfterGetAboutResource, 170 weak_ptr_factory_.GetWeakPtr(), callback)); 171 return; 172 } 173 174 GetResourceEntryByPath( 175 file_path.DirName(), 176 base::Bind( 177 &FakeFileSystem::GetResourceEntryByPathAfterGetParentEntryInfo, 178 weak_ptr_factory_.GetWeakPtr(), file_path.BaseName(), callback)); 179 } 180 181 void FakeFileSystem::ReadDirectoryByPath( 182 const base::FilePath& file_path, 183 const ReadDirectoryCallback& callback) { 184 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 185 } 186 187 void FakeFileSystem::Search(const std::string& search_query, 188 const GURL& next_url, 189 const SearchCallback& callback) { 190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 191 } 192 193 void FakeFileSystem::SearchMetadata( 194 const std::string& query, 195 int options, 196 int at_most_num_matches, 197 const SearchMetadataCallback& callback) { 198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 199 } 200 201 void FakeFileSystem::GetAvailableSpace( 202 const GetAvailableSpaceCallback& callback) { 203 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 204 } 205 206 void FakeFileSystem::GetShareUrl( 207 const base::FilePath& file_path, 208 const GURL& embed_origin, 209 const GetShareUrlCallback& callback) { 210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 211 } 212 213 void FakeFileSystem::GetMetadata( 214 const GetFilesystemMetadataCallback& callback) { 215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 216 } 217 218 void FakeFileSystem::MarkCacheFileAsMounted( 219 const base::FilePath& drive_file_path, 220 const MarkMountedCallback& callback) { 221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 222 } 223 224 void FakeFileSystem::MarkCacheFileAsUnmounted( 225 const base::FilePath& cache_file_path, 226 const FileOperationCallback& callback) { 227 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 228 } 229 230 void FakeFileSystem::GetCacheEntryByResourceId( 231 const std::string& resource_id, 232 const GetCacheEntryCallback& callback) { 233 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 234 } 235 236 void FakeFileSystem::Reload() { 237 } 238 239 // Implementation of GetFileContentByPath. 240 void FakeFileSystem::GetFileContentByPathAfterGetResourceEntry( 241 const GetFileContentInitializedCallback& initialized_callback, 242 const google_apis::GetContentCallback& get_content_callback, 243 const FileOperationCallback& completion_callback, 244 FileError error, 245 scoped_ptr<ResourceEntry> entry) { 246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 247 248 if (error != FILE_ERROR_OK) { 249 completion_callback.Run(error); 250 return; 251 } 252 DCHECK(entry); 253 254 // We're only interested in a file. 255 if (entry->file_info().is_directory()) { 256 completion_callback.Run(FILE_ERROR_NOT_A_FILE); 257 return; 258 } 259 260 // Fetch google_apis::ResourceEntry for its |download_url|. 261 drive_service_->GetResourceEntry( 262 entry->resource_id(), 263 base::Bind( 264 &FakeFileSystem::GetFileContentByPathAfterGetWapiResourceEntry, 265 weak_ptr_factory_.GetWeakPtr(), 266 initialized_callback, 267 get_content_callback, 268 completion_callback)); 269 } 270 271 void FakeFileSystem::GetFileContentByPathAfterGetWapiResourceEntry( 272 const GetFileContentInitializedCallback& initialized_callback, 273 const google_apis::GetContentCallback& get_content_callback, 274 const FileOperationCallback& completion_callback, 275 google_apis::GDataErrorCode gdata_error, 276 scoped_ptr<google_apis::ResourceEntry> gdata_entry) { 277 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 278 279 FileError error = GDataToFileError(gdata_error); 280 if (error != FILE_ERROR_OK) { 281 completion_callback.Run(error); 282 return; 283 } 284 DCHECK(gdata_entry); 285 286 scoped_ptr<ResourceEntry> entry(new ResourceEntry); 287 bool converted = ConvertToResourceEntry(*gdata_entry, entry.get()); 288 DCHECK(converted); 289 290 base::FilePath cache_path = 291 cache_dir_.path().AppendASCII(entry->resource_id()); 292 if (base::PathExists(cache_path)) { 293 // Cache file is found. 294 initialized_callback.Run(FILE_ERROR_OK, entry.Pass(), cache_path, 295 base::Closure()); 296 completion_callback.Run(FILE_ERROR_OK); 297 return; 298 } 299 300 initialized_callback.Run(FILE_ERROR_OK, entry.Pass(), base::FilePath(), 301 base::Bind(&base::DoNothing)); 302 drive_service_->DownloadFile( 303 cache_path, 304 gdata_entry->resource_id(), 305 base::Bind(&FakeFileSystem::GetFileContentByPathAfterDownloadFile, 306 weak_ptr_factory_.GetWeakPtr(), 307 completion_callback), 308 get_content_callback, 309 google_apis::ProgressCallback()); 310 } 311 312 void FakeFileSystem::GetFileContentByPathAfterDownloadFile( 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 GetResourceEntryByPath. 321 void FakeFileSystem::GetResourceEntryByPathAfterGetAboutResource( 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::GetResourceEntryByPathAfterGetParentEntryInfo( 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_->GetResourceListInDirectory( 355 parent_entry->resource_id(), 356 base::Bind( 357 &FakeFileSystem::GetResourceEntryByPathAfterGetResourceList, 358 weak_ptr_factory_.GetWeakPtr(), base_name, callback)); 359 } 360 361 void FakeFileSystem::GetResourceEntryByPathAfterGetResourceList( 362 const base::FilePath& base_name, 363 const GetResourceEntryCallback& callback, 364 google_apis::GDataErrorCode gdata_error, 365 scoped_ptr<google_apis::ResourceList> resource_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(resource_list); 375 const ScopedVector<google_apis::ResourceEntry>& entries = 376 resource_list->entries(); 377 for (size_t i = 0; i < entries.size(); ++i) { 378 scoped_ptr<ResourceEntry> entry(new ResourceEntry); 379 bool converted = ConvertToResourceEntry(*entries[i], entry.get()); 380 DCHECK(converted); 381 382 if (entry->base_name() == base_name.AsUTF8Unsafe()) { 383 // Found the target entry. 384 callback.Run(FILE_ERROR_OK, entry.Pass()); 385 return; 386 } 387 } 388 389 callback.Run(FILE_ERROR_NOT_FOUND, scoped_ptr<ResourceEntry>()); 390 } 391 392 } // namespace test_util 393 } // namespace drive 394