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.
5 #include "chrome/browser/chromeos/drive/file_system.h"
8 #include "base/file_util.h"
9 #include "base/platform_file.h"
10 #include "base/prefs/pref_service.h"
11 #include "chrome/browser/chromeos/drive/change_list_loader.h"
12 #include "chrome/browser/chromeos/drive/directory_loader.h"
13 #include "chrome/browser/chromeos/drive/drive.pb.h"
14 #include "chrome/browser/chromeos/drive/file_cache.h"
15 #include "chrome/browser/chromeos/drive/file_system/copy_operation.h"
16 #include "chrome/browser/chromeos/drive/file_system/create_directory_operation.h"
17 #include "chrome/browser/chromeos/drive/file_system/create_file_operation.h"
18 #include "chrome/browser/chromeos/drive/file_system/download_operation.h"
19 #include "chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.h"
20 #include "chrome/browser/chromeos/drive/file_system/move_operation.h"
21 #include "chrome/browser/chromeos/drive/file_system/open_file_operation.h"
22 #include "chrome/browser/chromeos/drive/file_system/remove_operation.h"
23 #include "chrome/browser/chromeos/drive/file_system/search_operation.h"
24 #include "chrome/browser/chromeos/drive/file_system/touch_operation.h"
25 #include "chrome/browser/chromeos/drive/file_system/truncate_operation.h"
26 #include "chrome/browser/chromeos/drive/file_system_observer.h"
27 #include "chrome/browser/chromeos/drive/file_system_util.h"
28 #include "chrome/browser/chromeos/drive/job_scheduler.h"
29 #include "chrome/browser/chromeos/drive/remove_stale_cache_files.h"
30 #include "chrome/browser/chromeos/drive/resource_entry_conversion.h"
31 #include "chrome/browser/chromeos/drive/search_metadata.h"
32 #include "chrome/browser/chromeos/drive/sync_client.h"
33 #include "chrome/browser/drive/drive_service_interface.h"
34 #include "chrome/common/pref_names.h"
35 #include "content/public/browser/browser_thread.h"
36 #include "google_apis/drive/drive_api_parser.h"
38 using content::BrowserThread;
43 // Gets a ResourceEntry from the metadata, and overwrites its file info when the
44 // cached file is dirty.
45 FileError GetLocallyStoredResourceEntry(
46 internal::ResourceMetadata* resource_metadata,
47 internal::FileCache* cache,
48 const base::FilePath& file_path,
49 ResourceEntry* entry) {
51 FileError error = resource_metadata->GetIdByPath(file_path, &local_id);
52 if (error != FILE_ERROR_OK)
55 error = resource_metadata->GetResourceEntryById(local_id, entry);
56 if (error != FILE_ERROR_OK)
59 // For entries that will never be cached, use the original resource entry
61 if (!entry->has_file_specific_info() ||
62 entry->file_specific_info().is_hosted_document())
65 // When cache is not found, use the original resource entry as is.
66 FileCacheEntry cache_entry;
67 if (!cache->GetCacheEntry(local_id, &cache_entry))
70 // When cache is non-dirty and obsolete (old hash), use the original entry.
71 if (!cache_entry.is_dirty() &&
72 entry->file_specific_info().md5() != cache_entry.md5())
75 // If there's a valid cache, obtain the file info from the cache file itself.
76 base::FilePath local_cache_path;
77 error = cache->GetFile(local_id, &local_cache_path);
78 if (error != FILE_ERROR_OK)
81 base::File::Info file_info;
82 if (!base::GetFileInfo(local_cache_path, &file_info))
83 return FILE_ERROR_NOT_FOUND;
85 // TODO(hashimoto): crbug.com/346625. Also reflect timestamps.
86 entry->mutable_file_info()->set_size(file_info.size);
90 // Runs the callback with parameters.
91 void RunGetResourceEntryCallback(const GetResourceEntryCallback& callback,
92 scoped_ptr<ResourceEntry> entry,
94 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
95 DCHECK(!callback.is_null());
97 if (error != FILE_ERROR_OK)
99 callback.Run(error, entry.Pass());
102 // Used to implement Pin().
103 FileError PinInternal(internal::ResourceMetadata* resource_metadata,
104 internal::FileCache* cache,
105 const base::FilePath& file_path,
106 std::string* local_id) {
107 FileError error = resource_metadata->GetIdByPath(file_path, local_id);
108 if (error != FILE_ERROR_OK)
112 error = resource_metadata->GetResourceEntryById(*local_id, &entry);
113 if (error != FILE_ERROR_OK)
116 // TODO(hashimoto): Support pinning directories. crbug.com/127831
117 if (entry.file_info().is_directory())
118 return FILE_ERROR_NOT_A_FILE;
120 return cache->Pin(*local_id);
123 // Used to implement Unpin().
124 FileError UnpinInternal(internal::ResourceMetadata* resource_metadata,
125 internal::FileCache* cache,
126 const base::FilePath& file_path,
127 std::string* local_id) {
128 FileError error = resource_metadata->GetIdByPath(file_path, local_id);
129 if (error != FILE_ERROR_OK)
132 return cache->Unpin(*local_id);
135 // Used to implement MarkCacheFileAsMounted().
136 FileError MarkCacheFileAsMountedInternal(
137 internal::ResourceMetadata* resource_metadata,
138 internal::FileCache* cache,
139 const base::FilePath& drive_file_path,
140 base::FilePath* cache_file_path) {
141 std::string local_id;
142 FileError error = resource_metadata->GetIdByPath(drive_file_path, &local_id);
143 if (error != FILE_ERROR_OK)
146 return cache->MarkAsMounted(local_id, cache_file_path);
149 // Runs the callback with arguments.
150 void RunMarkMountedCallback(const MarkMountedCallback& callback,
151 base::FilePath* cache_file_path,
153 DCHECK(!callback.is_null());
154 callback.Run(error, *cache_file_path);
157 // Used to implement GetCacheEntry.
158 bool GetCacheEntryInternal(internal::ResourceMetadata* resource_metadata,
159 internal::FileCache* cache,
160 const base::FilePath& drive_file_path,
161 FileCacheEntry* cache_entry) {
163 if (resource_metadata->GetIdByPath(drive_file_path, &id) != FILE_ERROR_OK)
166 return cache->GetCacheEntry(id, cache_entry);
169 // Runs the callback with arguments.
170 void RunGetCacheEntryCallback(const GetCacheEntryCallback& callback,
171 const FileCacheEntry* cache_entry,
173 DCHECK(!callback.is_null());
174 callback.Run(success, *cache_entry);
177 // Callback for ResourceMetadata::GetLargestChangestamp.
178 // |callback| must not be null.
179 void OnGetLargestChangestamp(
180 FileSystemMetadata metadata, // Will be modified.
181 const GetFilesystemMetadataCallback& callback,
182 int64 largest_changestamp) {
183 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
184 DCHECK(!callback.is_null());
186 metadata.largest_changestamp = largest_changestamp;
187 callback.Run(metadata);
190 // Thin adapter to map GetFileCallback to FileOperationCallback.
191 void GetFileCallbackToFileOperationCallbackAdapter(
192 const FileOperationCallback& callback,
194 const base::FilePath& unused_file_path,
195 scoped_ptr<ResourceEntry> unused_entry) {
199 // Clears |resource_metadata| and |cache|.
200 FileError ResetOnBlockingPool(internal::ResourceMetadata* resource_metadata,
201 internal::FileCache* cache) {
202 FileError error = resource_metadata->Reset();
203 if (error != FILE_ERROR_OK)
205 return cache->ClearAll() ? FILE_ERROR_OK : FILE_ERROR_FAILED;
208 // Part of GetPathFromResourceId().
209 // Obtains |file_path| from |resource_id|. The function should be run on the
211 FileError GetPathFromResourceIdOnBlockingPool(
212 internal::ResourceMetadata* resource_metadata,
213 const std::string& resource_id,
214 base::FilePath* file_path) {
215 std::string local_id;
216 const FileError error =
217 resource_metadata->GetIdByResourceId(resource_id, &local_id);
218 *file_path = error == FILE_ERROR_OK ?
219 resource_metadata->GetFilePath(local_id) : base::FilePath();
223 // Part of GetPathFromResourceId().
224 // Called when GetPathFromResourceIdInBlockingPool is complete.
225 void GetPathFromResourceIdAfterGetPath(base::FilePath* file_path,
226 const GetFilePathCallback& callback,
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
229 callback.Run(error, *file_path);
232 // Excludes hosted documents from the given entries.
233 // Used to implement ReadDirectory().
234 void FilterHostedDocuments(const ReadDirectoryEntriesCallback& callback,
235 scoped_ptr<ResourceEntryVector> entries) {
236 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
237 DCHECK(!callback.is_null());
240 // TODO(kinaba): Stop handling hide_hosted_docs here. crbug.com/256520.
241 scoped_ptr<ResourceEntryVector> filtered(new ResourceEntryVector);
242 for (size_t i = 0; i < entries->size(); ++i) {
243 if (entries->at(i).file_specific_info().is_hosted_document()) {
246 filtered->push_back(entries->at(i));
248 entries.swap(filtered);
250 callback.Run(entries.Pass());
253 // Adapter for using FileOperationCallback as google_apis::EntryActionCallback.
254 void RunFileOperationCallbackAsEntryActionCallback(
255 const FileOperationCallback& callback,
256 google_apis::GDataErrorCode error) {
257 callback.Run(GDataToFileError(error));
262 struct FileSystem::CreateDirectoryParams {
263 base::FilePath directory_path;
266 FileOperationCallback callback;
269 FileSystem::FileSystem(
270 PrefService* pref_service,
272 internal::FileCache* cache,
273 DriveServiceInterface* drive_service,
274 JobScheduler* scheduler,
275 internal::ResourceMetadata* resource_metadata,
276 base::SequencedTaskRunner* blocking_task_runner,
277 const base::FilePath& temporary_file_directory)
278 : pref_service_(pref_service),
281 drive_service_(drive_service),
282 scheduler_(scheduler),
283 resource_metadata_(resource_metadata),
284 last_update_check_error_(FILE_ERROR_OK),
285 blocking_task_runner_(blocking_task_runner),
286 temporary_file_directory_(temporary_file_directory),
287 weak_ptr_factory_(this) {
288 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
293 FileSystem::~FileSystem() {
294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
296 directory_loader_->RemoveObserver(this);
297 change_list_loader_->RemoveObserver(this);
300 void FileSystem::Reset(const FileOperationCallback& callback) {
301 // Discard the current loader and operation objects and renew them. This is to
302 // avoid that changes initiated before the metadata reset is applied after the
303 // reset, which may cause an inconsistent state.
304 // TODO(kinaba): callbacks held in the subcomponents are discarded. We might
305 // want to have a way to abort and flush callbacks in in-flight operations.
308 base::PostTaskAndReplyWithResult(
309 blocking_task_runner_,
311 base::Bind(&ResetOnBlockingPool, resource_metadata_, cache_),
315 void FileSystem::ResetComponents() {
316 file_system::OperationObserver* observer = this;
318 about_resource_loader_.reset(new internal::AboutResourceLoader(scheduler_));
319 loader_controller_.reset(new internal::LoaderController);
320 change_list_loader_.reset(new internal::ChangeListLoader(
322 blocking_task_runner_.get(),
325 about_resource_loader_.get(),
326 loader_controller_.get()));
327 change_list_loader_->AddObserver(this);
328 directory_loader_.reset(new internal::DirectoryLoader(
330 blocking_task_runner_.get(),
334 about_resource_loader_.get(),
335 loader_controller_.get()));
336 directory_loader_->AddObserver(this);
338 sync_client_.reset(new internal::SyncClient(blocking_task_runner_.get(),
343 loader_controller_.get(),
344 temporary_file_directory_));
346 copy_operation_.reset(
347 new file_system::CopyOperation(
348 blocking_task_runner_.get(),
353 drive_service_->GetResourceIdCanonicalizer()));
354 create_directory_operation_.reset(new file_system::CreateDirectoryOperation(
355 blocking_task_runner_.get(), observer, resource_metadata_));
356 create_file_operation_.reset(
357 new file_system::CreateFileOperation(blocking_task_runner_.get(),
359 resource_metadata_));
360 move_operation_.reset(
361 new file_system::MoveOperation(blocking_task_runner_.get(),
363 resource_metadata_));
364 open_file_operation_.reset(
365 new file_system::OpenFileOperation(blocking_task_runner_.get(),
370 temporary_file_directory_));
371 remove_operation_.reset(
372 new file_system::RemoveOperation(blocking_task_runner_.get(),
376 touch_operation_.reset(new file_system::TouchOperation(
377 blocking_task_runner_.get(), observer, resource_metadata_));
378 truncate_operation_.reset(
379 new file_system::TruncateOperation(blocking_task_runner_.get(),
384 temporary_file_directory_));
385 download_operation_.reset(
386 new file_system::DownloadOperation(blocking_task_runner_.get(),
391 temporary_file_directory_));
392 search_operation_.reset(new file_system::SearchOperation(
393 blocking_task_runner_.get(), scheduler_, resource_metadata_,
394 loader_controller_.get()));
395 get_file_for_saving_operation_.reset(
396 new file_system::GetFileForSavingOperation(logger_,
397 blocking_task_runner_.get(),
402 temporary_file_directory_));
405 void FileSystem::CheckForUpdates() {
406 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
407 DVLOG(1) << "CheckForUpdates";
409 change_list_loader_->CheckForUpdates(
410 base::Bind(&FileSystem::OnUpdateChecked, weak_ptr_factory_.GetWeakPtr()));
413 void FileSystem::OnUpdateChecked(FileError error) {
414 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
415 DVLOG(1) << "CheckForUpdates finished: " << FileErrorToString(error);
416 last_update_check_time_ = base::Time::Now();
417 last_update_check_error_ = error;
420 void FileSystem::AddObserver(FileSystemObserver* observer) {
421 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
422 observers_.AddObserver(observer);
425 void FileSystem::RemoveObserver(FileSystemObserver* observer) {
426 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
427 observers_.RemoveObserver(observer);
430 void FileSystem::TransferFileFromLocalToRemote(
431 const base::FilePath& local_src_file_path,
432 const base::FilePath& remote_dest_file_path,
433 const FileOperationCallback& callback) {
434 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
435 DCHECK(!callback.is_null());
436 copy_operation_->TransferFileFromLocalToRemote(local_src_file_path,
437 remote_dest_file_path,
441 void FileSystem::Copy(const base::FilePath& src_file_path,
442 const base::FilePath& dest_file_path,
443 bool preserve_last_modified,
444 const FileOperationCallback& callback) {
445 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
446 DCHECK(!callback.is_null());
447 copy_operation_->Copy(
448 src_file_path, dest_file_path, preserve_last_modified, callback);
451 void FileSystem::Move(const base::FilePath& src_file_path,
452 const base::FilePath& dest_file_path,
453 const FileOperationCallback& callback) {
454 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
455 DCHECK(!callback.is_null());
456 move_operation_->Move(src_file_path, dest_file_path, callback);
459 void FileSystem::Remove(const base::FilePath& file_path,
461 const FileOperationCallback& callback) {
462 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
463 DCHECK(!callback.is_null());
464 remove_operation_->Remove(file_path, is_recursive, callback);
467 void FileSystem::CreateDirectory(
468 const base::FilePath& directory_path,
471 const FileOperationCallback& callback) {
472 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
473 DCHECK(!callback.is_null());
475 CreateDirectoryParams params;
476 params.directory_path = directory_path;
477 params.is_exclusive = is_exclusive;
478 params.is_recursive = is_recursive;
479 params.callback = callback;
481 // Ensure its parent directory is loaded to the local metadata.
482 ReadDirectory(directory_path.DirName(),
483 ReadDirectoryEntriesCallback(),
484 base::Bind(&FileSystem::CreateDirectoryAfterRead,
485 weak_ptr_factory_.GetWeakPtr(), params));
488 void FileSystem::CreateDirectoryAfterRead(const CreateDirectoryParams& params,
490 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
491 DCHECK(!params.callback.is_null());
493 DVLOG_IF(1, error != FILE_ERROR_OK) << "ReadDirectory failed. "
494 << FileErrorToString(error);
496 create_directory_operation_->CreateDirectory(
497 params.directory_path, params.is_exclusive, params.is_recursive,
501 void FileSystem::CreateFile(const base::FilePath& file_path,
503 const std::string& mime_type,
504 const FileOperationCallback& callback) {
505 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
506 DCHECK(!callback.is_null());
507 create_file_operation_->CreateFile(
508 file_path, is_exclusive, mime_type, callback);
511 void FileSystem::TouchFile(const base::FilePath& file_path,
512 const base::Time& last_access_time,
513 const base::Time& last_modified_time,
514 const FileOperationCallback& callback) {
515 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
516 DCHECK(!callback.is_null());
517 touch_operation_->TouchFile(
518 file_path, last_access_time, last_modified_time, callback);
521 void FileSystem::TruncateFile(const base::FilePath& file_path,
523 const FileOperationCallback& callback) {
524 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
525 DCHECK(!callback.is_null());
526 truncate_operation_->Truncate(file_path, length, callback);
529 void FileSystem::Pin(const base::FilePath& file_path,
530 const FileOperationCallback& callback) {
531 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
532 DCHECK(!callback.is_null());
534 std::string* local_id = new std::string;
535 base::PostTaskAndReplyWithResult(
536 blocking_task_runner_,
538 base::Bind(&PinInternal, resource_metadata_, cache_, file_path, local_id),
539 base::Bind(&FileSystem::FinishPin,
540 weak_ptr_factory_.GetWeakPtr(),
542 base::Owned(local_id)));
545 void FileSystem::FinishPin(const FileOperationCallback& callback,
546 const std::string* local_id,
548 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
549 DCHECK(!callback.is_null());
551 if (error == FILE_ERROR_OK)
552 sync_client_->AddFetchTask(*local_id);
556 void FileSystem::Unpin(const base::FilePath& file_path,
557 const FileOperationCallback& callback) {
558 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
559 DCHECK(!callback.is_null());
561 std::string* local_id = new std::string;
562 base::PostTaskAndReplyWithResult(
563 blocking_task_runner_,
565 base::Bind(&UnpinInternal,
570 base::Bind(&FileSystem::FinishUnpin,
571 weak_ptr_factory_.GetWeakPtr(),
573 base::Owned(local_id)));
576 void FileSystem::FinishUnpin(const FileOperationCallback& callback,
577 const std::string* local_id,
579 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
580 DCHECK(!callback.is_null());
582 if (error == FILE_ERROR_OK)
583 sync_client_->RemoveFetchTask(*local_id);
587 void FileSystem::GetFile(const base::FilePath& file_path,
588 const GetFileCallback& callback) {
589 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
590 DCHECK(!callback.is_null());
592 download_operation_->EnsureFileDownloadedByPath(
594 ClientContext(USER_INITIATED),
595 GetFileContentInitializedCallback(),
596 google_apis::GetContentCallback(),
600 void FileSystem::GetFileForSaving(const base::FilePath& file_path,
601 const GetFileCallback& callback) {
602 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
603 DCHECK(!callback.is_null());
605 get_file_for_saving_operation_->GetFileForSaving(file_path, callback);
608 base::Closure FileSystem::GetFileContent(
609 const base::FilePath& file_path,
610 const GetFileContentInitializedCallback& initialized_callback,
611 const google_apis::GetContentCallback& get_content_callback,
612 const FileOperationCallback& completion_callback) {
613 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
614 DCHECK(!initialized_callback.is_null());
615 DCHECK(!get_content_callback.is_null());
616 DCHECK(!completion_callback.is_null());
618 return download_operation_->EnsureFileDownloadedByPath(
620 ClientContext(USER_INITIATED),
621 initialized_callback,
622 get_content_callback,
623 base::Bind(&GetFileCallbackToFileOperationCallbackAdapter,
624 completion_callback));
627 void FileSystem::GetResourceEntry(
628 const base::FilePath& file_path,
629 const GetResourceEntryCallback& callback) {
630 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
631 DCHECK(!callback.is_null());
633 ReadDirectory(file_path.DirName(),
634 ReadDirectoryEntriesCallback(),
635 base::Bind(&FileSystem::GetResourceEntryAfterRead,
636 weak_ptr_factory_.GetWeakPtr(),
641 void FileSystem::GetResourceEntryAfterRead(
642 const base::FilePath& file_path,
643 const GetResourceEntryCallback& callback,
645 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
646 DCHECK(!callback.is_null());
648 DVLOG_IF(1, error != FILE_ERROR_OK) << "ReadDirectory failed. "
649 << FileErrorToString(error);
651 scoped_ptr<ResourceEntry> entry(new ResourceEntry);
652 ResourceEntry* entry_ptr = entry.get();
653 base::PostTaskAndReplyWithResult(
654 blocking_task_runner_,
656 base::Bind(&GetLocallyStoredResourceEntry,
661 base::Bind(&RunGetResourceEntryCallback, callback, base::Passed(&entry)));
664 void FileSystem::ReadDirectory(
665 const base::FilePath& directory_path,
666 const ReadDirectoryEntriesCallback& entries_callback_in,
667 const FileOperationCallback& completion_callback) {
668 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
669 DCHECK(!completion_callback.is_null());
671 const bool hide_hosted_docs =
672 pref_service_->GetBoolean(prefs::kDisableDriveHostedFiles);
673 ReadDirectoryEntriesCallback entries_callback = entries_callback_in;
674 if (!entries_callback.is_null() && hide_hosted_docs)
675 entries_callback = base::Bind(&FilterHostedDocuments, entries_callback);
677 directory_loader_->ReadDirectory(
678 directory_path, entries_callback, completion_callback);
680 // Also start loading all of the user's contents.
681 change_list_loader_->LoadIfNeeded(
682 base::Bind(&util::EmptyFileOperationCallback));
685 void FileSystem::GetAvailableSpace(
686 const GetAvailableSpaceCallback& callback) {
687 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
688 DCHECK(!callback.is_null());
690 about_resource_loader_->GetAboutResource(
691 base::Bind(&FileSystem::OnGetAboutResource,
692 weak_ptr_factory_.GetWeakPtr(),
696 void FileSystem::OnGetAboutResource(
697 const GetAvailableSpaceCallback& callback,
698 google_apis::GDataErrorCode status,
699 scoped_ptr<google_apis::AboutResource> about_resource) {
700 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
701 DCHECK(!callback.is_null());
703 FileError error = GDataToFileError(status);
704 if (error != FILE_ERROR_OK) {
705 callback.Run(error, -1, -1);
708 DCHECK(about_resource);
710 callback.Run(FILE_ERROR_OK,
711 about_resource->quota_bytes_total(),
712 about_resource->quota_bytes_used());
715 void FileSystem::GetShareUrl(const base::FilePath& file_path,
716 const GURL& embed_origin,
717 const GetShareUrlCallback& callback) {
718 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
719 DCHECK(!callback.is_null());
721 // Resolve the resource id.
722 ResourceEntry* entry = new ResourceEntry;
723 base::PostTaskAndReplyWithResult(
724 blocking_task_runner_.get(),
726 base::Bind(&internal::ResourceMetadata::GetResourceEntryByPath,
727 base::Unretained(resource_metadata_),
730 base::Bind(&FileSystem::GetShareUrlAfterGetResourceEntry,
731 weak_ptr_factory_.GetWeakPtr(),
735 base::Owned(entry)));
738 void FileSystem::GetShareUrlAfterGetResourceEntry(
739 const base::FilePath& file_path,
740 const GURL& embed_origin,
741 const GetShareUrlCallback& callback,
742 ResourceEntry* entry,
744 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
745 DCHECK(!callback.is_null());
747 if (error != FILE_ERROR_OK) {
748 callback.Run(error, GURL());
751 if (entry->resource_id().empty()) {
752 // This entry does not exist on the server. Just return.
753 callback.Run(FILE_ERROR_FAILED, GURL());
757 scheduler_->GetShareUrl(
758 entry->resource_id(),
760 ClientContext(USER_INITIATED),
761 base::Bind(&FileSystem::OnGetResourceEntryForGetShareUrl,
762 weak_ptr_factory_.GetWeakPtr(),
766 void FileSystem::OnGetResourceEntryForGetShareUrl(
767 const GetShareUrlCallback& callback,
768 google_apis::GDataErrorCode status,
769 const GURL& share_url) {
770 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
771 DCHECK(!callback.is_null());
773 FileError error = GDataToFileError(status);
774 if (error != FILE_ERROR_OK) {
775 callback.Run(error, GURL());
779 if (share_url.is_empty()) {
780 callback.Run(FILE_ERROR_FAILED, GURL());
784 callback.Run(FILE_ERROR_OK, share_url);
787 void FileSystem::Search(const std::string& search_query,
788 const GURL& next_link,
789 const SearchCallback& callback) {
790 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
791 DCHECK(!callback.is_null());
792 search_operation_->Search(search_query, next_link, callback);
795 void FileSystem::SearchMetadata(const std::string& query,
797 int at_most_num_matches,
798 const SearchMetadataCallback& callback) {
799 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
801 // TODO(satorux): Stop handling hide_hosted_docs here. crbug.com/256520.
802 if (pref_service_->GetBoolean(prefs::kDisableDriveHostedFiles))
803 options |= SEARCH_METADATA_EXCLUDE_HOSTED_DOCUMENTS;
805 drive::internal::SearchMetadata(blocking_task_runner_,
813 void FileSystem::OnDirectoryChangedByOperation(
814 const base::FilePath& directory_path) {
815 OnDirectoryChanged(directory_path);
818 void FileSystem::OnEntryUpdatedByOperation(const std::string& local_id) {
819 sync_client_->AddUpdateTask(ClientContext(USER_INITIATED), local_id);
822 void FileSystem::OnDriveSyncError(file_system::DriveSyncErrorType type,
823 const std::string& local_id) {
824 base::PostTaskAndReplyWithResult(
825 blocking_task_runner_,
827 base::Bind(&internal::ResourceMetadata::GetFilePath,
828 base::Unretained(resource_metadata_),
830 base::Bind(&FileSystem::OnDriveSyncErrorAfterGetFilePath,
831 weak_ptr_factory_.GetWeakPtr(),
835 void FileSystem::OnDriveSyncErrorAfterGetFilePath(
836 file_system::DriveSyncErrorType type,
837 const base::FilePath& path) {
840 FOR_EACH_OBSERVER(FileSystemObserver,
842 OnDriveSyncError(type, path));
845 void FileSystem::OnDirectoryChanged(const base::FilePath& directory_path) {
846 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
848 FOR_EACH_OBSERVER(FileSystemObserver, observers_,
849 OnDirectoryChanged(directory_path));
852 void FileSystem::OnLoadFromServerComplete() {
853 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
855 sync_client_->StartCheckingExistingPinnedFiles();
858 void FileSystem::OnInitialLoadComplete() {
859 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
861 blocking_task_runner_->PostTask(FROM_HERE,
862 base::Bind(&internal::RemoveStaleCacheFiles,
864 resource_metadata_));
865 sync_client_->StartProcessingBacklog();
868 void FileSystem::GetMetadata(
869 const GetFilesystemMetadataCallback& callback) {
870 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
871 DCHECK(!callback.is_null());
873 FileSystemMetadata metadata;
874 metadata.refreshing = change_list_loader_->IsRefreshing();
876 // Metadata related to delta update.
877 metadata.last_update_check_time = last_update_check_time_;
878 metadata.last_update_check_error = last_update_check_error_;
880 base::PostTaskAndReplyWithResult(
881 blocking_task_runner_,
883 base::Bind(&internal::ResourceMetadata::GetLargestChangestamp,
884 base::Unretained(resource_metadata_)),
885 base::Bind(&OnGetLargestChangestamp, metadata, callback));
888 void FileSystem::MarkCacheFileAsMounted(
889 const base::FilePath& drive_file_path,
890 const MarkMountedCallback& callback) {
891 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
892 DCHECK(!callback.is_null());
894 base::FilePath* cache_file_path = new base::FilePath;
895 base::PostTaskAndReplyWithResult(
896 blocking_task_runner_,
898 base::Bind(&MarkCacheFileAsMountedInternal,
903 base::Bind(&RunMarkMountedCallback,
905 base::Owned(cache_file_path)));
908 void FileSystem::MarkCacheFileAsUnmounted(
909 const base::FilePath& cache_file_path,
910 const FileOperationCallback& callback) {
911 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
912 DCHECK(!callback.is_null());
914 if (!cache_->IsUnderFileCacheDirectory(cache_file_path)) {
915 callback.Run(FILE_ERROR_FAILED);
919 base::PostTaskAndReplyWithResult(
920 blocking_task_runner_,
922 base::Bind(&internal::FileCache::MarkAsUnmounted,
923 base::Unretained(cache_),
928 void FileSystem::GetCacheEntry(
929 const base::FilePath& drive_file_path,
930 const GetCacheEntryCallback& callback) {
931 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
932 DCHECK(!callback.is_null());
934 FileCacheEntry* cache_entry = new FileCacheEntry;
935 base::PostTaskAndReplyWithResult(
936 blocking_task_runner_,
938 base::Bind(&GetCacheEntryInternal,
943 base::Bind(&RunGetCacheEntryCallback,
945 base::Owned(cache_entry)));
948 void FileSystem::AddPermission(const base::FilePath& drive_file_path,
949 const std::string& email,
950 google_apis::drive::PermissionRole role,
951 const FileOperationCallback& callback) {
952 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
953 DCHECK(!callback.is_null());
955 // Resolve the resource id.
956 ResourceEntry* const entry = new ResourceEntry;
957 base::PostTaskAndReplyWithResult(
958 blocking_task_runner_.get(),
960 base::Bind(&internal::ResourceMetadata::GetResourceEntryByPath,
961 base::Unretained(resource_metadata_),
964 base::Bind(&FileSystem::AddPermissionAfterGetResourceEntry,
965 weak_ptr_factory_.GetWeakPtr(),
969 base::Owned(entry)));
972 void FileSystem::AddPermissionAfterGetResourceEntry(
973 const std::string& email,
974 google_apis::drive::PermissionRole role,
975 const FileOperationCallback& callback,
976 ResourceEntry* entry,
978 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
980 if (error != FILE_ERROR_OK) {
985 scheduler_->AddPermission(
986 entry->resource_id(),
989 base::Bind(&RunFileOperationCallbackAsEntryActionCallback, callback));
992 void FileSystem::OpenFile(const base::FilePath& file_path,
994 const std::string& mime_type,
995 const OpenFileCallback& callback) {
996 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
997 DCHECK(!callback.is_null());
999 open_file_operation_->OpenFile(file_path, open_mode, mime_type, callback);
1002 void FileSystem::GetPathFromResourceId(const std::string& resource_id,
1003 const GetFilePathCallback& callback) {
1004 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1005 DCHECK(!callback.is_null());
1007 base::FilePath* const file_path = new base::FilePath();
1008 base::PostTaskAndReplyWithResult(
1009 blocking_task_runner_,
1011 base::Bind(&GetPathFromResourceIdOnBlockingPool,
1015 base::Bind(&GetPathFromResourceIdAfterGetPath,
1016 base::Owned(file_path),
1019 } // namespace drive