1 // Copyright (c) 2012 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/file_system.h" 6 7 #include "base/bind.h" 8 #include "base/file_util.h" 9 #include "base/prefs/pref_service.h" 10 #include "chrome/browser/chromeos/drive/change_list_loader.h" 11 #include "chrome/browser/chromeos/drive/directory_loader.h" 12 #include "chrome/browser/chromeos/drive/drive.pb.h" 13 #include "chrome/browser/chromeos/drive/file_cache.h" 14 #include "chrome/browser/chromeos/drive/file_system/copy_operation.h" 15 #include "chrome/browser/chromeos/drive/file_system/create_directory_operation.h" 16 #include "chrome/browser/chromeos/drive/file_system/create_file_operation.h" 17 #include "chrome/browser/chromeos/drive/file_system/download_operation.h" 18 #include "chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.h" 19 #include "chrome/browser/chromeos/drive/file_system/move_operation.h" 20 #include "chrome/browser/chromeos/drive/file_system/open_file_operation.h" 21 #include "chrome/browser/chromeos/drive/file_system/remove_operation.h" 22 #include "chrome/browser/chromeos/drive/file_system/search_operation.h" 23 #include "chrome/browser/chromeos/drive/file_system/touch_operation.h" 24 #include "chrome/browser/chromeos/drive/file_system/truncate_operation.h" 25 #include "chrome/browser/chromeos/drive/file_system_observer.h" 26 #include "chrome/browser/chromeos/drive/file_system_util.h" 27 #include "chrome/browser/chromeos/drive/job_scheduler.h" 28 #include "chrome/browser/chromeos/drive/remove_stale_cache_files.h" 29 #include "chrome/browser/chromeos/drive/resource_entry_conversion.h" 30 #include "chrome/browser/chromeos/drive/search_metadata.h" 31 #include "chrome/browser/chromeos/drive/sync_client.h" 32 #include "chrome/browser/drive/drive_service_interface.h" 33 #include "chrome/common/pref_names.h" 34 #include "content/public/browser/browser_thread.h" 35 #include "google_apis/drive/drive_api_parser.h" 36 37 using content::BrowserThread; 38 39 namespace drive { 40 namespace { 41 42 // Gets a ResourceEntry from the metadata, and overwrites its file info when the 43 // cached file is dirty. 44 FileError GetLocallyStoredResourceEntry( 45 internal::ResourceMetadata* resource_metadata, 46 internal::FileCache* cache, 47 const base::FilePath& file_path, 48 ResourceEntry* entry) { 49 std::string local_id; 50 FileError error = resource_metadata->GetIdByPath(file_path, &local_id); 51 if (error != FILE_ERROR_OK) 52 return error; 53 54 error = resource_metadata->GetResourceEntryById(local_id, entry); 55 if (error != FILE_ERROR_OK) 56 return error; 57 58 // For entries that will never be cached, use the original resource entry 59 // as is. 60 if (!entry->has_file_specific_info() || 61 entry->file_specific_info().is_hosted_document()) 62 return FILE_ERROR_OK; 63 64 // When cache is not found, use the original resource entry as is. 65 if (!entry->file_specific_info().has_cache_state()) 66 return FILE_ERROR_OK; 67 68 // When cache is non-dirty and obsolete (old hash), use the original entry. 69 if (!entry->file_specific_info().cache_state().is_dirty() && 70 entry->file_specific_info().md5() != 71 entry->file_specific_info().cache_state().md5()) 72 return FILE_ERROR_OK; 73 74 // If there's a valid cache, obtain the file info from the cache file itself. 75 base::FilePath local_cache_path; 76 error = cache->GetFile(local_id, &local_cache_path); 77 if (error != FILE_ERROR_OK) 78 return error; 79 80 base::File::Info file_info; 81 if (!base::GetFileInfo(local_cache_path, &file_info)) 82 return FILE_ERROR_NOT_FOUND; 83 84 entry->mutable_file_info()->set_size(file_info.size); 85 return FILE_ERROR_OK; 86 } 87 88 // Runs the callback with parameters. 89 void RunGetResourceEntryCallback(const GetResourceEntryCallback& callback, 90 scoped_ptr<ResourceEntry> entry, 91 FileError error) { 92 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 93 DCHECK(!callback.is_null()); 94 95 if (error != FILE_ERROR_OK) 96 entry.reset(); 97 callback.Run(error, entry.Pass()); 98 } 99 100 // Used to implement Pin(). 101 FileError PinInternal(internal::ResourceMetadata* resource_metadata, 102 internal::FileCache* cache, 103 const base::FilePath& file_path, 104 std::string* local_id) { 105 FileError error = resource_metadata->GetIdByPath(file_path, local_id); 106 if (error != FILE_ERROR_OK) 107 return error; 108 109 ResourceEntry entry; 110 error = resource_metadata->GetResourceEntryById(*local_id, &entry); 111 if (error != FILE_ERROR_OK) 112 return error; 113 114 // TODO(hashimoto): Support pinning directories. crbug.com/127831 115 if (entry.file_info().is_directory()) 116 return FILE_ERROR_NOT_A_FILE; 117 118 return cache->Pin(*local_id); 119 } 120 121 // Used to implement Unpin(). 122 FileError UnpinInternal(internal::ResourceMetadata* resource_metadata, 123 internal::FileCache* cache, 124 const base::FilePath& file_path, 125 std::string* local_id) { 126 FileError error = resource_metadata->GetIdByPath(file_path, local_id); 127 if (error != FILE_ERROR_OK) 128 return error; 129 130 return cache->Unpin(*local_id); 131 } 132 133 // Used to implement MarkCacheFileAsMounted(). 134 FileError MarkCacheFileAsMountedInternal( 135 internal::ResourceMetadata* resource_metadata, 136 internal::FileCache* cache, 137 const base::FilePath& drive_file_path, 138 base::FilePath* cache_file_path) { 139 std::string local_id; 140 FileError error = resource_metadata->GetIdByPath(drive_file_path, &local_id); 141 if (error != FILE_ERROR_OK) 142 return error; 143 144 return cache->MarkAsMounted(local_id, cache_file_path); 145 } 146 147 // Runs the callback with arguments. 148 void RunMarkMountedCallback(const MarkMountedCallback& callback, 149 base::FilePath* cache_file_path, 150 FileError error) { 151 DCHECK(!callback.is_null()); 152 callback.Run(error, *cache_file_path); 153 } 154 155 // Callback for ResourceMetadata::GetLargestChangestamp. 156 // |callback| must not be null. 157 void OnGetLargestChangestamp( 158 FileSystemMetadata metadata, // Will be modified. 159 const GetFilesystemMetadataCallback& callback, 160 const int64* largest_changestamp, 161 FileError error) { 162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 163 DCHECK(!callback.is_null()); 164 165 metadata.largest_changestamp = *largest_changestamp; 166 callback.Run(metadata); 167 } 168 169 // Thin adapter to map GetFileCallback to FileOperationCallback. 170 void GetFileCallbackToFileOperationCallbackAdapter( 171 const FileOperationCallback& callback, 172 FileError error, 173 const base::FilePath& unused_file_path, 174 scoped_ptr<ResourceEntry> unused_entry) { 175 callback.Run(error); 176 } 177 178 // Clears |resource_metadata| and |cache|. 179 FileError ResetOnBlockingPool(internal::ResourceMetadata* resource_metadata, 180 internal::FileCache* cache) { 181 FileError error = resource_metadata->Reset(); 182 if (error != FILE_ERROR_OK) 183 return error; 184 return cache->ClearAll() ? FILE_ERROR_OK : FILE_ERROR_FAILED; 185 } 186 187 // Part of GetPathFromResourceId(). 188 // Obtains |file_path| from |resource_id|. The function should be run on the 189 // blocking pool. 190 FileError GetPathFromResourceIdOnBlockingPool( 191 internal::ResourceMetadata* resource_metadata, 192 const std::string& resource_id, 193 base::FilePath* file_path) { 194 std::string local_id; 195 const FileError error = 196 resource_metadata->GetIdByResourceId(resource_id, &local_id); 197 if (error != FILE_ERROR_OK) 198 return error; 199 return resource_metadata->GetFilePath(local_id, file_path); 200 } 201 202 // Part of GetPathFromResourceId(). 203 // Called when GetPathFromResourceIdInBlockingPool is complete. 204 void GetPathFromResourceIdAfterGetPath(base::FilePath* file_path, 205 const GetFilePathCallback& callback, 206 FileError error) { 207 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 208 callback.Run(error, *file_path); 209 } 210 211 // Excludes hosted documents from the given entries. 212 // Used to implement ReadDirectory(). 213 void FilterHostedDocuments(const ReadDirectoryEntriesCallback& callback, 214 scoped_ptr<ResourceEntryVector> entries) { 215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 216 DCHECK(!callback.is_null()); 217 218 if (entries) { 219 // TODO(kinaba): Stop handling hide_hosted_docs here. crbug.com/256520. 220 scoped_ptr<ResourceEntryVector> filtered(new ResourceEntryVector); 221 for (size_t i = 0; i < entries->size(); ++i) { 222 if (entries->at(i).file_specific_info().is_hosted_document()) { 223 continue; 224 } 225 filtered->push_back(entries->at(i)); 226 } 227 entries.swap(filtered); 228 } 229 callback.Run(entries.Pass()); 230 } 231 232 // Adapter for using FileOperationCallback as google_apis::EntryActionCallback. 233 void RunFileOperationCallbackAsEntryActionCallback( 234 const FileOperationCallback& callback, 235 google_apis::GDataErrorCode error) { 236 callback.Run(GDataToFileError(error)); 237 } 238 239 } // namespace 240 241 struct FileSystem::CreateDirectoryParams { 242 base::FilePath directory_path; 243 bool is_exclusive; 244 bool is_recursive; 245 FileOperationCallback callback; 246 }; 247 248 FileSystem::FileSystem( 249 PrefService* pref_service, 250 EventLogger* logger, 251 internal::FileCache* cache, 252 DriveServiceInterface* drive_service, 253 JobScheduler* scheduler, 254 internal::ResourceMetadata* resource_metadata, 255 base::SequencedTaskRunner* blocking_task_runner, 256 const base::FilePath& temporary_file_directory) 257 : pref_service_(pref_service), 258 logger_(logger), 259 cache_(cache), 260 drive_service_(drive_service), 261 scheduler_(scheduler), 262 resource_metadata_(resource_metadata), 263 last_update_check_error_(FILE_ERROR_OK), 264 blocking_task_runner_(blocking_task_runner), 265 temporary_file_directory_(temporary_file_directory), 266 weak_ptr_factory_(this) { 267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 268 269 ResetComponents(); 270 } 271 272 FileSystem::~FileSystem() { 273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 274 275 directory_loader_->RemoveObserver(this); 276 change_list_loader_->RemoveObserver(this); 277 } 278 279 void FileSystem::Reset(const FileOperationCallback& callback) { 280 // Discard the current loader and operation objects and renew them. This is to 281 // avoid that changes initiated before the metadata reset is applied after the 282 // reset, which may cause an inconsistent state. 283 // TODO(kinaba): callbacks held in the subcomponents are discarded. We might 284 // want to have a way to abort and flush callbacks in in-flight operations. 285 ResetComponents(); 286 287 base::PostTaskAndReplyWithResult( 288 blocking_task_runner_, 289 FROM_HERE, 290 base::Bind(&ResetOnBlockingPool, resource_metadata_, cache_), 291 callback); 292 } 293 294 void FileSystem::ResetComponents() { 295 file_system::OperationObserver* observer = this; 296 297 about_resource_loader_.reset(new internal::AboutResourceLoader(scheduler_)); 298 loader_controller_.reset(new internal::LoaderController); 299 change_list_loader_.reset(new internal::ChangeListLoader( 300 logger_, 301 blocking_task_runner_.get(), 302 resource_metadata_, 303 scheduler_, 304 about_resource_loader_.get(), 305 loader_controller_.get())); 306 change_list_loader_->AddObserver(this); 307 directory_loader_.reset(new internal::DirectoryLoader( 308 logger_, 309 blocking_task_runner_.get(), 310 resource_metadata_, 311 scheduler_, 312 about_resource_loader_.get(), 313 loader_controller_.get())); 314 directory_loader_->AddObserver(this); 315 316 sync_client_.reset(new internal::SyncClient(blocking_task_runner_.get(), 317 observer, 318 scheduler_, 319 resource_metadata_, 320 cache_, 321 loader_controller_.get(), 322 temporary_file_directory_)); 323 324 copy_operation_.reset( 325 new file_system::CopyOperation( 326 blocking_task_runner_.get(), 327 observer, 328 scheduler_, 329 resource_metadata_, 330 cache_, 331 drive_service_->GetResourceIdCanonicalizer())); 332 create_directory_operation_.reset(new file_system::CreateDirectoryOperation( 333 blocking_task_runner_.get(), observer, resource_metadata_)); 334 create_file_operation_.reset( 335 new file_system::CreateFileOperation(blocking_task_runner_.get(), 336 observer, 337 resource_metadata_)); 338 move_operation_.reset( 339 new file_system::MoveOperation(blocking_task_runner_.get(), 340 observer, 341 resource_metadata_)); 342 open_file_operation_.reset( 343 new file_system::OpenFileOperation(blocking_task_runner_.get(), 344 observer, 345 scheduler_, 346 resource_metadata_, 347 cache_, 348 temporary_file_directory_)); 349 remove_operation_.reset( 350 new file_system::RemoveOperation(blocking_task_runner_.get(), 351 observer, 352 resource_metadata_, 353 cache_)); 354 touch_operation_.reset(new file_system::TouchOperation( 355 blocking_task_runner_.get(), observer, resource_metadata_)); 356 truncate_operation_.reset( 357 new file_system::TruncateOperation(blocking_task_runner_.get(), 358 observer, 359 scheduler_, 360 resource_metadata_, 361 cache_, 362 temporary_file_directory_)); 363 download_operation_.reset( 364 new file_system::DownloadOperation(blocking_task_runner_.get(), 365 observer, 366 scheduler_, 367 resource_metadata_, 368 cache_, 369 temporary_file_directory_)); 370 search_operation_.reset(new file_system::SearchOperation( 371 blocking_task_runner_.get(), scheduler_, resource_metadata_, 372 loader_controller_.get())); 373 get_file_for_saving_operation_.reset( 374 new file_system::GetFileForSavingOperation(logger_, 375 blocking_task_runner_.get(), 376 observer, 377 scheduler_, 378 resource_metadata_, 379 cache_, 380 temporary_file_directory_)); 381 } 382 383 void FileSystem::CheckForUpdates() { 384 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 385 DVLOG(1) << "CheckForUpdates"; 386 387 change_list_loader_->CheckForUpdates( 388 base::Bind(&FileSystem::OnUpdateChecked, weak_ptr_factory_.GetWeakPtr())); 389 } 390 391 void FileSystem::OnUpdateChecked(FileError error) { 392 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 393 DVLOG(1) << "CheckForUpdates finished: " << FileErrorToString(error); 394 last_update_check_time_ = base::Time::Now(); 395 last_update_check_error_ = error; 396 } 397 398 void FileSystem::AddObserver(FileSystemObserver* observer) { 399 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 400 observers_.AddObserver(observer); 401 } 402 403 void FileSystem::RemoveObserver(FileSystemObserver* observer) { 404 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 405 observers_.RemoveObserver(observer); 406 } 407 408 void FileSystem::TransferFileFromLocalToRemote( 409 const base::FilePath& local_src_file_path, 410 const base::FilePath& remote_dest_file_path, 411 const FileOperationCallback& callback) { 412 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 413 DCHECK(!callback.is_null()); 414 copy_operation_->TransferFileFromLocalToRemote(local_src_file_path, 415 remote_dest_file_path, 416 callback); 417 } 418 419 void FileSystem::Copy(const base::FilePath& src_file_path, 420 const base::FilePath& dest_file_path, 421 bool preserve_last_modified, 422 const FileOperationCallback& callback) { 423 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 424 DCHECK(!callback.is_null()); 425 copy_operation_->Copy( 426 src_file_path, dest_file_path, preserve_last_modified, callback); 427 } 428 429 void FileSystem::Move(const base::FilePath& src_file_path, 430 const base::FilePath& dest_file_path, 431 const FileOperationCallback& callback) { 432 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 433 DCHECK(!callback.is_null()); 434 move_operation_->Move(src_file_path, dest_file_path, callback); 435 } 436 437 void FileSystem::Remove(const base::FilePath& file_path, 438 bool is_recursive, 439 const FileOperationCallback& callback) { 440 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 441 DCHECK(!callback.is_null()); 442 remove_operation_->Remove(file_path, is_recursive, callback); 443 } 444 445 void FileSystem::CreateDirectory( 446 const base::FilePath& directory_path, 447 bool is_exclusive, 448 bool is_recursive, 449 const FileOperationCallback& callback) { 450 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 451 DCHECK(!callback.is_null()); 452 453 CreateDirectoryParams params; 454 params.directory_path = directory_path; 455 params.is_exclusive = is_exclusive; 456 params.is_recursive = is_recursive; 457 params.callback = callback; 458 459 // Ensure its parent directory is loaded to the local metadata. 460 ReadDirectory(directory_path.DirName(), 461 ReadDirectoryEntriesCallback(), 462 base::Bind(&FileSystem::CreateDirectoryAfterRead, 463 weak_ptr_factory_.GetWeakPtr(), params)); 464 } 465 466 void FileSystem::CreateDirectoryAfterRead(const CreateDirectoryParams& params, 467 FileError error) { 468 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 469 DCHECK(!params.callback.is_null()); 470 471 DVLOG_IF(1, error != FILE_ERROR_OK) << "ReadDirectory failed. " 472 << FileErrorToString(error); 473 474 create_directory_operation_->CreateDirectory( 475 params.directory_path, params.is_exclusive, params.is_recursive, 476 params.callback); 477 } 478 479 void FileSystem::CreateFile(const base::FilePath& file_path, 480 bool is_exclusive, 481 const std::string& mime_type, 482 const FileOperationCallback& callback) { 483 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 484 DCHECK(!callback.is_null()); 485 create_file_operation_->CreateFile( 486 file_path, is_exclusive, mime_type, callback); 487 } 488 489 void FileSystem::TouchFile(const base::FilePath& file_path, 490 const base::Time& last_access_time, 491 const base::Time& last_modified_time, 492 const FileOperationCallback& callback) { 493 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 494 DCHECK(!callback.is_null()); 495 touch_operation_->TouchFile( 496 file_path, last_access_time, last_modified_time, callback); 497 } 498 499 void FileSystem::TruncateFile(const base::FilePath& file_path, 500 int64 length, 501 const FileOperationCallback& callback) { 502 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 503 DCHECK(!callback.is_null()); 504 truncate_operation_->Truncate(file_path, length, callback); 505 } 506 507 void FileSystem::Pin(const base::FilePath& file_path, 508 const FileOperationCallback& callback) { 509 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 510 DCHECK(!callback.is_null()); 511 512 std::string* local_id = new std::string; 513 base::PostTaskAndReplyWithResult( 514 blocking_task_runner_, 515 FROM_HERE, 516 base::Bind(&PinInternal, resource_metadata_, cache_, file_path, local_id), 517 base::Bind(&FileSystem::FinishPin, 518 weak_ptr_factory_.GetWeakPtr(), 519 callback, 520 base::Owned(local_id))); 521 } 522 523 void FileSystem::FinishPin(const FileOperationCallback& callback, 524 const std::string* local_id, 525 FileError error) { 526 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 527 DCHECK(!callback.is_null()); 528 529 if (error == FILE_ERROR_OK) 530 sync_client_->AddFetchTask(*local_id); 531 callback.Run(error); 532 } 533 534 void FileSystem::Unpin(const base::FilePath& file_path, 535 const FileOperationCallback& callback) { 536 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 537 DCHECK(!callback.is_null()); 538 539 std::string* local_id = new std::string; 540 base::PostTaskAndReplyWithResult( 541 blocking_task_runner_, 542 FROM_HERE, 543 base::Bind(&UnpinInternal, 544 resource_metadata_, 545 cache_, 546 file_path, 547 local_id), 548 base::Bind(&FileSystem::FinishUnpin, 549 weak_ptr_factory_.GetWeakPtr(), 550 callback, 551 base::Owned(local_id))); 552 } 553 554 void FileSystem::FinishUnpin(const FileOperationCallback& callback, 555 const std::string* local_id, 556 FileError error) { 557 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 558 DCHECK(!callback.is_null()); 559 560 if (error == FILE_ERROR_OK) 561 sync_client_->RemoveFetchTask(*local_id); 562 callback.Run(error); 563 } 564 565 void FileSystem::GetFile(const base::FilePath& file_path, 566 const GetFileCallback& callback) { 567 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 568 DCHECK(!callback.is_null()); 569 570 download_operation_->EnsureFileDownloadedByPath( 571 file_path, 572 ClientContext(USER_INITIATED), 573 GetFileContentInitializedCallback(), 574 google_apis::GetContentCallback(), 575 callback); 576 } 577 578 void FileSystem::GetFileForSaving(const base::FilePath& file_path, 579 const GetFileCallback& callback) { 580 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 581 DCHECK(!callback.is_null()); 582 583 get_file_for_saving_operation_->GetFileForSaving(file_path, callback); 584 } 585 586 base::Closure FileSystem::GetFileContent( 587 const base::FilePath& file_path, 588 const GetFileContentInitializedCallback& initialized_callback, 589 const google_apis::GetContentCallback& get_content_callback, 590 const FileOperationCallback& completion_callback) { 591 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 592 DCHECK(!initialized_callback.is_null()); 593 DCHECK(!get_content_callback.is_null()); 594 DCHECK(!completion_callback.is_null()); 595 596 return download_operation_->EnsureFileDownloadedByPath( 597 file_path, 598 ClientContext(USER_INITIATED), 599 initialized_callback, 600 get_content_callback, 601 base::Bind(&GetFileCallbackToFileOperationCallbackAdapter, 602 completion_callback)); 603 } 604 605 void FileSystem::GetResourceEntry( 606 const base::FilePath& file_path, 607 const GetResourceEntryCallback& callback) { 608 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 609 DCHECK(!callback.is_null()); 610 611 ReadDirectory(file_path.DirName(), 612 ReadDirectoryEntriesCallback(), 613 base::Bind(&FileSystem::GetResourceEntryAfterRead, 614 weak_ptr_factory_.GetWeakPtr(), 615 file_path, 616 callback)); 617 } 618 619 void FileSystem::GetResourceEntryAfterRead( 620 const base::FilePath& file_path, 621 const GetResourceEntryCallback& callback, 622 FileError error) { 623 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 624 DCHECK(!callback.is_null()); 625 626 DVLOG_IF(1, error != FILE_ERROR_OK) << "ReadDirectory failed. " 627 << FileErrorToString(error); 628 629 scoped_ptr<ResourceEntry> entry(new ResourceEntry); 630 ResourceEntry* entry_ptr = entry.get(); 631 base::PostTaskAndReplyWithResult( 632 blocking_task_runner_, 633 FROM_HERE, 634 base::Bind(&GetLocallyStoredResourceEntry, 635 resource_metadata_, 636 cache_, 637 file_path, 638 entry_ptr), 639 base::Bind(&RunGetResourceEntryCallback, callback, base::Passed(&entry))); 640 } 641 642 void FileSystem::ReadDirectory( 643 const base::FilePath& directory_path, 644 const ReadDirectoryEntriesCallback& entries_callback_in, 645 const FileOperationCallback& completion_callback) { 646 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 647 DCHECK(!completion_callback.is_null()); 648 649 const bool hide_hosted_docs = 650 pref_service_->GetBoolean(prefs::kDisableDriveHostedFiles); 651 ReadDirectoryEntriesCallback entries_callback = entries_callback_in; 652 if (!entries_callback.is_null() && hide_hosted_docs) 653 entries_callback = base::Bind(&FilterHostedDocuments, entries_callback); 654 655 directory_loader_->ReadDirectory( 656 directory_path, entries_callback, completion_callback); 657 658 // Also start loading all of the user's contents. 659 change_list_loader_->LoadIfNeeded( 660 base::Bind(&util::EmptyFileOperationCallback)); 661 } 662 663 void FileSystem::GetAvailableSpace( 664 const GetAvailableSpaceCallback& callback) { 665 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 666 DCHECK(!callback.is_null()); 667 668 about_resource_loader_->GetAboutResource( 669 base::Bind(&FileSystem::OnGetAboutResource, 670 weak_ptr_factory_.GetWeakPtr(), 671 callback)); 672 } 673 674 void FileSystem::OnGetAboutResource( 675 const GetAvailableSpaceCallback& callback, 676 google_apis::GDataErrorCode status, 677 scoped_ptr<google_apis::AboutResource> about_resource) { 678 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 679 DCHECK(!callback.is_null()); 680 681 FileError error = GDataToFileError(status); 682 if (error != FILE_ERROR_OK) { 683 callback.Run(error, -1, -1); 684 return; 685 } 686 DCHECK(about_resource); 687 688 callback.Run(FILE_ERROR_OK, 689 about_resource->quota_bytes_total(), 690 about_resource->quota_bytes_used()); 691 } 692 693 void FileSystem::GetShareUrl(const base::FilePath& file_path, 694 const GURL& embed_origin, 695 const GetShareUrlCallback& callback) { 696 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 697 DCHECK(!callback.is_null()); 698 699 // Resolve the resource id. 700 ResourceEntry* entry = new ResourceEntry; 701 base::PostTaskAndReplyWithResult( 702 blocking_task_runner_.get(), 703 FROM_HERE, 704 base::Bind(&internal::ResourceMetadata::GetResourceEntryByPath, 705 base::Unretained(resource_metadata_), 706 file_path, 707 entry), 708 base::Bind(&FileSystem::GetShareUrlAfterGetResourceEntry, 709 weak_ptr_factory_.GetWeakPtr(), 710 file_path, 711 embed_origin, 712 callback, 713 base::Owned(entry))); 714 } 715 716 void FileSystem::GetShareUrlAfterGetResourceEntry( 717 const base::FilePath& file_path, 718 const GURL& embed_origin, 719 const GetShareUrlCallback& callback, 720 ResourceEntry* entry, 721 FileError error) { 722 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 723 DCHECK(!callback.is_null()); 724 725 if (error != FILE_ERROR_OK) { 726 callback.Run(error, GURL()); 727 return; 728 } 729 if (entry->resource_id().empty()) { 730 // This entry does not exist on the server. Just return. 731 callback.Run(FILE_ERROR_FAILED, GURL()); 732 return; 733 } 734 735 scheduler_->GetShareUrl( 736 entry->resource_id(), 737 embed_origin, 738 ClientContext(USER_INITIATED), 739 base::Bind(&FileSystem::OnGetResourceEntryForGetShareUrl, 740 weak_ptr_factory_.GetWeakPtr(), 741 callback)); 742 } 743 744 void FileSystem::OnGetResourceEntryForGetShareUrl( 745 const GetShareUrlCallback& callback, 746 google_apis::GDataErrorCode status, 747 const GURL& share_url) { 748 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 749 DCHECK(!callback.is_null()); 750 751 FileError error = GDataToFileError(status); 752 if (error != FILE_ERROR_OK) { 753 callback.Run(error, GURL()); 754 return; 755 } 756 757 if (share_url.is_empty()) { 758 callback.Run(FILE_ERROR_FAILED, GURL()); 759 return; 760 } 761 762 callback.Run(FILE_ERROR_OK, share_url); 763 } 764 765 void FileSystem::Search(const std::string& search_query, 766 const GURL& next_link, 767 const SearchCallback& callback) { 768 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 769 DCHECK(!callback.is_null()); 770 search_operation_->Search(search_query, next_link, callback); 771 } 772 773 void FileSystem::SearchMetadata(const std::string& query, 774 int options, 775 int at_most_num_matches, 776 const SearchMetadataCallback& callback) { 777 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 778 779 // TODO(satorux): Stop handling hide_hosted_docs here. crbug.com/256520. 780 if (pref_service_->GetBoolean(prefs::kDisableDriveHostedFiles)) 781 options |= SEARCH_METADATA_EXCLUDE_HOSTED_DOCUMENTS; 782 783 drive::internal::SearchMetadata(blocking_task_runner_, 784 resource_metadata_, 785 query, 786 options, 787 at_most_num_matches, 788 callback); 789 } 790 791 void FileSystem::OnDirectoryChangedByOperation( 792 const base::FilePath& directory_path) { 793 OnDirectoryChanged(directory_path); 794 } 795 796 void FileSystem::OnEntryUpdatedByOperation(const std::string& local_id) { 797 sync_client_->AddUpdateTask(ClientContext(USER_INITIATED), local_id); 798 } 799 800 void FileSystem::OnDriveSyncError(file_system::DriveSyncErrorType type, 801 const std::string& local_id) { 802 base::FilePath* file_path = new base::FilePath; 803 base::PostTaskAndReplyWithResult( 804 blocking_task_runner_, 805 FROM_HERE, 806 base::Bind(&internal::ResourceMetadata::GetFilePath, 807 base::Unretained(resource_metadata_), 808 local_id, 809 file_path), 810 base::Bind(&FileSystem::OnDriveSyncErrorAfterGetFilePath, 811 weak_ptr_factory_.GetWeakPtr(), 812 type, 813 base::Owned(file_path))); 814 } 815 816 void FileSystem::OnDriveSyncErrorAfterGetFilePath( 817 file_system::DriveSyncErrorType type, 818 const base::FilePath* file_path, 819 FileError error) { 820 if (error != FILE_ERROR_OK) 821 return; 822 FOR_EACH_OBSERVER(FileSystemObserver, 823 observers_, 824 OnDriveSyncError(type, *file_path)); 825 } 826 827 void FileSystem::OnDirectoryChanged(const base::FilePath& directory_path) { 828 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 829 830 FOR_EACH_OBSERVER(FileSystemObserver, observers_, 831 OnDirectoryChanged(directory_path)); 832 } 833 834 void FileSystem::OnLoadFromServerComplete() { 835 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 836 837 sync_client_->StartCheckingExistingPinnedFiles(); 838 } 839 840 void FileSystem::OnInitialLoadComplete() { 841 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 842 843 blocking_task_runner_->PostTask(FROM_HERE, 844 base::Bind(&internal::RemoveStaleCacheFiles, 845 cache_, 846 resource_metadata_)); 847 sync_client_->StartProcessingBacklog(); 848 } 849 850 void FileSystem::GetMetadata( 851 const GetFilesystemMetadataCallback& callback) { 852 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 853 DCHECK(!callback.is_null()); 854 855 FileSystemMetadata metadata; 856 metadata.refreshing = change_list_loader_->IsRefreshing(); 857 858 // Metadata related to delta update. 859 metadata.last_update_check_time = last_update_check_time_; 860 metadata.last_update_check_error = last_update_check_error_; 861 862 int64* largest_changestamp = new int64(0); 863 base::PostTaskAndReplyWithResult( 864 blocking_task_runner_, 865 FROM_HERE, 866 base::Bind(&internal::ResourceMetadata::GetLargestChangestamp, 867 base::Unretained(resource_metadata_), largest_changestamp), 868 base::Bind(&OnGetLargestChangestamp, metadata, callback, 869 base::Owned(largest_changestamp))); 870 } 871 872 void FileSystem::MarkCacheFileAsMounted( 873 const base::FilePath& drive_file_path, 874 const MarkMountedCallback& callback) { 875 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 876 DCHECK(!callback.is_null()); 877 878 base::FilePath* cache_file_path = new base::FilePath; 879 base::PostTaskAndReplyWithResult( 880 blocking_task_runner_, 881 FROM_HERE, 882 base::Bind(&MarkCacheFileAsMountedInternal, 883 resource_metadata_, 884 cache_, 885 drive_file_path, 886 cache_file_path), 887 base::Bind(&RunMarkMountedCallback, 888 callback, 889 base::Owned(cache_file_path))); 890 } 891 892 void FileSystem::MarkCacheFileAsUnmounted( 893 const base::FilePath& cache_file_path, 894 const FileOperationCallback& callback) { 895 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 896 DCHECK(!callback.is_null()); 897 898 if (!cache_->IsUnderFileCacheDirectory(cache_file_path)) { 899 callback.Run(FILE_ERROR_FAILED); 900 return; 901 } 902 903 base::PostTaskAndReplyWithResult( 904 blocking_task_runner_, 905 FROM_HERE, 906 base::Bind(&internal::FileCache::MarkAsUnmounted, 907 base::Unretained(cache_), 908 cache_file_path), 909 callback); 910 } 911 912 void FileSystem::AddPermission(const base::FilePath& drive_file_path, 913 const std::string& email, 914 google_apis::drive::PermissionRole role, 915 const FileOperationCallback& callback) { 916 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 917 DCHECK(!callback.is_null()); 918 919 // Resolve the resource id. 920 ResourceEntry* const entry = new ResourceEntry; 921 base::PostTaskAndReplyWithResult( 922 blocking_task_runner_.get(), 923 FROM_HERE, 924 base::Bind(&internal::ResourceMetadata::GetResourceEntryByPath, 925 base::Unretained(resource_metadata_), 926 drive_file_path, 927 entry), 928 base::Bind(&FileSystem::AddPermissionAfterGetResourceEntry, 929 weak_ptr_factory_.GetWeakPtr(), 930 email, 931 role, 932 callback, 933 base::Owned(entry))); 934 } 935 936 void FileSystem::AddPermissionAfterGetResourceEntry( 937 const std::string& email, 938 google_apis::drive::PermissionRole role, 939 const FileOperationCallback& callback, 940 ResourceEntry* entry, 941 FileError error) { 942 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 943 944 if (error != FILE_ERROR_OK) { 945 callback.Run(error); 946 return; 947 } 948 949 scheduler_->AddPermission( 950 entry->resource_id(), 951 email, 952 role, 953 base::Bind(&RunFileOperationCallbackAsEntryActionCallback, callback)); 954 } 955 956 void FileSystem::OpenFile(const base::FilePath& file_path, 957 OpenMode open_mode, 958 const std::string& mime_type, 959 const OpenFileCallback& callback) { 960 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 961 DCHECK(!callback.is_null()); 962 963 open_file_operation_->OpenFile(file_path, open_mode, mime_type, callback); 964 } 965 966 void FileSystem::GetPathFromResourceId(const std::string& resource_id, 967 const GetFilePathCallback& callback) { 968 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 969 DCHECK(!callback.is_null()); 970 971 base::FilePath* const file_path = new base::FilePath(); 972 base::PostTaskAndReplyWithResult( 973 blocking_task_runner_, 974 FROM_HERE, 975 base::Bind(&GetPathFromResourceIdOnBlockingPool, 976 resource_metadata_, 977 resource_id, 978 file_path), 979 base::Bind(&GetPathFromResourceIdAfterGetPath, 980 base::Owned(file_path), 981 callback)); 982 } 983 } // namespace drive 984