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/files/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/file_system/copy_operation.h"
13 #include "chrome/browser/chromeos/drive/file_system/create_directory_operation.h"
14 #include "chrome/browser/chromeos/drive/file_system/create_file_operation.h"
15 #include "chrome/browser/chromeos/drive/file_system/download_operation.h"
16 #include "chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.h"
17 #include "chrome/browser/chromeos/drive/file_system/move_operation.h"
18 #include "chrome/browser/chromeos/drive/file_system/open_file_operation.h"
19 #include "chrome/browser/chromeos/drive/file_system/remove_operation.h"
20 #include "chrome/browser/chromeos/drive/file_system/search_operation.h"
21 #include "chrome/browser/chromeos/drive/file_system/set_property_operation.h"
22 #include "chrome/browser/chromeos/drive/file_system/touch_operation.h"
23 #include "chrome/browser/chromeos/drive/file_system/truncate_operation.h"
24 #include "chrome/browser/chromeos/drive/file_system_observer.h"
25 #include "chrome/browser/chromeos/drive/remove_stale_cache_files.h"
26 #include "chrome/browser/chromeos/drive/search_metadata.h"
27 #include "chrome/browser/chromeos/drive/sync_client.h"
28 #include "components/drive/drive.pb.h"
29 #include "components/drive/drive_pref_names.h"
30 #include "components/drive/file_cache.h"
31 #include "components/drive/file_change.h"
32 #include "components/drive/file_system_core_util.h"
33 #include "components/drive/job_scheduler.h"
34 #include "components/drive/resource_entry_conversion.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 // 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(!callback
.is_null());
218 // TODO(kinaba): Stop handling hide_hosted_docs here. crbug.com/256520.
219 scoped_ptr
<ResourceEntryVector
> filtered(new ResourceEntryVector
);
220 for (size_t i
= 0; i
< entries
->size(); ++i
) {
221 if (entries
->at(i
).file_specific_info().is_hosted_document()) {
224 filtered
->push_back(entries
->at(i
));
226 entries
.swap(filtered
);
228 callback
.Run(entries
.Pass());
231 // Adapter for using FileOperationCallback as google_apis::EntryActionCallback.
232 void RunFileOperationCallbackAsEntryActionCallback(
233 const FileOperationCallback
& callback
,
234 google_apis::DriveApiErrorCode error
) {
235 callback
.Run(GDataToFileError(error
));
238 // Checks if the |entry|'s hash is included in |hashes|.
239 bool CheckHashes(const std::set
<std::string
>& hashes
,
240 const ResourceEntry
& entry
) {
241 return hashes
.find(entry
.file_specific_info().md5()) != hashes
.end();
244 // Runs |callback| with |error| and the list of HashAndFilePath obtained from
245 // |original_result|.
246 void RunSearchByHashesCallback(
247 const SearchByHashesCallback
& callback
,
249 scoped_ptr
<MetadataSearchResultVector
> original_result
) {
250 std::vector
<HashAndFilePath
> result
;
251 if (error
!= FILE_ERROR_OK
) {
252 callback
.Run(error
, result
);
255 for (const auto& search_result
: *original_result
) {
256 HashAndFilePath hash_and_path
;
257 hash_and_path
.hash
= search_result
.md5
;
258 hash_and_path
.path
= search_result
.path
;
259 result
.push_back(hash_and_path
);
261 callback
.Run(FILE_ERROR_OK
, result
);
266 struct FileSystem::CreateDirectoryParams
{
267 base::FilePath directory_path
;
270 FileOperationCallback callback
;
273 FileSystem::FileSystem(PrefService
* pref_service
,
275 internal::FileCache
* cache
,
276 JobScheduler
* scheduler
,
277 internal::ResourceMetadata
* resource_metadata
,
278 base::SequencedTaskRunner
* blocking_task_runner
,
279 base::SingleThreadTaskRunner
* file_task_runner
,
280 const base::FilePath
& temporary_file_directory
)
281 : pref_service_(pref_service
),
284 scheduler_(scheduler
),
285 resource_metadata_(resource_metadata
),
286 last_update_check_error_(FILE_ERROR_OK
),
287 blocking_task_runner_(blocking_task_runner
),
288 file_task_runner_(file_task_runner
),
289 temporary_file_directory_(temporary_file_directory
),
290 weak_ptr_factory_(this) {
294 FileSystem::~FileSystem() {
295 DCHECK(thread_checker_
.CalledOnValidThread());
297 directory_loader_
->RemoveObserver(this);
298 change_list_loader_
->RemoveObserver(this);
301 void FileSystem::Reset(const FileOperationCallback
& callback
) {
302 // Discard the current loader and operation objects and renew them. This is to
303 // avoid that changes initiated before the metadata reset is applied after the
304 // reset, which may cause an inconsistent state.
305 // TODO(kinaba): callbacks held in the subcomponents are discarded. We might
306 // want to have a way to abort and flush callbacks in in-flight operations.
309 base::PostTaskAndReplyWithResult(
310 blocking_task_runner_
.get(),
312 base::Bind(&ResetOnBlockingPool
, resource_metadata_
, cache_
),
316 void FileSystem::ResetComponents() {
317 file_system::OperationDelegate
* delegate
= this;
319 about_resource_loader_
.reset(new internal::AboutResourceLoader(scheduler_
));
320 loader_controller_
.reset(new internal::LoaderController
);
321 change_list_loader_
.reset(new internal::ChangeListLoader(
323 blocking_task_runner_
.get(),
326 about_resource_loader_
.get(),
327 loader_controller_
.get()));
328 change_list_loader_
->AddObserver(this);
329 directory_loader_
.reset(new internal::DirectoryLoader(
331 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(blocking_task_runner_
.get(),
352 create_directory_operation_
.reset(new file_system::CreateDirectoryOperation(
353 blocking_task_runner_
.get(), delegate
, resource_metadata_
));
354 create_file_operation_
.reset(
355 new file_system::CreateFileOperation(blocking_task_runner_
.get(),
357 resource_metadata_
));
358 move_operation_
.reset(
359 new file_system::MoveOperation(blocking_task_runner_
.get(),
361 resource_metadata_
));
362 open_file_operation_
.reset(
363 new file_system::OpenFileOperation(blocking_task_runner_
.get(),
368 temporary_file_directory_
));
369 remove_operation_
.reset(
370 new file_system::RemoveOperation(blocking_task_runner_
.get(),
374 touch_operation_
.reset(new file_system::TouchOperation(
375 blocking_task_runner_
.get(), delegate
, resource_metadata_
));
376 truncate_operation_
.reset(
377 new file_system::TruncateOperation(blocking_task_runner_
.get(),
382 temporary_file_directory_
));
383 download_operation_
.reset(
384 new file_system::DownloadOperation(blocking_task_runner_
.get(),
389 temporary_file_directory_
));
390 search_operation_
.reset(new file_system::SearchOperation(
391 blocking_task_runner_
.get(), scheduler_
, resource_metadata_
,
392 loader_controller_
.get()));
393 get_file_for_saving_operation_
.reset(
394 new file_system::GetFileForSavingOperation(
395 logger_
, blocking_task_runner_
.get(), file_task_runner_
.get(),
396 delegate
, scheduler_
, resource_metadata_
, cache_
,
397 temporary_file_directory_
));
398 set_property_operation_
.reset(new file_system::SetPropertyOperation(
399 blocking_task_runner_
.get(), delegate
, resource_metadata_
));
402 void FileSystem::CheckForUpdates() {
403 DCHECK(thread_checker_
.CalledOnValidThread());
404 DVLOG(1) << "CheckForUpdates";
406 change_list_loader_
->CheckForUpdates(
407 base::Bind(&FileSystem::OnUpdateChecked
, weak_ptr_factory_
.GetWeakPtr()));
410 void FileSystem::OnUpdateChecked(FileError error
) {
411 DCHECK(thread_checker_
.CalledOnValidThread());
412 DVLOG(1) << "CheckForUpdates finished: " << FileErrorToString(error
);
413 last_update_check_time_
= base::Time::Now();
414 last_update_check_error_
= error
;
417 void FileSystem::AddObserver(FileSystemObserver
* observer
) {
418 DCHECK(thread_checker_
.CalledOnValidThread());
419 observers_
.AddObserver(observer
);
422 void FileSystem::RemoveObserver(FileSystemObserver
* observer
) {
423 DCHECK(thread_checker_
.CalledOnValidThread());
424 observers_
.RemoveObserver(observer
);
427 void FileSystem::TransferFileFromLocalToRemote(
428 const base::FilePath
& local_src_file_path
,
429 const base::FilePath
& remote_dest_file_path
,
430 const FileOperationCallback
& callback
) {
431 DCHECK(thread_checker_
.CalledOnValidThread());
432 DCHECK(!callback
.is_null());
433 copy_operation_
->TransferFileFromLocalToRemote(local_src_file_path
,
434 remote_dest_file_path
,
438 void FileSystem::Copy(const base::FilePath
& src_file_path
,
439 const base::FilePath
& dest_file_path
,
440 bool preserve_last_modified
,
441 const FileOperationCallback
& callback
) {
442 DCHECK(thread_checker_
.CalledOnValidThread());
443 DCHECK(!callback
.is_null());
444 copy_operation_
->Copy(
445 src_file_path
, dest_file_path
, preserve_last_modified
, callback
);
448 void FileSystem::Move(const base::FilePath
& src_file_path
,
449 const base::FilePath
& dest_file_path
,
450 const FileOperationCallback
& callback
) {
451 DCHECK(thread_checker_
.CalledOnValidThread());
452 DCHECK(!callback
.is_null());
453 move_operation_
->Move(src_file_path
, dest_file_path
, callback
);
456 void FileSystem::Remove(const base::FilePath
& file_path
,
458 const FileOperationCallback
& callback
) {
459 DCHECK(thread_checker_
.CalledOnValidThread());
460 DCHECK(!callback
.is_null());
461 remove_operation_
->Remove(file_path
, is_recursive
, callback
);
464 void FileSystem::CreateDirectory(
465 const base::FilePath
& directory_path
,
468 const FileOperationCallback
& callback
) {
469 DCHECK(thread_checker_
.CalledOnValidThread());
470 DCHECK(!callback
.is_null());
472 CreateDirectoryParams params
;
473 params
.directory_path
= directory_path
;
474 params
.is_exclusive
= is_exclusive
;
475 params
.is_recursive
= is_recursive
;
476 params
.callback
= callback
;
478 // Ensure its parent directory is loaded to the local metadata.
479 ReadDirectory(directory_path
.DirName(),
480 ReadDirectoryEntriesCallback(),
481 base::Bind(&FileSystem::CreateDirectoryAfterRead
,
482 weak_ptr_factory_
.GetWeakPtr(), params
));
485 void FileSystem::CreateDirectoryAfterRead(const CreateDirectoryParams
& params
,
487 DCHECK(thread_checker_
.CalledOnValidThread());
488 DCHECK(!params
.callback
.is_null());
490 DVLOG_IF(1, error
!= FILE_ERROR_OK
) << "ReadDirectory failed. "
491 << FileErrorToString(error
);
493 create_directory_operation_
->CreateDirectory(
494 params
.directory_path
, params
.is_exclusive
, params
.is_recursive
,
498 void FileSystem::CreateFile(const base::FilePath
& file_path
,
500 const std::string
& mime_type
,
501 const FileOperationCallback
& callback
) {
502 DCHECK(thread_checker_
.CalledOnValidThread());
503 DCHECK(!callback
.is_null());
504 create_file_operation_
->CreateFile(
505 file_path
, is_exclusive
, mime_type
, callback
);
508 void FileSystem::TouchFile(const base::FilePath
& file_path
,
509 const base::Time
& last_access_time
,
510 const base::Time
& last_modified_time
,
511 const FileOperationCallback
& callback
) {
512 DCHECK(thread_checker_
.CalledOnValidThread());
513 DCHECK(!callback
.is_null());
514 touch_operation_
->TouchFile(
515 file_path
, last_access_time
, last_modified_time
, callback
);
518 void FileSystem::TruncateFile(const base::FilePath
& file_path
,
520 const FileOperationCallback
& callback
) {
521 DCHECK(thread_checker_
.CalledOnValidThread());
522 DCHECK(!callback
.is_null());
523 truncate_operation_
->Truncate(file_path
, length
, callback
);
526 void FileSystem::Pin(const base::FilePath
& file_path
,
527 const FileOperationCallback
& callback
) {
528 DCHECK(thread_checker_
.CalledOnValidThread());
529 DCHECK(!callback
.is_null());
531 std::string
* local_id
= new std::string
;
532 base::PostTaskAndReplyWithResult(
533 blocking_task_runner_
.get(),
535 base::Bind(&PinInternal
, resource_metadata_
, cache_
, file_path
, local_id
),
536 base::Bind(&FileSystem::FinishPin
,
537 weak_ptr_factory_
.GetWeakPtr(),
539 base::Owned(local_id
)));
542 void FileSystem::FinishPin(const FileOperationCallback
& callback
,
543 const std::string
* local_id
,
545 DCHECK(thread_checker_
.CalledOnValidThread());
546 DCHECK(!callback
.is_null());
548 if (error
== FILE_ERROR_OK
)
549 sync_client_
->AddFetchTask(*local_id
);
553 void FileSystem::Unpin(const base::FilePath
& file_path
,
554 const FileOperationCallback
& callback
) {
555 DCHECK(thread_checker_
.CalledOnValidThread());
556 DCHECK(!callback
.is_null());
558 std::string
* local_id
= new std::string
;
559 base::PostTaskAndReplyWithResult(
560 blocking_task_runner_
.get(),
563 &UnpinInternal
, resource_metadata_
, cache_
, file_path
, local_id
),
564 base::Bind(&FileSystem::FinishUnpin
,
565 weak_ptr_factory_
.GetWeakPtr(),
567 base::Owned(local_id
)));
570 void FileSystem::FinishUnpin(const FileOperationCallback
& callback
,
571 const std::string
* local_id
,
573 DCHECK(thread_checker_
.CalledOnValidThread());
574 DCHECK(!callback
.is_null());
576 if (error
== FILE_ERROR_OK
)
577 sync_client_
->RemoveFetchTask(*local_id
);
581 void FileSystem::GetFile(const base::FilePath
& file_path
,
582 const GetFileCallback
& callback
) {
583 DCHECK(thread_checker_
.CalledOnValidThread());
584 DCHECK(!callback
.is_null());
586 download_operation_
->EnsureFileDownloadedByPath(
588 ClientContext(USER_INITIATED
),
589 GetFileContentInitializedCallback(),
590 google_apis::GetContentCallback(),
594 void FileSystem::GetFileForSaving(const base::FilePath
& file_path
,
595 const GetFileCallback
& callback
) {
596 DCHECK(thread_checker_
.CalledOnValidThread());
597 DCHECK(!callback
.is_null());
599 get_file_for_saving_operation_
->GetFileForSaving(file_path
, callback
);
602 base::Closure
FileSystem::GetFileContent(
603 const base::FilePath
& file_path
,
604 const GetFileContentInitializedCallback
& initialized_callback
,
605 const google_apis::GetContentCallback
& get_content_callback
,
606 const FileOperationCallback
& completion_callback
) {
607 DCHECK(thread_checker_
.CalledOnValidThread());
608 DCHECK(!initialized_callback
.is_null());
609 DCHECK(!get_content_callback
.is_null());
610 DCHECK(!completion_callback
.is_null());
612 return download_operation_
->EnsureFileDownloadedByPath(
614 ClientContext(USER_INITIATED
),
615 initialized_callback
,
616 get_content_callback
,
617 base::Bind(&GetFileCallbackToFileOperationCallbackAdapter
,
618 completion_callback
));
621 void FileSystem::GetResourceEntry(
622 const base::FilePath
& file_path
,
623 const GetResourceEntryCallback
& callback
) {
624 DCHECK(thread_checker_
.CalledOnValidThread());
625 DCHECK(!callback
.is_null());
627 ReadDirectory(file_path
.DirName(),
628 ReadDirectoryEntriesCallback(),
629 base::Bind(&FileSystem::GetResourceEntryAfterRead
,
630 weak_ptr_factory_
.GetWeakPtr(),
635 void FileSystem::GetResourceEntryAfterRead(
636 const base::FilePath
& file_path
,
637 const GetResourceEntryCallback
& callback
,
639 DCHECK(thread_checker_
.CalledOnValidThread());
640 DCHECK(!callback
.is_null());
642 DVLOG_IF(1, error
!= FILE_ERROR_OK
) << "ReadDirectory failed. "
643 << FileErrorToString(error
);
645 scoped_ptr
<ResourceEntry
> entry(new ResourceEntry
);
646 ResourceEntry
* entry_ptr
= entry
.get();
647 base::PostTaskAndReplyWithResult(
648 blocking_task_runner_
.get(),
650 base::Bind(&GetLocallyStoredResourceEntry
,
655 base::Bind(&RunGetResourceEntryCallback
, callback
, base::Passed(&entry
)));
658 void FileSystem::ReadDirectory(
659 const base::FilePath
& directory_path
,
660 const ReadDirectoryEntriesCallback
& entries_callback_in
,
661 const FileOperationCallback
& completion_callback
) {
662 DCHECK(thread_checker_
.CalledOnValidThread());
663 DCHECK(!completion_callback
.is_null());
665 const bool hide_hosted_docs
=
666 pref_service_
->GetBoolean(prefs::kDisableDriveHostedFiles
);
667 ReadDirectoryEntriesCallback entries_callback
= entries_callback_in
;
668 if (!entries_callback
.is_null() && hide_hosted_docs
)
669 entries_callback
= base::Bind(&FilterHostedDocuments
, entries_callback
);
671 directory_loader_
->ReadDirectory(
672 directory_path
, entries_callback
, completion_callback
);
674 // Also start loading all of the user's contents.
675 change_list_loader_
->LoadIfNeeded(
676 base::Bind(&util::EmptyFileOperationCallback
));
679 void FileSystem::GetAvailableSpace(
680 const GetAvailableSpaceCallback
& callback
) {
681 DCHECK(thread_checker_
.CalledOnValidThread());
682 DCHECK(!callback
.is_null());
684 about_resource_loader_
->GetAboutResource(
685 base::Bind(&FileSystem::OnGetAboutResource
,
686 weak_ptr_factory_
.GetWeakPtr(),
690 void FileSystem::OnGetAboutResource(
691 const GetAvailableSpaceCallback
& callback
,
692 google_apis::DriveApiErrorCode status
,
693 scoped_ptr
<google_apis::AboutResource
> about_resource
) {
694 DCHECK(thread_checker_
.CalledOnValidThread());
695 DCHECK(!callback
.is_null());
697 FileError error
= GDataToFileError(status
);
698 if (error
!= FILE_ERROR_OK
) {
699 callback
.Run(error
, -1, -1);
702 DCHECK(about_resource
);
704 callback
.Run(FILE_ERROR_OK
, about_resource
->quota_bytes_total(),
705 about_resource
->quota_bytes_used_aggregate());
708 void FileSystem::GetShareUrl(const base::FilePath
& file_path
,
709 const GURL
& embed_origin
,
710 const GetShareUrlCallback
& callback
) {
711 DCHECK(thread_checker_
.CalledOnValidThread());
712 DCHECK(!callback
.is_null());
714 // Resolve the resource id.
715 ResourceEntry
* entry
= new ResourceEntry
;
716 base::PostTaskAndReplyWithResult(
717 blocking_task_runner_
.get(),
719 base::Bind(&internal::ResourceMetadata::GetResourceEntryByPath
,
720 base::Unretained(resource_metadata_
),
723 base::Bind(&FileSystem::GetShareUrlAfterGetResourceEntry
,
724 weak_ptr_factory_
.GetWeakPtr(),
728 base::Owned(entry
)));
731 void FileSystem::GetShareUrlAfterGetResourceEntry(
732 const base::FilePath
& file_path
,
733 const GURL
& embed_origin
,
734 const GetShareUrlCallback
& callback
,
735 ResourceEntry
* entry
,
737 DCHECK(thread_checker_
.CalledOnValidThread());
738 DCHECK(!callback
.is_null());
740 if (error
!= FILE_ERROR_OK
) {
741 callback
.Run(error
, GURL());
744 if (entry
->resource_id().empty()) {
745 // This entry does not exist on the server. Just return.
746 callback
.Run(FILE_ERROR_FAILED
, GURL());
750 scheduler_
->GetShareUrl(
751 entry
->resource_id(),
753 ClientContext(USER_INITIATED
),
754 base::Bind(&FileSystem::OnGetResourceEntryForGetShareUrl
,
755 weak_ptr_factory_
.GetWeakPtr(),
759 void FileSystem::OnGetResourceEntryForGetShareUrl(
760 const GetShareUrlCallback
& callback
,
761 google_apis::DriveApiErrorCode status
,
762 const GURL
& share_url
) {
763 DCHECK(thread_checker_
.CalledOnValidThread());
764 DCHECK(!callback
.is_null());
766 FileError error
= GDataToFileError(status
);
767 if (error
!= FILE_ERROR_OK
) {
768 callback
.Run(error
, GURL());
772 if (share_url
.is_empty()) {
773 callback
.Run(FILE_ERROR_FAILED
, GURL());
777 callback
.Run(FILE_ERROR_OK
, share_url
);
780 void FileSystem::Search(const std::string
& search_query
,
781 const GURL
& next_link
,
782 const SearchCallback
& callback
) {
783 DCHECK(thread_checker_
.CalledOnValidThread());
784 DCHECK(!callback
.is_null());
785 search_operation_
->Search(search_query
, next_link
, callback
);
788 void FileSystem::SearchMetadata(const std::string
& query
,
790 int at_most_num_matches
,
791 const SearchMetadataCallback
& callback
) {
792 DCHECK(thread_checker_
.CalledOnValidThread());
794 // TODO(satorux): Stop handling hide_hosted_docs here. crbug.com/256520.
795 if (pref_service_
->GetBoolean(prefs::kDisableDriveHostedFiles
))
796 options
|= SEARCH_METADATA_EXCLUDE_HOSTED_DOCUMENTS
;
798 drive::internal::SearchMetadata(
799 blocking_task_runner_
, resource_metadata_
, query
,
800 base::Bind(&drive::internal::MatchesType
, options
), at_most_num_matches
,
804 void FileSystem::SearchByHashes(const std::set
<std::string
>& hashes
,
805 const SearchByHashesCallback
& callback
) {
806 DCHECK(thread_checker_
.CalledOnValidThread());
807 drive::internal::SearchMetadata(
808 blocking_task_runner_
, resource_metadata_
,
809 /* any file name */ "", base::Bind(&CheckHashes
, hashes
),
810 std::numeric_limits
<size_t>::max(),
811 base::Bind(&RunSearchByHashesCallback
, callback
));
814 void FileSystem::OnFileChangedByOperation(const FileChange
& changed_files
) {
815 DCHECK(thread_checker_
.CalledOnValidThread());
818 FileSystemObserver
, observers_
, OnFileChanged(changed_files
));
821 void FileSystem::OnEntryUpdatedByOperation(const ClientContext
& context
,
822 const std::string
& local_id
) {
823 sync_client_
->AddUpdateTask(context
, local_id
);
826 void FileSystem::OnDriveSyncError(file_system::DriveSyncErrorType type
,
827 const std::string
& local_id
) {
828 base::FilePath
* file_path
= new base::FilePath
;
829 base::PostTaskAndReplyWithResult(
830 blocking_task_runner_
.get(),
832 base::Bind(&internal::ResourceMetadata::GetFilePath
,
833 base::Unretained(resource_metadata_
),
836 base::Bind(&FileSystem::OnDriveSyncErrorAfterGetFilePath
,
837 weak_ptr_factory_
.GetWeakPtr(),
839 base::Owned(file_path
)));
842 void FileSystem::OnDriveSyncErrorAfterGetFilePath(
843 file_system::DriveSyncErrorType type
,
844 const base::FilePath
* file_path
,
846 if (error
!= FILE_ERROR_OK
)
848 FOR_EACH_OBSERVER(FileSystemObserver
,
850 OnDriveSyncError(type
, *file_path
));
853 bool FileSystem::WaitForSyncComplete(const std::string
& local_id
,
854 const FileOperationCallback
& callback
) {
855 return sync_client_
->WaitForUpdateTaskToComplete(local_id
, callback
);
858 void FileSystem::OnDirectoryReloaded(const base::FilePath
& directory_path
) {
859 DCHECK(thread_checker_
.CalledOnValidThread());
862 FileSystemObserver
, observers_
, OnDirectoryChanged(directory_path
));
865 void FileSystem::OnFileChanged(const FileChange
& changed_files
) {
866 DCHECK(thread_checker_
.CalledOnValidThread());
869 FileSystemObserver
, observers_
, OnFileChanged(changed_files
));
872 void FileSystem::OnLoadFromServerComplete() {
873 DCHECK(thread_checker_
.CalledOnValidThread());
875 sync_client_
->StartCheckingExistingPinnedFiles();
878 void FileSystem::OnInitialLoadComplete() {
879 DCHECK(thread_checker_
.CalledOnValidThread());
881 blocking_task_runner_
->PostTask(FROM_HERE
,
882 base::Bind(&internal::RemoveStaleCacheFiles
,
884 resource_metadata_
));
885 sync_client_
->StartProcessingBacklog();
888 void FileSystem::GetMetadata(
889 const GetFilesystemMetadataCallback
& callback
) {
890 DCHECK(thread_checker_
.CalledOnValidThread());
891 DCHECK(!callback
.is_null());
893 FileSystemMetadata metadata
;
894 metadata
.refreshing
= change_list_loader_
->IsRefreshing();
896 // Metadata related to delta update.
897 metadata
.last_update_check_time
= last_update_check_time_
;
898 metadata
.last_update_check_error
= last_update_check_error_
;
900 int64
* largest_changestamp
= new int64(0);
901 base::PostTaskAndReplyWithResult(
902 blocking_task_runner_
.get(),
904 base::Bind(&internal::ResourceMetadata::GetLargestChangestamp
,
905 base::Unretained(resource_metadata_
),
906 largest_changestamp
),
907 base::Bind(&OnGetLargestChangestamp
,
910 base::Owned(largest_changestamp
)));
913 void FileSystem::MarkCacheFileAsMounted(
914 const base::FilePath
& drive_file_path
,
915 const MarkMountedCallback
& callback
) {
916 DCHECK(thread_checker_
.CalledOnValidThread());
917 DCHECK(!callback
.is_null());
919 base::FilePath
* cache_file_path
= new base::FilePath
;
920 base::PostTaskAndReplyWithResult(
921 blocking_task_runner_
.get(),
923 base::Bind(&MarkCacheFileAsMountedInternal
,
929 &RunMarkMountedCallback
, callback
, base::Owned(cache_file_path
)));
932 void FileSystem::MarkCacheFileAsUnmounted(
933 const base::FilePath
& cache_file_path
,
934 const FileOperationCallback
& callback
) {
935 DCHECK(thread_checker_
.CalledOnValidThread());
936 DCHECK(!callback
.is_null());
938 if (!cache_
->IsUnderFileCacheDirectory(cache_file_path
)) {
939 callback
.Run(FILE_ERROR_FAILED
);
943 base::PostTaskAndReplyWithResult(
944 blocking_task_runner_
.get(),
946 base::Bind(&internal::FileCache::MarkAsUnmounted
,
947 base::Unretained(cache_
),
952 void FileSystem::AddPermission(const base::FilePath
& drive_file_path
,
953 const std::string
& email
,
954 google_apis::drive::PermissionRole role
,
955 const FileOperationCallback
& callback
) {
956 DCHECK(thread_checker_
.CalledOnValidThread());
957 DCHECK(!callback
.is_null());
959 // Resolve the resource id.
960 ResourceEntry
* const entry
= new ResourceEntry
;
961 base::PostTaskAndReplyWithResult(
962 blocking_task_runner_
.get(),
964 base::Bind(&internal::ResourceMetadata::GetResourceEntryByPath
,
965 base::Unretained(resource_metadata_
),
968 base::Bind(&FileSystem::AddPermissionAfterGetResourceEntry
,
969 weak_ptr_factory_
.GetWeakPtr(),
973 base::Owned(entry
)));
976 void FileSystem::AddPermissionAfterGetResourceEntry(
977 const std::string
& email
,
978 google_apis::drive::PermissionRole role
,
979 const FileOperationCallback
& callback
,
980 ResourceEntry
* entry
,
982 DCHECK(thread_checker_
.CalledOnValidThread());
984 if (error
!= FILE_ERROR_OK
) {
989 scheduler_
->AddPermission(
990 entry
->resource_id(),
993 base::Bind(&RunFileOperationCallbackAsEntryActionCallback
, callback
));
996 void FileSystem::SetProperty(
997 const base::FilePath
& drive_file_path
,
998 google_apis::drive::Property::Visibility visibility
,
999 const std::string
& key
,
1000 const std::string
& value
,
1001 const FileOperationCallback
& callback
) {
1002 DCHECK(thread_checker_
.CalledOnValidThread());
1003 DCHECK(!callback
.is_null());
1005 set_property_operation_
->SetProperty(drive_file_path
, visibility
, key
, value
,
1009 void FileSystem::OpenFile(const base::FilePath
& file_path
,
1011 const std::string
& mime_type
,
1012 const OpenFileCallback
& callback
) {
1013 DCHECK(thread_checker_
.CalledOnValidThread());
1014 DCHECK(!callback
.is_null());
1016 open_file_operation_
->OpenFile(file_path
, open_mode
, mime_type
, callback
);
1019 void FileSystem::GetPathFromResourceId(const std::string
& resource_id
,
1020 const GetFilePathCallback
& callback
) {
1021 DCHECK(thread_checker_
.CalledOnValidThread());
1022 DCHECK(!callback
.is_null());
1024 base::FilePath
* const file_path
= new base::FilePath();
1025 base::PostTaskAndReplyWithResult(
1026 blocking_task_runner_
.get(),
1028 base::Bind(&GetPathFromResourceIdOnBlockingPool
,
1032 base::Bind(&GetPathFromResourceIdAfterGetPath
,
1033 base::Owned(file_path
),
1037 void FileSystem::FreeDiskSpaceIfNeededFor(
1039 const FreeDiskSpaceCallback
& callback
) {
1040 DCHECK(thread_checker_
.CalledOnValidThread());
1041 DCHECK(!callback
.is_null());
1042 base::PostTaskAndReplyWithResult(
1043 blocking_task_runner_
.get(), FROM_HERE
,
1044 base::Bind(&FreeDiskSpaceIfNeededForOnBlockingPool
, cache_
, num_bytes
),
1047 } // namespace drive