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 "components/drive/file_system.h"
8 #include "base/files/file_util.h"
9 #include "base/prefs/pref_service.h"
10 #include "components/drive/change_list_loader.h"
11 #include "components/drive/directory_loader.h"
12 #include "components/drive/drive.pb.h"
13 #include "components/drive/drive_pref_names.h"
14 #include "components/drive/file_cache.h"
15 #include "components/drive/file_change.h"
16 #include "components/drive/file_system/copy_operation.h"
17 #include "components/drive/file_system/create_directory_operation.h"
18 #include "components/drive/file_system/create_file_operation.h"
19 #include "components/drive/file_system/download_operation.h"
20 #include "components/drive/file_system/get_file_for_saving_operation.h"
21 #include "components/drive/file_system/move_operation.h"
22 #include "components/drive/file_system/open_file_operation.h"
23 #include "components/drive/file_system/remove_operation.h"
24 #include "components/drive/file_system/search_operation.h"
25 #include "components/drive/file_system/set_property_operation.h"
26 #include "components/drive/file_system/touch_operation.h"
27 #include "components/drive/file_system/truncate_operation.h"
28 #include "components/drive/file_system_core_util.h"
29 #include "components/drive/file_system_observer.h"
30 #include "components/drive/job_scheduler.h"
31 #include "components/drive/remove_stale_cache_files.h"
32 #include "components/drive/resource_entry_conversion.h"
33 #include "components/drive/search_metadata.h"
34 #include "components/drive/sync_client.h"
35 #include "google_apis/drive/drive_api_parser.h"
40 // Gets a ResourceEntry from the metadata, and overwrites its file info when the
41 // cached file is dirty.
42 FileError
GetLocallyStoredResourceEntry(
43 internal::ResourceMetadata
* resource_metadata
,
44 internal::FileCache
* cache
,
45 const base::FilePath
& file_path
,
46 ResourceEntry
* entry
) {
48 FileError error
= resource_metadata
->GetIdByPath(file_path
, &local_id
);
49 if (error
!= FILE_ERROR_OK
)
52 error
= resource_metadata
->GetResourceEntryById(local_id
, entry
);
53 if (error
!= FILE_ERROR_OK
)
56 // For entries that will never be cached, use the original resource entry
58 if (!entry
->has_file_specific_info() ||
59 entry
->file_specific_info().is_hosted_document())
62 // When cache is not found, use the original resource entry as is.
63 if (!entry
->file_specific_info().has_cache_state())
66 // When cache is non-dirty and obsolete (old hash), use the original entry.
67 if (!entry
->file_specific_info().cache_state().is_dirty() &&
68 entry
->file_specific_info().md5() !=
69 entry
->file_specific_info().cache_state().md5())
72 // If there's a valid cache, obtain the file info from the cache file itself.
73 base::FilePath local_cache_path
;
74 error
= cache
->GetFile(local_id
, &local_cache_path
);
75 if (error
!= FILE_ERROR_OK
)
78 base::File::Info file_info
;
79 if (!base::GetFileInfo(local_cache_path
, &file_info
))
80 return FILE_ERROR_NOT_FOUND
;
82 entry
->mutable_file_info()->set_size(file_info
.size
);
86 // Runs the callback with parameters.
87 void RunGetResourceEntryCallback(const GetResourceEntryCallback
& callback
,
88 scoped_ptr
<ResourceEntry
> entry
,
90 DCHECK(!callback
.is_null());
92 if (error
!= FILE_ERROR_OK
)
94 callback
.Run(error
, entry
.Pass());
97 // Used to implement Pin().
98 FileError
PinInternal(internal::ResourceMetadata
* resource_metadata
,
99 internal::FileCache
* cache
,
100 const base::FilePath
& file_path
,
101 std::string
* local_id
) {
102 FileError error
= resource_metadata
->GetIdByPath(file_path
, local_id
);
103 if (error
!= FILE_ERROR_OK
)
107 error
= resource_metadata
->GetResourceEntryById(*local_id
, &entry
);
108 if (error
!= FILE_ERROR_OK
)
111 // TODO(hashimoto): Support pinning directories. crbug.com/127831
112 if (entry
.file_info().is_directory())
113 return FILE_ERROR_NOT_A_FILE
;
115 return cache
->Pin(*local_id
);
118 // Used to implement Unpin().
119 FileError
UnpinInternal(internal::ResourceMetadata
* resource_metadata
,
120 internal::FileCache
* cache
,
121 const base::FilePath
& file_path
,
122 std::string
* local_id
) {
123 FileError error
= resource_metadata
->GetIdByPath(file_path
, local_id
);
124 if (error
!= FILE_ERROR_OK
)
127 return cache
->Unpin(*local_id
);
130 // Used to implement MarkCacheFileAsMounted().
131 FileError
MarkCacheFileAsMountedInternal(
132 internal::ResourceMetadata
* resource_metadata
,
133 internal::FileCache
* cache
,
134 const base::FilePath
& drive_file_path
,
135 base::FilePath
* cache_file_path
) {
136 std::string local_id
;
137 FileError error
= resource_metadata
->GetIdByPath(drive_file_path
, &local_id
);
138 if (error
!= FILE_ERROR_OK
)
141 return cache
->MarkAsMounted(local_id
, cache_file_path
);
144 // Runs the callback with arguments.
145 void RunMarkMountedCallback(const MarkMountedCallback
& callback
,
146 base::FilePath
* cache_file_path
,
148 DCHECK(!callback
.is_null());
149 callback
.Run(error
, *cache_file_path
);
152 // Callback for ResourceMetadata::GetLargestChangestamp.
153 // |callback| must not be null.
154 void OnGetLargestChangestamp(
155 FileSystemMetadata metadata
, // Will be modified.
156 const GetFilesystemMetadataCallback
& callback
,
157 const int64
* largest_changestamp
,
159 DCHECK(!callback
.is_null());
161 metadata
.largest_changestamp
= *largest_changestamp
;
162 callback
.Run(metadata
);
165 // Thin adapter to map GetFileCallback to FileOperationCallback.
166 void GetFileCallbackToFileOperationCallbackAdapter(
167 const FileOperationCallback
& callback
,
169 const base::FilePath
& unused_file_path
,
170 scoped_ptr
<ResourceEntry
> unused_entry
) {
174 // Clears |resource_metadata| and |cache|.
175 FileError
ResetOnBlockingPool(internal::ResourceMetadata
* resource_metadata
,
176 internal::FileCache
* cache
) {
177 FileError error
= resource_metadata
->Reset();
178 if (error
!= FILE_ERROR_OK
)
180 return cache
->ClearAll() ? FILE_ERROR_OK
: FILE_ERROR_FAILED
;
183 // Part of GetPathFromResourceId().
184 // Obtains |file_path| from |resource_id|. The function should be run on the
186 FileError
GetPathFromResourceIdOnBlockingPool(
187 internal::ResourceMetadata
* resource_metadata
,
188 const std::string
& resource_id
,
189 base::FilePath
* file_path
) {
190 std::string local_id
;
191 const FileError error
=
192 resource_metadata
->GetIdByResourceId(resource_id
, &local_id
);
193 if (error
!= FILE_ERROR_OK
)
195 return resource_metadata
->GetFilePath(local_id
, file_path
);
198 // Part of GetPathFromResourceId().
199 // Called when GetPathFromResourceIdInBlockingPool is complete.
200 void GetPathFromResourceIdAfterGetPath(base::FilePath
* file_path
,
201 const GetFilePathCallback
& callback
,
203 callback
.Run(error
, *file_path
);
206 bool FreeDiskSpaceIfNeededForOnBlockingPool(internal::FileCache
* cache
,
208 return cache
->FreeDiskSpaceIfNeededFor(num_bytes
);
211 uint64_t CalculateEvictableCacheSizeOnBlockingPool(internal::FileCache
* cache
) {
212 return cache
->CalculateEvictableCacheSize();
215 // Excludes hosted documents from the given entries.
216 // Used to implement ReadDirectory().
217 void FilterHostedDocuments(const ReadDirectoryEntriesCallback
& callback
,
218 scoped_ptr
<ResourceEntryVector
> entries
) {
219 DCHECK(!callback
.is_null());
222 // TODO(kinaba): Stop handling hide_hosted_docs here. crbug.com/256520.
223 scoped_ptr
<ResourceEntryVector
> filtered(new ResourceEntryVector
);
224 for (size_t i
= 0; i
< entries
->size(); ++i
) {
225 if (entries
->at(i
).file_specific_info().is_hosted_document()) {
228 filtered
->push_back(entries
->at(i
));
230 entries
.swap(filtered
);
232 callback
.Run(entries
.Pass());
235 // Adapter for using FileOperationCallback as google_apis::EntryActionCallback.
236 void RunFileOperationCallbackAsEntryActionCallback(
237 const FileOperationCallback
& callback
,
238 google_apis::DriveApiErrorCode error
) {
239 callback
.Run(GDataToFileError(error
));
242 // Checks if the |entry|'s hash is included in |hashes|.
243 bool CheckHashes(const std::set
<std::string
>& hashes
,
244 const ResourceEntry
& entry
) {
245 return hashes
.find(entry
.file_specific_info().md5()) != hashes
.end();
248 // Runs |callback| with |error| and the list of HashAndFilePath obtained from
249 // |original_result|.
250 void RunSearchByHashesCallback(
251 const SearchByHashesCallback
& callback
,
253 scoped_ptr
<MetadataSearchResultVector
> original_result
) {
254 std::vector
<HashAndFilePath
> result
;
255 if (error
!= FILE_ERROR_OK
) {
256 callback
.Run(error
, result
);
259 for (const auto& search_result
: *original_result
) {
260 HashAndFilePath hash_and_path
;
261 hash_and_path
.hash
= search_result
.md5
;
262 hash_and_path
.path
= search_result
.path
;
263 result
.push_back(hash_and_path
);
265 callback
.Run(FILE_ERROR_OK
, result
);
270 struct FileSystem::CreateDirectoryParams
{
271 base::FilePath directory_path
;
274 FileOperationCallback callback
;
277 FileSystem::FileSystem(PrefService
* pref_service
,
279 internal::FileCache
* cache
,
280 JobScheduler
* scheduler
,
281 internal::ResourceMetadata
* resource_metadata
,
282 base::SequencedTaskRunner
* blocking_task_runner
,
283 base::SingleThreadTaskRunner
* file_task_runner
,
284 const base::FilePath
& temporary_file_directory
)
285 : pref_service_(pref_service
),
288 scheduler_(scheduler
),
289 resource_metadata_(resource_metadata
),
290 last_update_check_error_(FILE_ERROR_OK
),
291 blocking_task_runner_(blocking_task_runner
),
292 file_task_runner_(file_task_runner
),
293 temporary_file_directory_(temporary_file_directory
),
294 weak_ptr_factory_(this) {
298 FileSystem::~FileSystem() {
299 DCHECK(thread_checker_
.CalledOnValidThread());
301 directory_loader_
->RemoveObserver(this);
302 change_list_loader_
->RemoveObserver(this);
305 void FileSystem::Reset(const FileOperationCallback
& callback
) {
306 // Discard the current loader and operation objects and renew them. This is to
307 // avoid that changes initiated before the metadata reset is applied after the
308 // reset, which may cause an inconsistent state.
309 // TODO(kinaba): callbacks held in the subcomponents are discarded. We might
310 // want to have a way to abort and flush callbacks in in-flight operations.
313 base::PostTaskAndReplyWithResult(
314 blocking_task_runner_
.get(),
316 base::Bind(&ResetOnBlockingPool
, resource_metadata_
, cache_
),
320 void FileSystem::ResetComponents() {
321 file_system::OperationDelegate
* delegate
= this;
323 about_resource_loader_
.reset(new internal::AboutResourceLoader(scheduler_
));
324 loader_controller_
.reset(new internal::LoaderController
);
325 change_list_loader_
.reset(new internal::ChangeListLoader(
327 blocking_task_runner_
.get(),
330 about_resource_loader_
.get(),
331 loader_controller_
.get()));
332 change_list_loader_
->AddObserver(this);
333 directory_loader_
.reset(new internal::DirectoryLoader(
335 blocking_task_runner_
.get(),
338 about_resource_loader_
.get(),
339 loader_controller_
.get()));
340 directory_loader_
->AddObserver(this);
342 sync_client_
.reset(new internal::SyncClient(blocking_task_runner_
.get(),
347 loader_controller_
.get(),
348 temporary_file_directory_
));
350 copy_operation_
.reset(
351 new file_system::CopyOperation(blocking_task_runner_
.get(),
356 create_directory_operation_
.reset(new file_system::CreateDirectoryOperation(
357 blocking_task_runner_
.get(), delegate
, resource_metadata_
));
358 create_file_operation_
.reset(
359 new file_system::CreateFileOperation(blocking_task_runner_
.get(),
361 resource_metadata_
));
362 move_operation_
.reset(
363 new file_system::MoveOperation(blocking_task_runner_
.get(),
365 resource_metadata_
));
366 open_file_operation_
.reset(
367 new file_system::OpenFileOperation(blocking_task_runner_
.get(),
372 temporary_file_directory_
));
373 remove_operation_
.reset(
374 new file_system::RemoveOperation(blocking_task_runner_
.get(),
378 touch_operation_
.reset(new file_system::TouchOperation(
379 blocking_task_runner_
.get(), delegate
, resource_metadata_
));
380 truncate_operation_
.reset(
381 new file_system::TruncateOperation(blocking_task_runner_
.get(),
386 temporary_file_directory_
));
387 download_operation_
.reset(
388 new file_system::DownloadOperation(blocking_task_runner_
.get(),
393 temporary_file_directory_
));
394 search_operation_
.reset(new file_system::SearchOperation(
395 blocking_task_runner_
.get(), scheduler_
, resource_metadata_
,
396 loader_controller_
.get()));
397 get_file_for_saving_operation_
.reset(
398 new file_system::GetFileForSavingOperation(
399 logger_
, blocking_task_runner_
.get(), file_task_runner_
.get(),
400 delegate
, scheduler_
, resource_metadata_
, cache_
,
401 temporary_file_directory_
));
402 set_property_operation_
.reset(new file_system::SetPropertyOperation(
403 blocking_task_runner_
.get(), delegate
, resource_metadata_
));
406 void FileSystem::CheckForUpdates() {
407 DCHECK(thread_checker_
.CalledOnValidThread());
408 DVLOG(1) << "CheckForUpdates";
410 change_list_loader_
->CheckForUpdates(
411 base::Bind(&FileSystem::OnUpdateChecked
, weak_ptr_factory_
.GetWeakPtr()));
414 void FileSystem::OnUpdateChecked(FileError error
) {
415 DCHECK(thread_checker_
.CalledOnValidThread());
416 DVLOG(1) << "CheckForUpdates finished: " << FileErrorToString(error
);
417 last_update_check_time_
= base::Time::Now();
418 last_update_check_error_
= error
;
421 void FileSystem::AddObserver(FileSystemObserver
* observer
) {
422 DCHECK(thread_checker_
.CalledOnValidThread());
423 observers_
.AddObserver(observer
);
426 void FileSystem::RemoveObserver(FileSystemObserver
* observer
) {
427 DCHECK(thread_checker_
.CalledOnValidThread());
428 observers_
.RemoveObserver(observer
);
431 void FileSystem::TransferFileFromLocalToRemote(
432 const base::FilePath
& local_src_file_path
,
433 const base::FilePath
& remote_dest_file_path
,
434 const FileOperationCallback
& callback
) {
435 DCHECK(thread_checker_
.CalledOnValidThread());
436 DCHECK(!callback
.is_null());
437 copy_operation_
->TransferFileFromLocalToRemote(local_src_file_path
,
438 remote_dest_file_path
,
442 void FileSystem::Copy(const base::FilePath
& src_file_path
,
443 const base::FilePath
& dest_file_path
,
444 bool preserve_last_modified
,
445 const FileOperationCallback
& callback
) {
446 DCHECK(thread_checker_
.CalledOnValidThread());
447 DCHECK(!callback
.is_null());
448 copy_operation_
->Copy(
449 src_file_path
, dest_file_path
, preserve_last_modified
, callback
);
452 void FileSystem::Move(const base::FilePath
& src_file_path
,
453 const base::FilePath
& dest_file_path
,
454 const FileOperationCallback
& callback
) {
455 DCHECK(thread_checker_
.CalledOnValidThread());
456 DCHECK(!callback
.is_null());
457 move_operation_
->Move(src_file_path
, dest_file_path
, callback
);
460 void FileSystem::Remove(const base::FilePath
& file_path
,
462 const FileOperationCallback
& callback
) {
463 DCHECK(thread_checker_
.CalledOnValidThread());
464 DCHECK(!callback
.is_null());
465 remove_operation_
->Remove(file_path
, is_recursive
, callback
);
468 void FileSystem::CreateDirectory(
469 const base::FilePath
& directory_path
,
472 const FileOperationCallback
& callback
) {
473 DCHECK(thread_checker_
.CalledOnValidThread());
474 DCHECK(!callback
.is_null());
476 CreateDirectoryParams params
;
477 params
.directory_path
= directory_path
;
478 params
.is_exclusive
= is_exclusive
;
479 params
.is_recursive
= is_recursive
;
480 params
.callback
= callback
;
482 // Ensure its parent directory is loaded to the local metadata.
483 ReadDirectory(directory_path
.DirName(),
484 ReadDirectoryEntriesCallback(),
485 base::Bind(&FileSystem::CreateDirectoryAfterRead
,
486 weak_ptr_factory_
.GetWeakPtr(), params
));
489 void FileSystem::CreateDirectoryAfterRead(const CreateDirectoryParams
& params
,
491 DCHECK(thread_checker_
.CalledOnValidThread());
492 DCHECK(!params
.callback
.is_null());
494 DVLOG_IF(1, error
!= FILE_ERROR_OK
) << "ReadDirectory failed. "
495 << FileErrorToString(error
);
497 create_directory_operation_
->CreateDirectory(
498 params
.directory_path
, params
.is_exclusive
, params
.is_recursive
,
502 void FileSystem::CreateFile(const base::FilePath
& file_path
,
504 const std::string
& mime_type
,
505 const FileOperationCallback
& callback
) {
506 DCHECK(thread_checker_
.CalledOnValidThread());
507 DCHECK(!callback
.is_null());
508 create_file_operation_
->CreateFile(
509 file_path
, is_exclusive
, mime_type
, callback
);
512 void FileSystem::TouchFile(const base::FilePath
& file_path
,
513 const base::Time
& last_access_time
,
514 const base::Time
& last_modified_time
,
515 const FileOperationCallback
& callback
) {
516 DCHECK(thread_checker_
.CalledOnValidThread());
517 DCHECK(!callback
.is_null());
518 touch_operation_
->TouchFile(
519 file_path
, last_access_time
, last_modified_time
, callback
);
522 void FileSystem::TruncateFile(const base::FilePath
& file_path
,
524 const FileOperationCallback
& callback
) {
525 DCHECK(thread_checker_
.CalledOnValidThread());
526 DCHECK(!callback
.is_null());
527 truncate_operation_
->Truncate(file_path
, length
, callback
);
530 void FileSystem::Pin(const base::FilePath
& file_path
,
531 const FileOperationCallback
& callback
) {
532 DCHECK(thread_checker_
.CalledOnValidThread());
533 DCHECK(!callback
.is_null());
535 std::string
* local_id
= new std::string
;
536 base::PostTaskAndReplyWithResult(
537 blocking_task_runner_
.get(),
539 base::Bind(&PinInternal
, resource_metadata_
, cache_
, file_path
, local_id
),
540 base::Bind(&FileSystem::FinishPin
,
541 weak_ptr_factory_
.GetWeakPtr(),
543 base::Owned(local_id
)));
546 void FileSystem::FinishPin(const FileOperationCallback
& callback
,
547 const std::string
* local_id
,
549 DCHECK(thread_checker_
.CalledOnValidThread());
550 DCHECK(!callback
.is_null());
552 if (error
== FILE_ERROR_OK
)
553 sync_client_
->AddFetchTask(*local_id
);
557 void FileSystem::Unpin(const base::FilePath
& file_path
,
558 const FileOperationCallback
& callback
) {
559 DCHECK(thread_checker_
.CalledOnValidThread());
560 DCHECK(!callback
.is_null());
562 std::string
* local_id
= new std::string
;
563 base::PostTaskAndReplyWithResult(
564 blocking_task_runner_
.get(),
567 &UnpinInternal
, resource_metadata_
, cache_
, file_path
, local_id
),
568 base::Bind(&FileSystem::FinishUnpin
,
569 weak_ptr_factory_
.GetWeakPtr(),
571 base::Owned(local_id
)));
574 void FileSystem::FinishUnpin(const FileOperationCallback
& callback
,
575 const std::string
* local_id
,
577 DCHECK(thread_checker_
.CalledOnValidThread());
578 DCHECK(!callback
.is_null());
580 if (error
== FILE_ERROR_OK
)
581 sync_client_
->RemoveFetchTask(*local_id
);
585 void FileSystem::GetFile(const base::FilePath
& file_path
,
586 const GetFileCallback
& callback
) {
587 DCHECK(thread_checker_
.CalledOnValidThread());
588 DCHECK(!callback
.is_null());
590 download_operation_
->EnsureFileDownloadedByPath(
592 ClientContext(USER_INITIATED
),
593 GetFileContentInitializedCallback(),
594 google_apis::GetContentCallback(),
598 void FileSystem::GetFileForSaving(const base::FilePath
& file_path
,
599 const GetFileCallback
& callback
) {
600 DCHECK(thread_checker_
.CalledOnValidThread());
601 DCHECK(!callback
.is_null());
603 get_file_for_saving_operation_
->GetFileForSaving(file_path
, callback
);
606 base::Closure
FileSystem::GetFileContent(
607 const base::FilePath
& file_path
,
608 const GetFileContentInitializedCallback
& initialized_callback
,
609 const google_apis::GetContentCallback
& get_content_callback
,
610 const FileOperationCallback
& completion_callback
) {
611 DCHECK(thread_checker_
.CalledOnValidThread());
612 DCHECK(!initialized_callback
.is_null());
613 DCHECK(!get_content_callback
.is_null());
614 DCHECK(!completion_callback
.is_null());
616 return download_operation_
->EnsureFileDownloadedByPath(
618 ClientContext(USER_INITIATED
),
619 initialized_callback
,
620 get_content_callback
,
621 base::Bind(&GetFileCallbackToFileOperationCallbackAdapter
,
622 completion_callback
));
625 void FileSystem::GetResourceEntry(
626 const base::FilePath
& file_path
,
627 const GetResourceEntryCallback
& callback
) {
628 DCHECK(thread_checker_
.CalledOnValidThread());
629 DCHECK(!callback
.is_null());
631 ReadDirectory(file_path
.DirName(),
632 ReadDirectoryEntriesCallback(),
633 base::Bind(&FileSystem::GetResourceEntryAfterRead
,
634 weak_ptr_factory_
.GetWeakPtr(),
639 void FileSystem::GetResourceEntryAfterRead(
640 const base::FilePath
& file_path
,
641 const GetResourceEntryCallback
& callback
,
643 DCHECK(thread_checker_
.CalledOnValidThread());
644 DCHECK(!callback
.is_null());
646 DVLOG_IF(1, error
!= FILE_ERROR_OK
) << "ReadDirectory failed. "
647 << FileErrorToString(error
);
649 scoped_ptr
<ResourceEntry
> entry(new ResourceEntry
);
650 ResourceEntry
* entry_ptr
= entry
.get();
651 base::PostTaskAndReplyWithResult(
652 blocking_task_runner_
.get(),
654 base::Bind(&GetLocallyStoredResourceEntry
,
659 base::Bind(&RunGetResourceEntryCallback
, callback
, base::Passed(&entry
)));
662 void FileSystem::ReadDirectory(
663 const base::FilePath
& directory_path
,
664 const ReadDirectoryEntriesCallback
& entries_callback_in
,
665 const FileOperationCallback
& completion_callback
) {
666 DCHECK(thread_checker_
.CalledOnValidThread());
667 DCHECK(!completion_callback
.is_null());
669 const bool hide_hosted_docs
=
670 pref_service_
->GetBoolean(prefs::kDisableDriveHostedFiles
);
671 ReadDirectoryEntriesCallback entries_callback
= entries_callback_in
;
672 if (!entries_callback
.is_null() && hide_hosted_docs
)
673 entries_callback
= base::Bind(&FilterHostedDocuments
, entries_callback
);
675 directory_loader_
->ReadDirectory(
676 directory_path
, entries_callback
, completion_callback
);
678 // Also start loading all of the user's contents.
679 change_list_loader_
->LoadIfNeeded(
680 base::Bind(&util::EmptyFileOperationCallback
));
683 void FileSystem::GetAvailableSpace(
684 const GetAvailableSpaceCallback
& callback
) {
685 DCHECK(thread_checker_
.CalledOnValidThread());
686 DCHECK(!callback
.is_null());
688 about_resource_loader_
->GetAboutResource(
689 base::Bind(&FileSystem::OnGetAboutResource
,
690 weak_ptr_factory_
.GetWeakPtr(),
694 void FileSystem::OnGetAboutResource(
695 const GetAvailableSpaceCallback
& callback
,
696 google_apis::DriveApiErrorCode status
,
697 scoped_ptr
<google_apis::AboutResource
> about_resource
) {
698 DCHECK(thread_checker_
.CalledOnValidThread());
699 DCHECK(!callback
.is_null());
701 FileError error
= GDataToFileError(status
);
702 if (error
!= FILE_ERROR_OK
) {
703 callback
.Run(error
, -1, -1);
706 DCHECK(about_resource
);
708 callback
.Run(FILE_ERROR_OK
, about_resource
->quota_bytes_total(),
709 about_resource
->quota_bytes_used_aggregate());
712 void FileSystem::GetShareUrl(const base::FilePath
& file_path
,
713 const GURL
& embed_origin
,
714 const GetShareUrlCallback
& callback
) {
715 DCHECK(thread_checker_
.CalledOnValidThread());
716 DCHECK(!callback
.is_null());
718 // Resolve the resource id.
719 ResourceEntry
* entry
= new ResourceEntry
;
720 base::PostTaskAndReplyWithResult(
721 blocking_task_runner_
.get(),
723 base::Bind(&internal::ResourceMetadata::GetResourceEntryByPath
,
724 base::Unretained(resource_metadata_
),
727 base::Bind(&FileSystem::GetShareUrlAfterGetResourceEntry
,
728 weak_ptr_factory_
.GetWeakPtr(),
732 base::Owned(entry
)));
735 void FileSystem::GetShareUrlAfterGetResourceEntry(
736 const base::FilePath
& file_path
,
737 const GURL
& embed_origin
,
738 const GetShareUrlCallback
& callback
,
739 ResourceEntry
* entry
,
741 DCHECK(thread_checker_
.CalledOnValidThread());
742 DCHECK(!callback
.is_null());
744 if (error
!= FILE_ERROR_OK
) {
745 callback
.Run(error
, GURL());
748 if (entry
->resource_id().empty()) {
749 // This entry does not exist on the server. Just return.
750 callback
.Run(FILE_ERROR_FAILED
, GURL());
754 scheduler_
->GetShareUrl(
755 entry
->resource_id(),
757 ClientContext(USER_INITIATED
),
758 base::Bind(&FileSystem::OnGetResourceEntryForGetShareUrl
,
759 weak_ptr_factory_
.GetWeakPtr(),
763 void FileSystem::OnGetResourceEntryForGetShareUrl(
764 const GetShareUrlCallback
& callback
,
765 google_apis::DriveApiErrorCode status
,
766 const GURL
& share_url
) {
767 DCHECK(thread_checker_
.CalledOnValidThread());
768 DCHECK(!callback
.is_null());
770 FileError error
= GDataToFileError(status
);
771 if (error
!= FILE_ERROR_OK
) {
772 callback
.Run(error
, GURL());
776 if (share_url
.is_empty()) {
777 callback
.Run(FILE_ERROR_FAILED
, GURL());
781 callback
.Run(FILE_ERROR_OK
, share_url
);
784 void FileSystem::Search(const std::string
& search_query
,
785 const GURL
& next_link
,
786 const SearchCallback
& callback
) {
787 DCHECK(thread_checker_
.CalledOnValidThread());
788 DCHECK(!callback
.is_null());
789 search_operation_
->Search(search_query
, next_link
, callback
);
792 void FileSystem::SearchMetadata(const std::string
& query
,
794 int at_most_num_matches
,
795 const SearchMetadataCallback
& callback
) {
796 DCHECK(thread_checker_
.CalledOnValidThread());
798 // TODO(satorux): Stop handling hide_hosted_docs here. crbug.com/256520.
799 if (pref_service_
->GetBoolean(prefs::kDisableDriveHostedFiles
))
800 options
|= SEARCH_METADATA_EXCLUDE_HOSTED_DOCUMENTS
;
802 drive::internal::SearchMetadata(
803 blocking_task_runner_
, resource_metadata_
, query
,
804 base::Bind(&drive::internal::MatchesType
, options
), at_most_num_matches
,
808 void FileSystem::SearchByHashes(const std::set
<std::string
>& hashes
,
809 const SearchByHashesCallback
& callback
) {
810 DCHECK(thread_checker_
.CalledOnValidThread());
811 drive::internal::SearchMetadata(
812 blocking_task_runner_
, resource_metadata_
,
813 /* any file name */ "", base::Bind(&CheckHashes
, hashes
),
814 std::numeric_limits
<size_t>::max(),
815 base::Bind(&RunSearchByHashesCallback
, callback
));
818 void FileSystem::OnFileChangedByOperation(const FileChange
& changed_files
) {
819 DCHECK(thread_checker_
.CalledOnValidThread());
822 FileSystemObserver
, observers_
, OnFileChanged(changed_files
));
825 void FileSystem::OnEntryUpdatedByOperation(const ClientContext
& context
,
826 const std::string
& local_id
) {
827 sync_client_
->AddUpdateTask(context
, local_id
);
830 void FileSystem::OnDriveSyncError(file_system::DriveSyncErrorType type
,
831 const std::string
& local_id
) {
832 base::FilePath
* file_path
= new base::FilePath
;
833 base::PostTaskAndReplyWithResult(
834 blocking_task_runner_
.get(),
836 base::Bind(&internal::ResourceMetadata::GetFilePath
,
837 base::Unretained(resource_metadata_
),
840 base::Bind(&FileSystem::OnDriveSyncErrorAfterGetFilePath
,
841 weak_ptr_factory_
.GetWeakPtr(),
843 base::Owned(file_path
)));
846 void FileSystem::OnDriveSyncErrorAfterGetFilePath(
847 file_system::DriveSyncErrorType type
,
848 const base::FilePath
* file_path
,
850 if (error
!= FILE_ERROR_OK
)
852 FOR_EACH_OBSERVER(FileSystemObserver
,
854 OnDriveSyncError(type
, *file_path
));
857 bool FileSystem::WaitForSyncComplete(const std::string
& local_id
,
858 const FileOperationCallback
& callback
) {
859 return sync_client_
->WaitForUpdateTaskToComplete(local_id
, callback
);
862 void FileSystem::OnDirectoryReloaded(const base::FilePath
& directory_path
) {
863 DCHECK(thread_checker_
.CalledOnValidThread());
866 FileSystemObserver
, observers_
, OnDirectoryChanged(directory_path
));
869 void FileSystem::OnFileChanged(const FileChange
& changed_files
) {
870 DCHECK(thread_checker_
.CalledOnValidThread());
873 FileSystemObserver
, observers_
, OnFileChanged(changed_files
));
876 void FileSystem::OnLoadFromServerComplete() {
877 DCHECK(thread_checker_
.CalledOnValidThread());
879 sync_client_
->StartCheckingExistingPinnedFiles();
882 void FileSystem::OnInitialLoadComplete() {
883 DCHECK(thread_checker_
.CalledOnValidThread());
885 blocking_task_runner_
->PostTask(FROM_HERE
,
886 base::Bind(&internal::RemoveStaleCacheFiles
,
888 resource_metadata_
));
889 sync_client_
->StartProcessingBacklog();
892 void FileSystem::GetMetadata(
893 const GetFilesystemMetadataCallback
& callback
) {
894 DCHECK(thread_checker_
.CalledOnValidThread());
895 DCHECK(!callback
.is_null());
897 FileSystemMetadata metadata
;
898 metadata
.refreshing
= change_list_loader_
->IsRefreshing();
900 // Metadata related to delta update.
901 metadata
.last_update_check_time
= last_update_check_time_
;
902 metadata
.last_update_check_error
= last_update_check_error_
;
904 int64
* largest_changestamp
= new int64(0);
905 base::PostTaskAndReplyWithResult(
906 blocking_task_runner_
.get(),
908 base::Bind(&internal::ResourceMetadata::GetLargestChangestamp
,
909 base::Unretained(resource_metadata_
),
910 largest_changestamp
),
911 base::Bind(&OnGetLargestChangestamp
,
914 base::Owned(largest_changestamp
)));
917 void FileSystem::MarkCacheFileAsMounted(
918 const base::FilePath
& drive_file_path
,
919 const MarkMountedCallback
& callback
) {
920 DCHECK(thread_checker_
.CalledOnValidThread());
921 DCHECK(!callback
.is_null());
923 base::FilePath
* cache_file_path
= new base::FilePath
;
924 base::PostTaskAndReplyWithResult(
925 blocking_task_runner_
.get(),
927 base::Bind(&MarkCacheFileAsMountedInternal
,
933 &RunMarkMountedCallback
, callback
, base::Owned(cache_file_path
)));
936 void FileSystem::MarkCacheFileAsUnmounted(
937 const base::FilePath
& cache_file_path
,
938 const FileOperationCallback
& callback
) {
939 DCHECK(thread_checker_
.CalledOnValidThread());
940 DCHECK(!callback
.is_null());
942 if (!cache_
->IsUnderFileCacheDirectory(cache_file_path
)) {
943 callback
.Run(FILE_ERROR_FAILED
);
947 base::PostTaskAndReplyWithResult(
948 blocking_task_runner_
.get(),
950 base::Bind(&internal::FileCache::MarkAsUnmounted
,
951 base::Unretained(cache_
),
956 void FileSystem::AddPermission(const base::FilePath
& drive_file_path
,
957 const std::string
& email
,
958 google_apis::drive::PermissionRole role
,
959 const FileOperationCallback
& callback
) {
960 DCHECK(thread_checker_
.CalledOnValidThread());
961 DCHECK(!callback
.is_null());
963 // Resolve the resource id.
964 ResourceEntry
* const entry
= new ResourceEntry
;
965 base::PostTaskAndReplyWithResult(
966 blocking_task_runner_
.get(),
968 base::Bind(&internal::ResourceMetadata::GetResourceEntryByPath
,
969 base::Unretained(resource_metadata_
),
972 base::Bind(&FileSystem::AddPermissionAfterGetResourceEntry
,
973 weak_ptr_factory_
.GetWeakPtr(),
977 base::Owned(entry
)));
980 void FileSystem::AddPermissionAfterGetResourceEntry(
981 const std::string
& email
,
982 google_apis::drive::PermissionRole role
,
983 const FileOperationCallback
& callback
,
984 ResourceEntry
* entry
,
986 DCHECK(thread_checker_
.CalledOnValidThread());
988 if (error
!= FILE_ERROR_OK
) {
993 scheduler_
->AddPermission(
994 entry
->resource_id(),
997 base::Bind(&RunFileOperationCallbackAsEntryActionCallback
, callback
));
1000 void FileSystem::SetProperty(
1001 const base::FilePath
& drive_file_path
,
1002 google_apis::drive::Property::Visibility visibility
,
1003 const std::string
& key
,
1004 const std::string
& value
,
1005 const FileOperationCallback
& callback
) {
1006 DCHECK(thread_checker_
.CalledOnValidThread());
1007 DCHECK(!callback
.is_null());
1009 set_property_operation_
->SetProperty(drive_file_path
, visibility
, key
, value
,
1013 void FileSystem::OpenFile(const base::FilePath
& file_path
,
1015 const std::string
& mime_type
,
1016 const OpenFileCallback
& callback
) {
1017 DCHECK(thread_checker_
.CalledOnValidThread());
1018 DCHECK(!callback
.is_null());
1020 open_file_operation_
->OpenFile(file_path
, open_mode
, mime_type
, callback
);
1023 void FileSystem::GetPathFromResourceId(const std::string
& resource_id
,
1024 const GetFilePathCallback
& callback
) {
1025 DCHECK(thread_checker_
.CalledOnValidThread());
1026 DCHECK(!callback
.is_null());
1028 base::FilePath
* const file_path
= new base::FilePath();
1029 base::PostTaskAndReplyWithResult(
1030 blocking_task_runner_
.get(),
1032 base::Bind(&GetPathFromResourceIdOnBlockingPool
,
1036 base::Bind(&GetPathFromResourceIdAfterGetPath
,
1037 base::Owned(file_path
),
1041 void FileSystem::FreeDiskSpaceIfNeededFor(
1043 const FreeDiskSpaceCallback
& callback
) {
1044 DCHECK(thread_checker_
.CalledOnValidThread());
1045 DCHECK(!callback
.is_null());
1046 base::PostTaskAndReplyWithResult(
1047 blocking_task_runner_
.get(), FROM_HERE
,
1048 base::Bind(&FreeDiskSpaceIfNeededForOnBlockingPool
, cache_
, num_bytes
),
1052 void FileSystem::CalculateEvictableCacheSize(
1053 const EvictableCacheSizeCallback
& callback
) {
1054 DCHECK(thread_checker_
.CalledOnValidThread());
1055 DCHECK(!callback
.is_null());
1056 base::PostTaskAndReplyWithResult(
1057 blocking_task_runner_
.get(), FROM_HERE
,
1058 base::Bind(&CalculateEvictableCacheSizeOnBlockingPool
, cache_
), callback
);
1060 } // namespace drive