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