OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/chromeos/drive/file_system.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/files/file_util.h" | |
9 #include "base/prefs/pref_service.h" | |
10 #include "chrome/browser/chromeos/drive/directory_loader.h" | |
11 #include "chrome/browser/chromeos/drive/file_system_observer.h" | |
12 #include "chrome/browser/chromeos/drive/remove_stale_cache_files.h" | |
13 #include "chrome/browser/chromeos/drive/search_metadata.h" | |
14 #include "chrome/browser/chromeos/drive/sync_client.h" | |
15 #include "components/drive/change_list_loader.h" | |
16 #include "components/drive/drive.pb.h" | |
17 #include "components/drive/drive_pref_names.h" | |
18 #include "components/drive/file_cache.h" | |
19 #include "components/drive/file_change.h" | |
20 #include "components/drive/file_system/copy_operation.h" | |
21 #include "components/drive/file_system/create_directory_operation.h" | |
22 #include "components/drive/file_system/create_file_operation.h" | |
23 #include "components/drive/file_system/download_operation.h" | |
24 #include "components/drive/file_system/get_file_for_saving_operation.h" | |
25 #include "components/drive/file_system/move_operation.h" | |
26 #include "components/drive/file_system/open_file_operation.h" | |
27 #include "components/drive/file_system/remove_operation.h" | |
28 #include "components/drive/file_system/search_operation.h" | |
29 #include "components/drive/file_system/set_property_operation.h" | |
30 #include "components/drive/file_system/touch_operation.h" | |
31 #include "components/drive/file_system/truncate_operation.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" | |
36 | |
37 namespace drive { | |
38 namespace { | |
39 | |
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) { | |
47 std::string local_id; | |
48 FileError error = resource_metadata->GetIdByPath(file_path, &local_id); | |
49 if (error != FILE_ERROR_OK) | |
50 return error; | |
51 | |
52 error = resource_metadata->GetResourceEntryById(local_id, entry); | |
53 if (error != FILE_ERROR_OK) | |
54 return error; | |
55 | |
56 // For entries that will never be cached, use the original resource entry | |
57 // as is. | |
58 if (!entry->has_file_specific_info() || | |
59 entry->file_specific_info().is_hosted_document()) | |
60 return FILE_ERROR_OK; | |
61 | |
62 // When cache is not found, use the original resource entry as is. | |
63 if (!entry->file_specific_info().has_cache_state()) | |
64 return FILE_ERROR_OK; | |
65 | |
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()) | |
70 return FILE_ERROR_OK; | |
71 | |
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) | |
76 return error; | |
77 | |
78 base::File::Info file_info; | |
79 if (!base::GetFileInfo(local_cache_path, &file_info)) | |
80 return FILE_ERROR_NOT_FOUND; | |
81 | |
82 entry->mutable_file_info()->set_size(file_info.size); | |
83 return FILE_ERROR_OK; | |
84 } | |
85 | |
86 // Runs the callback with parameters. | |
87 void RunGetResourceEntryCallback(const GetResourceEntryCallback& callback, | |
88 scoped_ptr<ResourceEntry> entry, | |
89 FileError error) { | |
90 DCHECK(!callback.is_null()); | |
91 | |
92 if (error != FILE_ERROR_OK) | |
93 entry.reset(); | |
94 callback.Run(error, entry.Pass()); | |
95 } | |
96 | |
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) | |
104 return error; | |
105 | |
106 ResourceEntry entry; | |
107 error = resource_metadata->GetResourceEntryById(*local_id, &entry); | |
108 if (error != FILE_ERROR_OK) | |
109 return error; | |
110 | |
111 // TODO(hashimoto): Support pinning directories. crbug.com/127831 | |
112 if (entry.file_info().is_directory()) | |
113 return FILE_ERROR_NOT_A_FILE; | |
114 | |
115 return cache->Pin(*local_id); | |
116 } | |
117 | |
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) | |
125 return error; | |
126 | |
127 return cache->Unpin(*local_id); | |
128 } | |
129 | |
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) | |
139 return error; | |
140 | |
141 return cache->MarkAsMounted(local_id, cache_file_path); | |
142 } | |
143 | |
144 // Runs the callback with arguments. | |
145 void RunMarkMountedCallback(const MarkMountedCallback& callback, | |
146 base::FilePath* cache_file_path, | |
147 FileError error) { | |
148 DCHECK(!callback.is_null()); | |
149 callback.Run(error, *cache_file_path); | |
150 } | |
151 | |
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, | |
158 FileError error) { | |
159 DCHECK(!callback.is_null()); | |
160 | |
161 metadata.largest_changestamp = *largest_changestamp; | |
162 callback.Run(metadata); | |
163 } | |
164 | |
165 // Thin adapter to map GetFileCallback to FileOperationCallback. | |
166 void GetFileCallbackToFileOperationCallbackAdapter( | |
167 const FileOperationCallback& callback, | |
168 FileError error, | |
169 const base::FilePath& unused_file_path, | |
170 scoped_ptr<ResourceEntry> unused_entry) { | |
171 callback.Run(error); | |
172 } | |
173 | |
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) | |
179 return error; | |
180 return cache->ClearAll() ? FILE_ERROR_OK : FILE_ERROR_FAILED; | |
181 } | |
182 | |
183 // Part of GetPathFromResourceId(). | |
184 // Obtains |file_path| from |resource_id|. The function should be run on the | |
185 // blocking pool. | |
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) | |
194 return error; | |
195 return resource_metadata->GetFilePath(local_id, file_path); | |
196 } | |
197 | |
198 // Part of GetPathFromResourceId(). | |
199 // Called when GetPathFromResourceIdInBlockingPool is complete. | |
200 void GetPathFromResourceIdAfterGetPath(base::FilePath* file_path, | |
201 const GetFilePathCallback& callback, | |
202 FileError error) { | |
203 callback.Run(error, *file_path); | |
204 } | |
205 | |
206 bool FreeDiskSpaceIfNeededForOnBlockingPool(internal::FileCache* cache, | |
207 int64 num_bytes) { | |
208 return cache->FreeDiskSpaceIfNeededFor(num_bytes); | |
209 } | |
210 | |
211 uint64_t CalculateEvictableCacheSizeOnBlockingPool(internal::FileCache* cache) { | |
212 return cache->CalculateEvictableCacheSize(); | |
213 } | |
214 | |
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()); | |
220 | |
221 if (entries) { | |
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()) { | |
226 continue; | |
227 } | |
228 filtered->push_back(entries->at(i)); | |
229 } | |
230 entries.swap(filtered); | |
231 } | |
232 callback.Run(entries.Pass()); | |
233 } | |
234 | |
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)); | |
240 } | |
241 | |
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(); | |
246 } | |
247 | |
248 // Runs |callback| with |error| and the list of HashAndFilePath obtained from | |
249 // |original_result|. | |
250 void RunSearchByHashesCallback( | |
251 const SearchByHashesCallback& callback, | |
252 FileError error, | |
253 scoped_ptr<MetadataSearchResultVector> original_result) { | |
254 std::vector<HashAndFilePath> result; | |
255 if (error != FILE_ERROR_OK) { | |
256 callback.Run(error, result); | |
257 return; | |
258 } | |
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); | |
264 } | |
265 callback.Run(FILE_ERROR_OK, result); | |
266 } | |
267 | |
268 } // namespace | |
269 | |
270 struct FileSystem::CreateDirectoryParams { | |
271 base::FilePath directory_path; | |
272 bool is_exclusive; | |
273 bool is_recursive; | |
274 FileOperationCallback callback; | |
275 }; | |
276 | |
277 FileSystem::FileSystem(PrefService* pref_service, | |
278 EventLogger* logger, | |
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), | |
286 logger_(logger), | |
287 cache_(cache), | |
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) { | |
295 ResetComponents(); | |
296 } | |
297 | |
298 FileSystem::~FileSystem() { | |
299 DCHECK(thread_checker_.CalledOnValidThread()); | |
300 | |
301 directory_loader_->RemoveObserver(this); | |
302 change_list_loader_->RemoveObserver(this); | |
303 } | |
304 | |
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. | |
311 ResetComponents(); | |
312 | |
313 base::PostTaskAndReplyWithResult( | |
314 blocking_task_runner_.get(), | |
315 FROM_HERE, | |
316 base::Bind(&ResetOnBlockingPool, resource_metadata_, cache_), | |
317 callback); | |
318 } | |
319 | |
320 void FileSystem::ResetComponents() { | |
321 file_system::OperationDelegate* delegate = this; | |
322 | |
323 about_resource_loader_.reset(new internal::AboutResourceLoader(scheduler_)); | |
324 loader_controller_.reset(new internal::LoaderController); | |
325 change_list_loader_.reset(new internal::ChangeListLoader( | |
326 logger_, | |
327 blocking_task_runner_.get(), | |
328 resource_metadata_, | |
329 scheduler_, | |
330 about_resource_loader_.get(), | |
331 loader_controller_.get())); | |
332 change_list_loader_->AddObserver(this); | |
333 directory_loader_.reset(new internal::DirectoryLoader( | |
334 logger_, | |
335 blocking_task_runner_.get(), | |
336 resource_metadata_, | |
337 scheduler_, | |
338 about_resource_loader_.get(), | |
339 loader_controller_.get())); | |
340 directory_loader_->AddObserver(this); | |
341 | |
342 sync_client_.reset(new internal::SyncClient(blocking_task_runner_.get(), | |
343 delegate, | |
344 scheduler_, | |
345 resource_metadata_, | |
346 cache_, | |
347 loader_controller_.get(), | |
348 temporary_file_directory_)); | |
349 | |
350 copy_operation_.reset( | |
351 new file_system::CopyOperation(blocking_task_runner_.get(), | |
352 delegate, | |
353 scheduler_, | |
354 resource_metadata_, | |
355 cache_)); | |
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(), | |
360 delegate, | |
361 resource_metadata_)); | |
362 move_operation_.reset( | |
363 new file_system::MoveOperation(blocking_task_runner_.get(), | |
364 delegate, | |
365 resource_metadata_)); | |
366 open_file_operation_.reset( | |
367 new file_system::OpenFileOperation(blocking_task_runner_.get(), | |
368 delegate, | |
369 scheduler_, | |
370 resource_metadata_, | |
371 cache_, | |
372 temporary_file_directory_)); | |
373 remove_operation_.reset( | |
374 new file_system::RemoveOperation(blocking_task_runner_.get(), | |
375 delegate, | |
376 resource_metadata_, | |
377 cache_)); | |
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(), | |
382 delegate, | |
383 scheduler_, | |
384 resource_metadata_, | |
385 cache_, | |
386 temporary_file_directory_)); | |
387 download_operation_.reset( | |
388 new file_system::DownloadOperation(blocking_task_runner_.get(), | |
389 delegate, | |
390 scheduler_, | |
391 resource_metadata_, | |
392 cache_, | |
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_)); | |
404 } | |
405 | |
406 void FileSystem::CheckForUpdates() { | |
407 DCHECK(thread_checker_.CalledOnValidThread()); | |
408 DVLOG(1) << "CheckForUpdates"; | |
409 | |
410 change_list_loader_->CheckForUpdates( | |
411 base::Bind(&FileSystem::OnUpdateChecked, weak_ptr_factory_.GetWeakPtr())); | |
412 } | |
413 | |
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; | |
419 } | |
420 | |
421 void FileSystem::AddObserver(FileSystemObserver* observer) { | |
422 DCHECK(thread_checker_.CalledOnValidThread()); | |
423 observers_.AddObserver(observer); | |
424 } | |
425 | |
426 void FileSystem::RemoveObserver(FileSystemObserver* observer) { | |
427 DCHECK(thread_checker_.CalledOnValidThread()); | |
428 observers_.RemoveObserver(observer); | |
429 } | |
430 | |
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, | |
439 callback); | |
440 } | |
441 | |
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); | |
450 } | |
451 | |
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); | |
458 } | |
459 | |
460 void FileSystem::Remove(const base::FilePath& file_path, | |
461 bool is_recursive, | |
462 const FileOperationCallback& callback) { | |
463 DCHECK(thread_checker_.CalledOnValidThread()); | |
464 DCHECK(!callback.is_null()); | |
465 remove_operation_->Remove(file_path, is_recursive, callback); | |
466 } | |
467 | |
468 void FileSystem::CreateDirectory( | |
469 const base::FilePath& directory_path, | |
470 bool is_exclusive, | |
471 bool is_recursive, | |
472 const FileOperationCallback& callback) { | |
473 DCHECK(thread_checker_.CalledOnValidThread()); | |
474 DCHECK(!callback.is_null()); | |
475 | |
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; | |
481 | |
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)); | |
487 } | |
488 | |
489 void FileSystem::CreateDirectoryAfterRead(const CreateDirectoryParams& params, | |
490 FileError error) { | |
491 DCHECK(thread_checker_.CalledOnValidThread()); | |
492 DCHECK(!params.callback.is_null()); | |
493 | |
494 DVLOG_IF(1, error != FILE_ERROR_OK) << "ReadDirectory failed. " | |
495 << FileErrorToString(error); | |
496 | |
497 create_directory_operation_->CreateDirectory( | |
498 params.directory_path, params.is_exclusive, params.is_recursive, | |
499 params.callback); | |
500 } | |
501 | |
502 void FileSystem::CreateFile(const base::FilePath& file_path, | |
503 bool is_exclusive, | |
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); | |
510 } | |
511 | |
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); | |
520 } | |
521 | |
522 void FileSystem::TruncateFile(const base::FilePath& file_path, | |
523 int64 length, | |
524 const FileOperationCallback& callback) { | |
525 DCHECK(thread_checker_.CalledOnValidThread()); | |
526 DCHECK(!callback.is_null()); | |
527 truncate_operation_->Truncate(file_path, length, callback); | |
528 } | |
529 | |
530 void FileSystem::Pin(const base::FilePath& file_path, | |
531 const FileOperationCallback& callback) { | |
532 DCHECK(thread_checker_.CalledOnValidThread()); | |
533 DCHECK(!callback.is_null()); | |
534 | |
535 std::string* local_id = new std::string; | |
536 base::PostTaskAndReplyWithResult( | |
537 blocking_task_runner_.get(), | |
538 FROM_HERE, | |
539 base::Bind(&PinInternal, resource_metadata_, cache_, file_path, local_id), | |
540 base::Bind(&FileSystem::FinishPin, | |
541 weak_ptr_factory_.GetWeakPtr(), | |
542 callback, | |
543 base::Owned(local_id))); | |
544 } | |
545 | |
546 void FileSystem::FinishPin(const FileOperationCallback& callback, | |
547 const std::string* local_id, | |
548 FileError error) { | |
549 DCHECK(thread_checker_.CalledOnValidThread()); | |
550 DCHECK(!callback.is_null()); | |
551 | |
552 if (error == FILE_ERROR_OK) | |
553 sync_client_->AddFetchTask(*local_id); | |
554 callback.Run(error); | |
555 } | |
556 | |
557 void FileSystem::Unpin(const base::FilePath& file_path, | |
558 const FileOperationCallback& callback) { | |
559 DCHECK(thread_checker_.CalledOnValidThread()); | |
560 DCHECK(!callback.is_null()); | |
561 | |
562 std::string* local_id = new std::string; | |
563 base::PostTaskAndReplyWithResult( | |
564 blocking_task_runner_.get(), | |
565 FROM_HERE, | |
566 base::Bind( | |
567 &UnpinInternal, resource_metadata_, cache_, file_path, local_id), | |
568 base::Bind(&FileSystem::FinishUnpin, | |
569 weak_ptr_factory_.GetWeakPtr(), | |
570 callback, | |
571 base::Owned(local_id))); | |
572 } | |
573 | |
574 void FileSystem::FinishUnpin(const FileOperationCallback& callback, | |
575 const std::string* local_id, | |
576 FileError error) { | |
577 DCHECK(thread_checker_.CalledOnValidThread()); | |
578 DCHECK(!callback.is_null()); | |
579 | |
580 if (error == FILE_ERROR_OK) | |
581 sync_client_->RemoveFetchTask(*local_id); | |
582 callback.Run(error); | |
583 } | |
584 | |
585 void FileSystem::GetFile(const base::FilePath& file_path, | |
586 const GetFileCallback& callback) { | |
587 DCHECK(thread_checker_.CalledOnValidThread()); | |
588 DCHECK(!callback.is_null()); | |
589 | |
590 download_operation_->EnsureFileDownloadedByPath( | |
591 file_path, | |
592 ClientContext(USER_INITIATED), | |
593 GetFileContentInitializedCallback(), | |
594 google_apis::GetContentCallback(), | |
595 callback); | |
596 } | |
597 | |
598 void FileSystem::GetFileForSaving(const base::FilePath& file_path, | |
599 const GetFileCallback& callback) { | |
600 DCHECK(thread_checker_.CalledOnValidThread()); | |
601 DCHECK(!callback.is_null()); | |
602 | |
603 get_file_for_saving_operation_->GetFileForSaving(file_path, callback); | |
604 } | |
605 | |
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()); | |
615 | |
616 return download_operation_->EnsureFileDownloadedByPath( | |
617 file_path, | |
618 ClientContext(USER_INITIATED), | |
619 initialized_callback, | |
620 get_content_callback, | |
621 base::Bind(&GetFileCallbackToFileOperationCallbackAdapter, | |
622 completion_callback)); | |
623 } | |
624 | |
625 void FileSystem::GetResourceEntry( | |
626 const base::FilePath& file_path, | |
627 const GetResourceEntryCallback& callback) { | |
628 DCHECK(thread_checker_.CalledOnValidThread()); | |
629 DCHECK(!callback.is_null()); | |
630 | |
631 ReadDirectory(file_path.DirName(), | |
632 ReadDirectoryEntriesCallback(), | |
633 base::Bind(&FileSystem::GetResourceEntryAfterRead, | |
634 weak_ptr_factory_.GetWeakPtr(), | |
635 file_path, | |
636 callback)); | |
637 } | |
638 | |
639 void FileSystem::GetResourceEntryAfterRead( | |
640 const base::FilePath& file_path, | |
641 const GetResourceEntryCallback& callback, | |
642 FileError error) { | |
643 DCHECK(thread_checker_.CalledOnValidThread()); | |
644 DCHECK(!callback.is_null()); | |
645 | |
646 DVLOG_IF(1, error != FILE_ERROR_OK) << "ReadDirectory failed. " | |
647 << FileErrorToString(error); | |
648 | |
649 scoped_ptr<ResourceEntry> entry(new ResourceEntry); | |
650 ResourceEntry* entry_ptr = entry.get(); | |
651 base::PostTaskAndReplyWithResult( | |
652 blocking_task_runner_.get(), | |
653 FROM_HERE, | |
654 base::Bind(&GetLocallyStoredResourceEntry, | |
655 resource_metadata_, | |
656 cache_, | |
657 file_path, | |
658 entry_ptr), | |
659 base::Bind(&RunGetResourceEntryCallback, callback, base::Passed(&entry))); | |
660 } | |
661 | |
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()); | |
668 | |
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); | |
674 | |
675 directory_loader_->ReadDirectory( | |
676 directory_path, entries_callback, completion_callback); | |
677 | |
678 // Also start loading all of the user's contents. | |
679 change_list_loader_->LoadIfNeeded( | |
680 base::Bind(&util::EmptyFileOperationCallback)); | |
681 } | |
682 | |
683 void FileSystem::GetAvailableSpace( | |
684 const GetAvailableSpaceCallback& callback) { | |
685 DCHECK(thread_checker_.CalledOnValidThread()); | |
686 DCHECK(!callback.is_null()); | |
687 | |
688 about_resource_loader_->GetAboutResource( | |
689 base::Bind(&FileSystem::OnGetAboutResource, | |
690 weak_ptr_factory_.GetWeakPtr(), | |
691 callback)); | |
692 } | |
693 | |
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()); | |
700 | |
701 FileError error = GDataToFileError(status); | |
702 if (error != FILE_ERROR_OK) { | |
703 callback.Run(error, -1, -1); | |
704 return; | |
705 } | |
706 DCHECK(about_resource); | |
707 | |
708 callback.Run(FILE_ERROR_OK, about_resource->quota_bytes_total(), | |
709 about_resource->quota_bytes_used_aggregate()); | |
710 } | |
711 | |
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()); | |
717 | |
718 // Resolve the resource id. | |
719 ResourceEntry* entry = new ResourceEntry; | |
720 base::PostTaskAndReplyWithResult( | |
721 blocking_task_runner_.get(), | |
722 FROM_HERE, | |
723 base::Bind(&internal::ResourceMetadata::GetResourceEntryByPath, | |
724 base::Unretained(resource_metadata_), | |
725 file_path, | |
726 entry), | |
727 base::Bind(&FileSystem::GetShareUrlAfterGetResourceEntry, | |
728 weak_ptr_factory_.GetWeakPtr(), | |
729 file_path, | |
730 embed_origin, | |
731 callback, | |
732 base::Owned(entry))); | |
733 } | |
734 | |
735 void FileSystem::GetShareUrlAfterGetResourceEntry( | |
736 const base::FilePath& file_path, | |
737 const GURL& embed_origin, | |
738 const GetShareUrlCallback& callback, | |
739 ResourceEntry* entry, | |
740 FileError error) { | |
741 DCHECK(thread_checker_.CalledOnValidThread()); | |
742 DCHECK(!callback.is_null()); | |
743 | |
744 if (error != FILE_ERROR_OK) { | |
745 callback.Run(error, GURL()); | |
746 return; | |
747 } | |
748 if (entry->resource_id().empty()) { | |
749 // This entry does not exist on the server. Just return. | |
750 callback.Run(FILE_ERROR_FAILED, GURL()); | |
751 return; | |
752 } | |
753 | |
754 scheduler_->GetShareUrl( | |
755 entry->resource_id(), | |
756 embed_origin, | |
757 ClientContext(USER_INITIATED), | |
758 base::Bind(&FileSystem::OnGetResourceEntryForGetShareUrl, | |
759 weak_ptr_factory_.GetWeakPtr(), | |
760 callback)); | |
761 } | |
762 | |
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()); | |
769 | |
770 FileError error = GDataToFileError(status); | |
771 if (error != FILE_ERROR_OK) { | |
772 callback.Run(error, GURL()); | |
773 return; | |
774 } | |
775 | |
776 if (share_url.is_empty()) { | |
777 callback.Run(FILE_ERROR_FAILED, GURL()); | |
778 return; | |
779 } | |
780 | |
781 callback.Run(FILE_ERROR_OK, share_url); | |
782 } | |
783 | |
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); | |
790 } | |
791 | |
792 void FileSystem::SearchMetadata(const std::string& query, | |
793 int options, | |
794 int at_most_num_matches, | |
795 const SearchMetadataCallback& callback) { | |
796 DCHECK(thread_checker_.CalledOnValidThread()); | |
797 | |
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; | |
801 | |
802 drive::internal::SearchMetadata( | |
803 blocking_task_runner_, resource_metadata_, query, | |
804 base::Bind(&drive::internal::MatchesType, options), at_most_num_matches, | |
805 callback); | |
806 } | |
807 | |
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)); | |
816 } | |
817 | |
818 void FileSystem::OnFileChangedByOperation(const FileChange& changed_files) { | |
819 DCHECK(thread_checker_.CalledOnValidThread()); | |
820 | |
821 FOR_EACH_OBSERVER( | |
822 FileSystemObserver, observers_, OnFileChanged(changed_files)); | |
823 } | |
824 | |
825 void FileSystem::OnEntryUpdatedByOperation(const ClientContext& context, | |
826 const std::string& local_id) { | |
827 sync_client_->AddUpdateTask(context, local_id); | |
828 } | |
829 | |
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(), | |
835 FROM_HERE, | |
836 base::Bind(&internal::ResourceMetadata::GetFilePath, | |
837 base::Unretained(resource_metadata_), | |
838 local_id, | |
839 file_path), | |
840 base::Bind(&FileSystem::OnDriveSyncErrorAfterGetFilePath, | |
841 weak_ptr_factory_.GetWeakPtr(), | |
842 type, | |
843 base::Owned(file_path))); | |
844 } | |
845 | |
846 void FileSystem::OnDriveSyncErrorAfterGetFilePath( | |
847 file_system::DriveSyncErrorType type, | |
848 const base::FilePath* file_path, | |
849 FileError error) { | |
850 if (error != FILE_ERROR_OK) | |
851 return; | |
852 FOR_EACH_OBSERVER(FileSystemObserver, | |
853 observers_, | |
854 OnDriveSyncError(type, *file_path)); | |
855 } | |
856 | |
857 bool FileSystem::WaitForSyncComplete(const std::string& local_id, | |
858 const FileOperationCallback& callback) { | |
859 return sync_client_->WaitForUpdateTaskToComplete(local_id, callback); | |
860 } | |
861 | |
862 void FileSystem::OnDirectoryReloaded(const base::FilePath& directory_path) { | |
863 DCHECK(thread_checker_.CalledOnValidThread()); | |
864 | |
865 FOR_EACH_OBSERVER( | |
866 FileSystemObserver, observers_, OnDirectoryChanged(directory_path)); | |
867 } | |
868 | |
869 void FileSystem::OnFileChanged(const FileChange& changed_files) { | |
870 DCHECK(thread_checker_.CalledOnValidThread()); | |
871 | |
872 FOR_EACH_OBSERVER( | |
873 FileSystemObserver, observers_, OnFileChanged(changed_files)); | |
874 } | |
875 | |
876 void FileSystem::OnLoadFromServerComplete() { | |
877 DCHECK(thread_checker_.CalledOnValidThread()); | |
878 | |
879 sync_client_->StartCheckingExistingPinnedFiles(); | |
880 } | |
881 | |
882 void FileSystem::OnInitialLoadComplete() { | |
883 DCHECK(thread_checker_.CalledOnValidThread()); | |
884 | |
885 blocking_task_runner_->PostTask(FROM_HERE, | |
886 base::Bind(&internal::RemoveStaleCacheFiles, | |
887 cache_, | |
888 resource_metadata_)); | |
889 sync_client_->StartProcessingBacklog(); | |
890 } | |
891 | |
892 void FileSystem::GetMetadata( | |
893 const GetFilesystemMetadataCallback& callback) { | |
894 DCHECK(thread_checker_.CalledOnValidThread()); | |
895 DCHECK(!callback.is_null()); | |
896 | |
897 FileSystemMetadata metadata; | |
898 metadata.refreshing = change_list_loader_->IsRefreshing(); | |
899 | |
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_; | |
903 | |
904 int64* largest_changestamp = new int64(0); | |
905 base::PostTaskAndReplyWithResult( | |
906 blocking_task_runner_.get(), | |
907 FROM_HERE, | |
908 base::Bind(&internal::ResourceMetadata::GetLargestChangestamp, | |
909 base::Unretained(resource_metadata_), | |
910 largest_changestamp), | |
911 base::Bind(&OnGetLargestChangestamp, | |
912 metadata, | |
913 callback, | |
914 base::Owned(largest_changestamp))); | |
915 } | |
916 | |
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()); | |
922 | |
923 base::FilePath* cache_file_path = new base::FilePath; | |
924 base::PostTaskAndReplyWithResult( | |
925 blocking_task_runner_.get(), | |
926 FROM_HERE, | |
927 base::Bind(&MarkCacheFileAsMountedInternal, | |
928 resource_metadata_, | |
929 cache_, | |
930 drive_file_path, | |
931 cache_file_path), | |
932 base::Bind( | |
933 &RunMarkMountedCallback, callback, base::Owned(cache_file_path))); | |
934 } | |
935 | |
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()); | |
941 | |
942 if (!cache_->IsUnderFileCacheDirectory(cache_file_path)) { | |
943 callback.Run(FILE_ERROR_FAILED); | |
944 return; | |
945 } | |
946 | |
947 base::PostTaskAndReplyWithResult( | |
948 blocking_task_runner_.get(), | |
949 FROM_HERE, | |
950 base::Bind(&internal::FileCache::MarkAsUnmounted, | |
951 base::Unretained(cache_), | |
952 cache_file_path), | |
953 callback); | |
954 } | |
955 | |
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()); | |
962 | |
963 // Resolve the resource id. | |
964 ResourceEntry* const entry = new ResourceEntry; | |
965 base::PostTaskAndReplyWithResult( | |
966 blocking_task_runner_.get(), | |
967 FROM_HERE, | |
968 base::Bind(&internal::ResourceMetadata::GetResourceEntryByPath, | |
969 base::Unretained(resource_metadata_), | |
970 drive_file_path, | |
971 entry), | |
972 base::Bind(&FileSystem::AddPermissionAfterGetResourceEntry, | |
973 weak_ptr_factory_.GetWeakPtr(), | |
974 email, | |
975 role, | |
976 callback, | |
977 base::Owned(entry))); | |
978 } | |
979 | |
980 void FileSystem::AddPermissionAfterGetResourceEntry( | |
981 const std::string& email, | |
982 google_apis::drive::PermissionRole role, | |
983 const FileOperationCallback& callback, | |
984 ResourceEntry* entry, | |
985 FileError error) { | |
986 DCHECK(thread_checker_.CalledOnValidThread()); | |
987 | |
988 if (error != FILE_ERROR_OK) { | |
989 callback.Run(error); | |
990 return; | |
991 } | |
992 | |
993 scheduler_->AddPermission( | |
994 entry->resource_id(), | |
995 email, | |
996 role, | |
997 base::Bind(&RunFileOperationCallbackAsEntryActionCallback, callback)); | |
998 } | |
999 | |
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()); | |
1008 | |
1009 set_property_operation_->SetProperty(drive_file_path, visibility, key, value, | |
1010 callback); | |
1011 } | |
1012 | |
1013 void FileSystem::OpenFile(const base::FilePath& file_path, | |
1014 OpenMode open_mode, | |
1015 const std::string& mime_type, | |
1016 const OpenFileCallback& callback) { | |
1017 DCHECK(thread_checker_.CalledOnValidThread()); | |
1018 DCHECK(!callback.is_null()); | |
1019 | |
1020 open_file_operation_->OpenFile(file_path, open_mode, mime_type, callback); | |
1021 } | |
1022 | |
1023 void FileSystem::GetPathFromResourceId(const std::string& resource_id, | |
1024 const GetFilePathCallback& callback) { | |
1025 DCHECK(thread_checker_.CalledOnValidThread()); | |
1026 DCHECK(!callback.is_null()); | |
1027 | |
1028 base::FilePath* const file_path = new base::FilePath(); | |
1029 base::PostTaskAndReplyWithResult( | |
1030 blocking_task_runner_.get(), | |
1031 FROM_HERE, | |
1032 base::Bind(&GetPathFromResourceIdOnBlockingPool, | |
1033 resource_metadata_, | |
1034 resource_id, | |
1035 file_path), | |
1036 base::Bind(&GetPathFromResourceIdAfterGetPath, | |
1037 base::Owned(file_path), | |
1038 callback)); | |
1039 } | |
1040 | |
1041 void FileSystem::FreeDiskSpaceIfNeededFor( | |
1042 int64 num_bytes, | |
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), | |
1049 callback); | |
1050 } | |
1051 | |
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); | |
1059 } | |
1060 } // namespace drive | |
OLD | NEW |