Index: chrome/browser/chromeos/gdata/gdata_file_system.cc |
diff --git a/chrome/browser/chromeos/gdata/gdata_file_system.cc b/chrome/browser/chromeos/gdata/gdata_file_system.cc |
deleted file mode 100644 |
index 88cde5e3bd032f0aed77e234a301b5ca6cca2092..0000000000000000000000000000000000000000 |
--- a/chrome/browser/chromeos/gdata/gdata_file_system.cc |
+++ /dev/null |
@@ -1,3374 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome/browser/chromeos/gdata/gdata_file_system.h" |
- |
-#include <set> |
-#include <utility> |
- |
-#include "base/bind.h" |
-#include "base/file_util.h" |
-#include "base/json/json_file_value_serializer.h" |
-#include "base/message_loop.h" |
-#include "base/message_loop_proxy.h" |
-#include "base/metrics/histogram.h" |
-#include "base/platform_file.h" |
-#include "base/threading/sequenced_worker_pool.h" |
-#include "base/values.h" |
-#include "chrome/browser/chromeos/gdata/drive.pb.h" |
-#include "chrome/browser/chromeos/gdata/drive_api_parser.h" |
-#include "chrome/browser/chromeos/gdata/drive_files.h" |
-#include "chrome/browser/chromeos/gdata/drive_service_interface.h" |
-#include "chrome/browser/chromeos/gdata/drive_webapps_registry.h" |
-#include "chrome/browser/chromeos/gdata/gdata_download_observer.h" |
-#include "chrome/browser/chromeos/gdata/gdata_protocol_handler.h" |
-#include "chrome/browser/chromeos/gdata/gdata_system_service.h" |
-#include "chrome/browser/chromeos/gdata/gdata_uploader.h" |
-#include "chrome/browser/chromeos/gdata/gdata_util.h" |
-#include "chrome/browser/chromeos/gdata/task_util.h" |
-#include "chrome/browser/prefs/pref_service.h" |
-#include "chrome/browser/profiles/profile.h" |
-#include "chrome/common/chrome_notification_types.h" |
-#include "chrome/common/pref_names.h" |
-#include "content/public/browser/browser_thread.h" |
-#include "content/public/browser/notification_details.h" |
-#include "net/base/mime_util.h" |
- |
-using content::BrowserThread; |
- |
-namespace gdata { |
-namespace { |
- |
-const char kMimeTypeJson[] = "application/json"; |
-const char kMimeTypeOctetStream[] = "application/octet-stream"; |
- |
-const char kEmptyFilePath[] = "/dev/null"; |
- |
-// GData update check interval (in seconds). |
-#ifndef NDEBUG |
-const int kGDataUpdateCheckIntervalInSec = 5; |
-#else |
-const int kGDataUpdateCheckIntervalInSec = 60; |
-#endif |
- |
-//================================ Helper functions ============================ |
- |
-// Runs GetFileCallback with pointers dereferenced. |
-// Used for PostTaskAndReply(). |
-void RunGetFileCallbackHelper(const GetFileCallback& callback, |
- DriveFileError* error, |
- FilePath* file_path, |
- std::string* mime_type, |
- DriveFileType* file_type) { |
- DCHECK(error); |
- DCHECK(file_path); |
- DCHECK(mime_type); |
- DCHECK(file_type); |
- |
- if (!callback.is_null()) |
- callback.Run(*error, *file_path, *mime_type, *file_type); |
-} |
- |
-// Ditto for FileOperationCallback |
-void RunFileOperationCallbackHelper( |
- const FileOperationCallback& callback, |
- DriveFileError* error) { |
- DCHECK(error); |
- |
- if (!callback.is_null()) |
- callback.Run(*error); |
-} |
- |
-// Callback for cache file operations invoked by AddUploadedFileOnUIThread. |
-void OnCacheUpdatedForAddUploadedFile( |
- const base::Closure& callback, |
- DriveFileError /* error */, |
- const std::string& /* resource_id */, |
- const std::string& /* md5 */) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- if (!callback.is_null()) |
- callback.Run(); |
-} |
- |
-// Helper function called upon completion of AddUploadFile invoked by |
-// OnTransferCompleted. |
-void OnAddUploadFileCompleted( |
- const FileOperationCallback& callback, |
- DriveFileError error) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- if (!callback.is_null()) |
- callback.Run(error); |
-} |
- |
-// The class to wait for the initial load of root feed and runs the callback |
-// after the initialization. |
-class InitialLoadObserver : public GDataFileSystemInterface::Observer { |
- public: |
- InitialLoadObserver(GDataFileSystemInterface* file_system, |
- const base::Closure& callback) |
- : file_system_(file_system), callback_(callback) {} |
- |
- virtual void OnInitialLoadFinished() OVERRIDE { |
- if (!callback_.is_null()) |
- base::MessageLoopProxy::current()->PostTask(FROM_HERE, callback_); |
- file_system_->RemoveObserver(this); |
- base::MessageLoopProxy::current()->DeleteSoon(FROM_HERE, this); |
- } |
- |
- private: |
- GDataFileSystemInterface* file_system_; |
- base::Closure callback_; |
-}; |
- |
-// Gets the file size of |local_file|. |
-void GetLocalFileSizeOnBlockingPool(const FilePath& local_file, |
- DriveFileError* error, |
- int64* file_size) { |
- DCHECK(error); |
- DCHECK(file_size); |
- |
- *file_size = 0; |
- *error = file_util::GetFileSize(local_file, file_size) ? |
- DRIVE_FILE_OK : |
- DRIVE_FILE_ERROR_NOT_FOUND; |
-} |
- |
-// Gets the file size and the content type of |local_file|. |
-void GetLocalFileInfoOnBlockingPool( |
- const FilePath& local_file, |
- DriveFileError* error, |
- int64* file_size, |
- std::string* content_type) { |
- DCHECK(error); |
- DCHECK(file_size); |
- DCHECK(content_type); |
- |
- if (!net::GetMimeTypeFromExtension(local_file.Extension(), content_type)) |
- *content_type = kMimeTypeOctetStream; |
- |
- *file_size = 0; |
- *error = file_util::GetFileSize(local_file, file_size) ? |
- DRIVE_FILE_OK : |
- DRIVE_FILE_ERROR_NOT_FOUND; |
-} |
- |
-// Checks if a local file at |local_file_path| is a JSON file referencing a |
-// hosted document on blocking pool, and if so, gets the resource ID of the |
-// document. |
-void GetDocumentResourceIdOnBlockingPool( |
- const FilePath& local_file_path, |
- std::string* resource_id) { |
- DCHECK(resource_id); |
- |
- if (DocumentEntry::HasHostedDocumentExtension(local_file_path)) { |
- std::string error; |
- DictionaryValue* dict_value = NULL; |
- JSONFileValueSerializer serializer(local_file_path); |
- scoped_ptr<Value> value(serializer.Deserialize(NULL, &error)); |
- if (value.get() && value->GetAsDictionary(&dict_value)) |
- dict_value->GetString("resource_id", resource_id); |
- } |
-} |
- |
-// Creates a temporary JSON file representing a document with |edit_url| |
-// and |resource_id| under |document_dir| on blocking pool. |
-void CreateDocumentJsonFileOnBlockingPool( |
- const FilePath& document_dir, |
- const GURL& edit_url, |
- const std::string& resource_id, |
- DriveFileError* error, |
- FilePath* temp_file_path, |
- std::string* mime_type, |
- DriveFileType* file_type) { |
- DCHECK(error); |
- DCHECK(temp_file_path); |
- DCHECK(mime_type); |
- DCHECK(file_type); |
- |
- *error = DRIVE_FILE_ERROR_FAILED; |
- |
- if (file_util::CreateTemporaryFileInDir(document_dir, temp_file_path)) { |
- std::string document_content = base::StringPrintf( |
- "{\"url\": \"%s\", \"resource_id\": \"%s\"}", |
- edit_url.spec().c_str(), resource_id.c_str()); |
- int document_size = static_cast<int>(document_content.size()); |
- if (file_util::WriteFile(*temp_file_path, document_content.data(), |
- document_size) == document_size) { |
- *error = DRIVE_FILE_OK; |
- } |
- } |
- |
- *mime_type = kMimeTypeJson; |
- *file_type = HOSTED_DOCUMENT; |
- if (*error != DRIVE_FILE_OK) |
- temp_file_path->clear(); |
-} |
- |
-// Gets the information of the file at local path |path|. The information is |
-// filled in |file_info|, and if it fails |result| will be assigned false. |
-void GetFileInfoOnBlockingPool(const FilePath& path, |
- base::PlatformFileInfo* file_info, |
- bool* result) { |
- *result = file_util::GetFileInfo(path, file_info); |
-} |
- |
-// Copies a file from |src_file_path| to |dest_file_path| on the local |
-// file system using file_util::CopyFile. |error| is set to |
-// DRIVE_FILE_OK on success or DRIVE_FILE_ERROR_FAILED |
-// otherwise. |
-void CopyLocalFileOnBlockingPool( |
- const FilePath& src_file_path, |
- const FilePath& dest_file_path, |
- DriveFileError* error) { |
- DCHECK(error); |
- |
- *error = file_util::CopyFile(src_file_path, dest_file_path) ? |
- DRIVE_FILE_OK : DRIVE_FILE_ERROR_FAILED; |
-} |
- |
-// Callback for GetEntryByResourceIdAsync. |
-// Adds |entry| to |results|. Runs |callback| with |results| when |
-// |run_callback| is true. When |entry| is not present in our local file system |
-// snapshot, it is not added to |results|. Instead, |entry_skipped_callback| is |
-// called. |
-void AddEntryToSearchResults( |
- std::vector<SearchResultInfo>* results, |
- const SearchCallback& callback, |
- const base::Closure& entry_skipped_callback, |
- DriveFileError error, |
- bool run_callback, |
- const GURL& next_feed, |
- DriveEntry* entry) { |
- // If a result is not present in our local file system snapshot, invoke |
- // |entry_skipped_callback| and refreshes the snapshot with delta feed. |
- // For example, this may happen if the entry has recently been added to the |
- // drive (and we still haven't received its delta feed). |
- if (entry) { |
- const bool is_directory = entry->AsDriveDirectory() != NULL; |
- results->push_back(SearchResultInfo(entry->GetFilePath(), is_directory)); |
- } else { |
- if (!entry_skipped_callback.is_null()) |
- entry_skipped_callback.Run(); |
- } |
- |
- if (run_callback) { |
- scoped_ptr<std::vector<SearchResultInfo> > result_vec(results); |
- if (!callback.is_null()) |
- callback.Run(error, next_feed, result_vec.Pass()); |
- } |
-} |
- |
-// Helper function for binding |path| to GetEntryInfoWithFilePathCallback and |
-// create GetEntryInfoCallback. |
-void RunGetEntryInfoWithFilePathCallback( |
- const GetEntryInfoWithFilePathCallback& callback, |
- const FilePath& path, |
- DriveFileError error, |
- scoped_ptr<DriveEntryProto> entry_proto) { |
- if (!callback.is_null()) |
- callback.Run(error, path, entry_proto.Pass()); |
-} |
- |
-} // namespace |
- |
-// GDataFileSystem::CreateDirectoryParams struct implementation. |
-struct GDataFileSystem::CreateDirectoryParams { |
- CreateDirectoryParams(const FilePath& created_directory_path, |
- const FilePath& target_directory_path, |
- bool is_exclusive, |
- bool is_recursive, |
- const FileOperationCallback& callback); |
- ~CreateDirectoryParams(); |
- |
- const FilePath created_directory_path; |
- const FilePath target_directory_path; |
- const bool is_exclusive; |
- const bool is_recursive; |
- FileOperationCallback callback; |
-}; |
- |
-GDataFileSystem::CreateDirectoryParams::CreateDirectoryParams( |
- const FilePath& created_directory_path, |
- const FilePath& target_directory_path, |
- bool is_exclusive, |
- bool is_recursive, |
- const FileOperationCallback& callback) |
- : created_directory_path(created_directory_path), |
- target_directory_path(target_directory_path), |
- is_exclusive(is_exclusive), |
- is_recursive(is_recursive), |
- callback(callback) { |
-} |
- |
-GDataFileSystem::CreateDirectoryParams::~CreateDirectoryParams() { |
-} |
- |
-// GDataFileSystem::GetFileCompleteForOpenParams struct implementation. |
-struct GDataFileSystem::GetFileCompleteForOpenParams { |
- GetFileCompleteForOpenParams(const std::string& resource_id, |
- const std::string& md5); |
- ~GetFileCompleteForOpenParams(); |
- std::string resource_id; |
- std::string md5; |
-}; |
- |
-GDataFileSystem::GetFileCompleteForOpenParams::GetFileCompleteForOpenParams( |
- const std::string& resource_id, |
- const std::string& md5) |
- : resource_id(resource_id), |
- md5(md5) { |
-} |
- |
-GDataFileSystem::GetFileCompleteForOpenParams::~GetFileCompleteForOpenParams() { |
-} |
- |
-// GDataFileSystem::GetFileFromCacheParams struct implementation. |
-struct GDataFileSystem::GetFileFromCacheParams { |
- GetFileFromCacheParams( |
- const FilePath& virtual_file_path, |
- const FilePath& local_tmp_path, |
- const GURL& content_url, |
- const std::string& resource_id, |
- const std::string& md5, |
- const std::string& mime_type, |
- const GetFileCallback& get_file_callback, |
- const GetContentCallback& get_content_callback); |
- ~GetFileFromCacheParams(); |
- |
- FilePath virtual_file_path; |
- FilePath local_tmp_path; |
- GURL content_url; |
- std::string resource_id; |
- std::string md5; |
- std::string mime_type; |
- const GetFileCallback get_file_callback; |
- const GetContentCallback get_content_callback; |
-}; |
- |
-GDataFileSystem::GetFileFromCacheParams::GetFileFromCacheParams( |
- const FilePath& virtual_file_path, |
- const FilePath& local_tmp_path, |
- const GURL& content_url, |
- const std::string& resource_id, |
- const std::string& md5, |
- const std::string& mime_type, |
- const GetFileCallback& get_file_callback, |
- const GetContentCallback& get_content_callback) |
- : virtual_file_path(virtual_file_path), |
- local_tmp_path(local_tmp_path), |
- content_url(content_url), |
- resource_id(resource_id), |
- md5(md5), |
- mime_type(mime_type), |
- get_file_callback(get_file_callback), |
- get_content_callback(get_content_callback) { |
-} |
- |
-GDataFileSystem::GetFileFromCacheParams::~GetFileFromCacheParams() { |
-} |
- |
-// GDataFileSystem::StartFileUploadParams implementation. |
-struct GDataFileSystem::StartFileUploadParams { |
- StartFileUploadParams(const FilePath& in_local_file_path, |
- const FilePath& in_remote_file_path, |
- const FileOperationCallback& in_callback) |
- : local_file_path(in_local_file_path), |
- remote_file_path(in_remote_file_path), |
- callback(in_callback) {} |
- |
- const FilePath local_file_path; |
- const FilePath remote_file_path; |
- const FileOperationCallback callback; |
-}; |
- |
-// GDataFileSystem::AddUploadedFileParams implementation. |
-struct GDataFileSystem::AddUploadedFileParams { |
- AddUploadedFileParams(UploadMode upload_mode, |
- DriveDirectory* parent_dir, |
- scoped_ptr<DriveEntry> new_entry, |
- const FilePath& file_content_path, |
- DriveCache::FileOperationType cache_operation, |
- const base::Closure& callback) |
- : upload_mode(upload_mode), |
- parent_dir(parent_dir), |
- new_entry(new_entry.Pass()), |
- file_content_path(file_content_path), |
- cache_operation(cache_operation), |
- callback(callback) { |
- } |
- |
- UploadMode upload_mode; |
- DriveDirectory* parent_dir; |
- scoped_ptr<DriveEntry> new_entry; |
- FilePath file_content_path; |
- DriveCache::FileOperationType cache_operation; |
- base::Closure callback; |
- std::string resource_id; |
- std::string md5; |
-}; |
- |
- |
-// GDataFileSystem class implementation. |
- |
-GDataFileSystem::GDataFileSystem( |
- Profile* profile, |
- DriveCache* cache, |
- DriveServiceInterface* drive_service, |
- GDataUploaderInterface* uploader, |
- DriveWebAppsRegistryInterface* webapps_registry, |
- base::SequencedTaskRunner* blocking_task_runner) |
- : profile_(profile), |
- cache_(cache), |
- uploader_(uploader), |
- drive_service_(drive_service), |
- webapps_registry_(webapps_registry), |
- update_timer_(true /* retain_user_task */, true /* is_repeating */), |
- hide_hosted_docs_(false), |
- blocking_task_runner_(blocking_task_runner), |
- ui_weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
- ui_weak_ptr_(ui_weak_ptr_factory_.GetWeakPtr()) { |
- // Should be created from the file browser extension API on UI thread. |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
-} |
- |
-void GDataFileSystem::Initialize() { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- drive_service_->Initialize(profile_); |
- |
- resource_metadata_.reset(new DriveResourceMetadata); |
- feed_loader_.reset(new GDataWapiFeedLoader(resource_metadata_.get(), |
- drive_service_, |
- webapps_registry_, |
- cache_, |
- blocking_task_runner_)); |
- feed_loader_->AddObserver(this); |
- |
- PrefService* pref_service = profile_->GetPrefs(); |
- hide_hosted_docs_ = pref_service->GetBoolean(prefs::kDisableGDataHostedFiles); |
- |
- InitializePreferenceObserver(); |
-} |
- |
-void GDataFileSystem::CheckForUpdates() { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- ContentOrigin initial_origin = resource_metadata_->origin(); |
- if (initial_origin == FROM_SERVER) { |
- resource_metadata_->set_origin(REFRESHING); |
- feed_loader_->ReloadFromServerIfNeeded( |
- initial_origin, |
- resource_metadata_->largest_changestamp(), |
- base::Bind(&GDataFileSystem::OnUpdateChecked, |
- ui_weak_ptr_, |
- initial_origin)); |
- } |
-} |
- |
-void GDataFileSystem::OnUpdateChecked(ContentOrigin initial_origin, |
- DriveFileError error) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- if (error != DRIVE_FILE_OK) |
- resource_metadata_->set_origin(initial_origin); |
-} |
- |
-GDataFileSystem::~GDataFileSystem() { |
- // This should be called from UI thread, from GDataSystemService shutdown. |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- feed_loader_->RemoveObserver(this); |
- |
- // Cancel all the in-flight operations. |
- // This asynchronously cancels the URL fetch operations. |
- drive_service_->CancelAll(); |
-} |
- |
-void GDataFileSystem::AddObserver( |
- GDataFileSystemInterface::Observer* observer) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- observers_.AddObserver(observer); |
-} |
- |
-void GDataFileSystem::RemoveObserver( |
- GDataFileSystemInterface::Observer* observer) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- observers_.RemoveObserver(observer); |
-} |
- |
-void GDataFileSystem::StartUpdates() { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- DCHECK(!update_timer_.IsRunning()); |
- update_timer_.Start(FROM_HERE, |
- base::TimeDelta::FromSeconds( |
- kGDataUpdateCheckIntervalInSec), |
- base::Bind(&GDataFileSystem::CheckForUpdates, |
- ui_weak_ptr_)); |
-} |
- |
-void GDataFileSystem::StopUpdates() { |
- // If unmount request comes from filesystem side, this method may be called |
- // twice. First is just after unmounting on filesystem, second is after |
- // unmounting on filemanager on JS. In other words, if this is called from |
- // GDataSystemService::RemoveDriveMountPoint(), this will be called again from |
- // FileBrowserEventRouter::HandleRemoteUpdateRequestOnUIThread(). |
- // We choose to stopping updates asynchronous without waiting for filemanager, |
- // rather than waiting for completion of unmounting on filemanager. |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- if (update_timer_.IsRunning()) |
- update_timer_.Stop(); |
-} |
- |
-void GDataFileSystem::GetEntryInfoByResourceId( |
- const std::string& resource_id, |
- const GetEntryInfoWithFilePathCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
- BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- DCHECK(!callback.is_null()); |
- |
- RunTaskOnUIThread( |
- base::Bind(&GDataFileSystem::GetEntryInfoByResourceIdOnUIThread, |
- ui_weak_ptr_, |
- resource_id, |
- CreateRelayCallback(callback))); |
-} |
- |
-void GDataFileSystem::GetEntryInfoByResourceIdOnUIThread( |
- const std::string& resource_id, |
- const GetEntryInfoWithFilePathCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- resource_metadata_->GetEntryByResourceIdAsync(resource_id, |
- base::Bind(&GDataFileSystem::GetEntryInfoByEntryOnUIThread, |
- ui_weak_ptr_, |
- callback)); |
-} |
- |
-void GDataFileSystem::GetEntryInfoByEntryOnUIThread( |
- const GetEntryInfoWithFilePathCallback& callback, |
- DriveEntry* entry) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- if (entry) { |
- scoped_ptr<DriveEntryProto> entry_proto(new DriveEntryProto); |
- entry->ToProtoFull(entry_proto.get()); |
- CheckLocalModificationAndRun( |
- entry_proto.Pass(), |
- base::Bind(&RunGetEntryInfoWithFilePathCallback, |
- callback, entry->GetFilePath())); |
- } else { |
- callback.Run(DRIVE_FILE_ERROR_NOT_FOUND, |
- FilePath(), |
- scoped_ptr<DriveEntryProto>()); |
- } |
-} |
- |
-void GDataFileSystem::LoadFeedIfNeeded(const FileOperationCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- if (resource_metadata_->origin() == INITIALIZING) { |
- // If root feed is not initialized but the initialization process has |
- // already started, add an observer to execute the remaining task after |
- // the end of the initialization. |
- AddObserver(new InitialLoadObserver(this, |
- base::Bind(callback, DRIVE_FILE_OK))); |
- return; |
- } else if (resource_metadata_->origin() == UNINITIALIZED) { |
- // Load root feed from this disk cache. Upon completion, kick off server |
- // fetching. |
- resource_metadata_->set_origin(INITIALIZING); |
- feed_loader_->LoadFromCache( |
- true, // should_load_from_server |
- base::Bind(&GDataFileSystem::NotifyInitialLoadFinishedAndRun, |
- ui_weak_ptr_, |
- callback)); |
- return; |
- } |
- |
- // The feed has already been loaded, so we have nothing to do, but post a |
- // task to the same thread, rather than calling it here, as |
- // LoadFeedIfNeeded() is asynchronous. |
- base::MessageLoopProxy::current()->PostTask( |
- FROM_HERE, |
- base::Bind(callback, DRIVE_FILE_OK)); |
-} |
- |
-void GDataFileSystem::TransferFileFromRemoteToLocal( |
- const FilePath& remote_src_file_path, |
- const FilePath& local_dest_file_path, |
- const FileOperationCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- GetFileByPath(remote_src_file_path, |
- base::Bind(&GDataFileSystem::OnGetFileCompleteForTransferFile, |
- ui_weak_ptr_, |
- local_dest_file_path, |
- callback), |
- GetContentCallback()); |
-} |
- |
-void GDataFileSystem::TransferFileFromLocalToRemote( |
- const FilePath& local_src_file_path, |
- const FilePath& remote_dest_file_path, |
- const FileOperationCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- // Make sure the destination directory exists. |
- resource_metadata_->GetEntryInfoByPath( |
- remote_dest_file_path.DirName(), |
- base::Bind( |
- &GDataFileSystem::TransferFileFromLocalToRemoteAfterGetEntryInfo, |
- ui_weak_ptr_, |
- local_src_file_path, |
- remote_dest_file_path, |
- callback)); |
-} |
- |
-void GDataFileSystem::TransferFileFromLocalToRemoteAfterGetEntryInfo( |
- const FilePath& local_src_file_path, |
- const FilePath& remote_dest_file_path, |
- const FileOperationCallback& callback, |
- DriveFileError error, |
- scoped_ptr<DriveEntryProto> entry_proto) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- if (error != DRIVE_FILE_OK) { |
- callback.Run(error); |
- return; |
- } |
- |
- DCHECK(entry_proto.get()); |
- if (!entry_proto->file_info().is_directory()) { |
- // The parent of |remote_dest_file_path| is not a directory. |
- callback.Run(DRIVE_FILE_ERROR_NOT_A_DIRECTORY); |
- return; |
- } |
- |
- std::string* resource_id = new std::string; |
- util::PostBlockingPoolSequencedTaskAndReply( |
- FROM_HERE, |
- blocking_task_runner_, |
- base::Bind(&GetDocumentResourceIdOnBlockingPool, |
- local_src_file_path, |
- resource_id), |
- base::Bind(&GDataFileSystem::TransferFileForResourceId, |
- ui_weak_ptr_, |
- local_src_file_path, |
- remote_dest_file_path, |
- callback, |
- base::Owned(resource_id))); |
-} |
- |
-void GDataFileSystem::TransferFileForResourceId( |
- const FilePath& local_file_path, |
- const FilePath& remote_dest_file_path, |
- const FileOperationCallback& callback, |
- std::string* resource_id) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(resource_id); |
- DCHECK(!callback.is_null()); |
- |
- if (resource_id->empty()) { |
- // If |resource_id| is empty, upload the local file as a regular file. |
- TransferRegularFile(local_file_path, remote_dest_file_path, callback); |
- return; |
- } |
- |
- // Otherwise, copy the document on the server side and add the new copy |
- // to the destination directory (collection). |
- CopyDocumentToDirectory( |
- remote_dest_file_path.DirName(), |
- *resource_id, |
- // Drop the document extension, which should not be |
- // in the document title. |
- remote_dest_file_path.BaseName().RemoveExtension().value(), |
- callback); |
-} |
- |
-void GDataFileSystem::TransferRegularFile( |
- const FilePath& local_file_path, |
- const FilePath& remote_dest_file_path, |
- const FileOperationCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- DriveFileError* error = |
- new DriveFileError(DRIVE_FILE_OK); |
- int64* file_size = new int64; |
- std::string* content_type = new std::string; |
- util::PostBlockingPoolSequencedTaskAndReply( |
- FROM_HERE, |
- blocking_task_runner_, |
- base::Bind(&GetLocalFileInfoOnBlockingPool, |
- local_file_path, |
- error, |
- file_size, |
- content_type), |
- base::Bind(&GDataFileSystem::StartFileUploadOnUIThread, |
- ui_weak_ptr_, |
- StartFileUploadParams(local_file_path, |
- remote_dest_file_path, |
- callback), |
- base::Owned(error), |
- base::Owned(file_size), |
- base::Owned(content_type))); |
-} |
- |
-void GDataFileSystem::StartFileUploadOnUIThread( |
- const StartFileUploadParams& params, |
- DriveFileError* error, |
- int64* file_size, |
- std::string* content_type) { |
- // This method needs to run on the UI thread as required by |
- // GDataUploader::UploadNewFile(). |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(error); |
- DCHECK(file_size); |
- DCHECK(content_type); |
- |
- if (*error != DRIVE_FILE_OK) { |
- if (!params.callback.is_null()) |
- params.callback.Run(*error); |
- |
- return; |
- } |
- |
- // Make sure the destination directory exists. |
- resource_metadata_->GetEntryInfoByPath( |
- params.remote_file_path.DirName(), |
- base::Bind( |
- &GDataFileSystem::StartFileUploadOnUIThreadAfterGetEntryInfo, |
- ui_weak_ptr_, |
- params, |
- *file_size, |
- *content_type)); |
-} |
- |
-void GDataFileSystem::StartFileUploadOnUIThreadAfterGetEntryInfo( |
- const StartFileUploadParams& params, |
- int64 file_size, |
- std::string content_type, |
- DriveFileError error, |
- scoped_ptr<DriveEntryProto> entry_proto) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- if (entry_proto.get() && !entry_proto->file_info().is_directory()) |
- error = DRIVE_FILE_ERROR_NOT_A_DIRECTORY; |
- |
- if (error != DRIVE_FILE_OK) { |
- if (!params.callback.is_null()) |
- params.callback.Run(error); |
- return; |
- } |
- DCHECK(entry_proto.get()); |
- |
- // Fill in values of UploadFileInfo. |
- scoped_ptr<UploadFileInfo> upload_file_info(new UploadFileInfo); |
- upload_file_info->file_path = params.local_file_path; |
- upload_file_info->file_size = file_size; |
- upload_file_info->gdata_path = params.remote_file_path; |
- // Use the file name as the title. |
- upload_file_info->title = params.remote_file_path.BaseName().value(); |
- upload_file_info->content_length = file_size; |
- upload_file_info->all_bytes_present = true; |
- upload_file_info->content_type = content_type; |
- upload_file_info->initial_upload_location = GURL(entry_proto->upload_url()); |
- |
- upload_file_info->completion_callback = |
- base::Bind(&GDataFileSystem::OnTransferCompleted, |
- ui_weak_ptr_, |
- params.callback); |
- |
- uploader_->UploadNewFile(upload_file_info.Pass()); |
-} |
- |
-void GDataFileSystem::OnTransferCompleted( |
- const FileOperationCallback& callback, |
- DriveFileError error, |
- scoped_ptr<UploadFileInfo> upload_file_info) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(upload_file_info.get()); |
- |
- if (error == DRIVE_FILE_OK && upload_file_info->entry.get()) { |
- AddUploadedFile(UPLOAD_NEW_FILE, |
- upload_file_info->gdata_path.DirName(), |
- upload_file_info->entry.Pass(), |
- upload_file_info->file_path, |
- DriveCache::FILE_OPERATION_COPY, |
- base::Bind(&OnAddUploadFileCompleted, callback, error)); |
- } else if (!callback.is_null()) { |
- callback.Run(error); |
- } |
-} |
- |
-void GDataFileSystem::Copy(const FilePath& src_file_path, |
- const FilePath& dest_file_path, |
- const FileOperationCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
- BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- DCHECK(!callback.is_null()); |
- |
- RunTaskOnUIThread(base::Bind(&GDataFileSystem::CopyOnUIThread, |
- ui_weak_ptr_, |
- src_file_path, |
- dest_file_path, |
- CreateRelayCallback(callback))); |
-} |
- |
-void GDataFileSystem::CopyOnUIThread(const FilePath& src_file_path, |
- const FilePath& dest_file_path, |
- const FileOperationCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- resource_metadata_->GetEntryInfoPairByPaths( |
- src_file_path, |
- dest_file_path.DirName(), |
- base::Bind(&GDataFileSystem::CopyOnUIThreadAfterGetEntryInfoPair, |
- ui_weak_ptr_, |
- dest_file_path, |
- callback)); |
-} |
- |
-void GDataFileSystem::CopyOnUIThreadAfterGetEntryInfoPair( |
- const FilePath& dest_file_path, |
- const FileOperationCallback& callback, |
- scoped_ptr<EntryInfoPairResult> result) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- DCHECK(result.get()); |
- |
- if (result->first.error != DRIVE_FILE_OK) { |
- callback.Run(result->first.error); |
- return; |
- } else if (result->second.error != DRIVE_FILE_OK) { |
- callback.Run(result->second.error); |
- return; |
- } |
- |
- scoped_ptr<DriveEntryProto> src_file_proto = result->first.proto.Pass(); |
- scoped_ptr<DriveEntryProto> dest_parent_proto = result->second.proto.Pass(); |
- |
- if (!dest_parent_proto->file_info().is_directory()) { |
- callback.Run(DRIVE_FILE_ERROR_NOT_A_DIRECTORY); |
- return; |
- } else if (src_file_proto->file_info().is_directory()) { |
- // TODO(kochi): Implement copy for directories. In the interim, |
- // we handle recursive directory copy in the file manager. |
- // crbug.com/141596 |
- callback.Run(DRIVE_FILE_ERROR_INVALID_OPERATION); |
- return; |
- } |
- |
- if (src_file_proto->file_specific_info().is_hosted_document()) { |
- CopyDocumentToDirectory(dest_file_path.DirName(), |
- src_file_proto->resource_id(), |
- // Drop the document extension, which should not be |
- // in the document title. |
- dest_file_path.BaseName().RemoveExtension().value(), |
- callback); |
- return; |
- } |
- |
- // TODO(kochi): Reimplement this once the server API supports |
- // copying of regular files directly on the server side. crbug.com/138273 |
- const FilePath& src_file_path = result->first.path; |
- GetFileByPath(src_file_path, |
- base::Bind(&GDataFileSystem::OnGetFileCompleteForCopy, |
- ui_weak_ptr_, |
- dest_file_path, |
- callback), |
- GetContentCallback()); |
-} |
- |
-void GDataFileSystem::OnGetFileCompleteForCopy( |
- const FilePath& remote_dest_file_path, |
- const FileOperationCallback& callback, |
- DriveFileError error, |
- const FilePath& local_file_path, |
- const std::string& unused_mime_type, |
- DriveFileType file_type) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- if (error != DRIVE_FILE_OK) { |
- callback.Run(error); |
- return; |
- } |
- |
- // This callback is only triggered for a regular file via Copy(). |
- DCHECK_EQ(REGULAR_FILE, file_type); |
- TransferRegularFile(local_file_path, remote_dest_file_path, callback); |
-} |
- |
-void GDataFileSystem::OnGetFileCompleteForTransferFile( |
- const FilePath& local_dest_file_path, |
- const FileOperationCallback& callback, |
- DriveFileError error, |
- const FilePath& local_file_path, |
- const std::string& unused_mime_type, |
- DriveFileType file_type) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- if (error != DRIVE_FILE_OK) { |
- callback.Run(error); |
- return; |
- } |
- |
- // GetFileByPath downloads the file from gdata to a local cache, which is then |
- // copied to the actual destination path on the local file system using |
- // CopyLocalFileOnBlockingPool. |
- DriveFileError* copy_file_error = |
- new DriveFileError(DRIVE_FILE_OK); |
- util::PostBlockingPoolSequencedTaskAndReply( |
- FROM_HERE, |
- blocking_task_runner_, |
- base::Bind(&CopyLocalFileOnBlockingPool, |
- local_file_path, |
- local_dest_file_path, |
- copy_file_error), |
- base::Bind(&RunFileOperationCallbackHelper, |
- callback, |
- base::Owned(copy_file_error))); |
-} |
- |
-void GDataFileSystem::CopyDocumentToDirectory( |
- const FilePath& dir_path, |
- const std::string& resource_id, |
- const FilePath::StringType& new_name, |
- const FileOperationCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- drive_service_->CopyDocument(resource_id, new_name, |
- base::Bind(&GDataFileSystem::OnCopyDocumentCompleted, |
- ui_weak_ptr_, |
- dir_path, |
- callback)); |
-} |
- |
-void GDataFileSystem::Rename(const FilePath& file_path, |
- const FilePath::StringType& new_name, |
- const FileMoveCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- // It is a no-op if the file is renamed to the same name. |
- if (file_path.BaseName().value() == new_name) { |
- callback.Run(DRIVE_FILE_OK, file_path); |
- return; |
- } |
- |
- // Get the edit URL of an entry at |file_path|. |
- resource_metadata_->GetEntryInfoByPath( |
- file_path, |
- base::Bind( |
- &GDataFileSystem::RenameAfterGetEntryInfo, |
- ui_weak_ptr_, |
- file_path, |
- new_name, |
- callback)); |
-} |
- |
-void GDataFileSystem::RenameAfterGetEntryInfo( |
- const FilePath& file_path, |
- const FilePath::StringType& new_name, |
- const FileMoveCallback& callback, |
- DriveFileError error, |
- scoped_ptr<DriveEntryProto> entry_proto) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- if (error != DRIVE_FILE_OK) { |
- if (!callback.is_null()) |
- callback.Run(error, file_path); |
- return; |
- } |
- DCHECK(entry_proto.get()); |
- |
- // Drop the .g<something> extension from |new_name| if the file being |
- // renamed is a hosted document and |new_name| has the same .g<something> |
- // extension as the file. |
- FilePath::StringType file_name = new_name; |
- if (entry_proto->has_file_specific_info() && |
- entry_proto->file_specific_info().is_hosted_document()) { |
- FilePath new_file(file_name); |
- if (new_file.Extension() == |
- entry_proto->file_specific_info().document_extension()) { |
- file_name = new_file.RemoveExtension().value(); |
- } |
- } |
- |
- drive_service_->RenameResource( |
- GURL(entry_proto->edit_url()), |
- file_name, |
- base::Bind(&GDataFileSystem::RenameEntryLocally, |
- ui_weak_ptr_, |
- file_path, |
- file_name, |
- callback)); |
-} |
- |
-void GDataFileSystem::Move(const FilePath& src_file_path, |
- const FilePath& dest_file_path, |
- const FileOperationCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
- BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- DCHECK(!callback.is_null()); |
- |
- RunTaskOnUIThread(base::Bind(&GDataFileSystem::MoveOnUIThread, |
- ui_weak_ptr_, |
- src_file_path, |
- dest_file_path, |
- CreateRelayCallback(callback))); |
-} |
- |
-void GDataFileSystem::MoveOnUIThread(const FilePath& src_file_path, |
- const FilePath& dest_file_path, |
- const FileOperationCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- resource_metadata_->GetEntryInfoPairByPaths( |
- src_file_path, |
- dest_file_path.DirName(), |
- base::Bind(&GDataFileSystem::MoveOnUIThreadAfterGetEntryInfoPair, |
- ui_weak_ptr_, |
- dest_file_path, |
- callback)); |
-} |
- |
-void GDataFileSystem::MoveOnUIThreadAfterGetEntryInfoPair( |
- const FilePath& dest_file_path, |
- const FileOperationCallback& callback, |
- scoped_ptr<EntryInfoPairResult> result) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- DCHECK(result.get()); |
- |
- if (result->first.error != DRIVE_FILE_OK) { |
- callback.Run(result->first.error); |
- return; |
- } else if (result->second.error != DRIVE_FILE_OK) { |
- callback.Run(result->second.error); |
- return; |
- } |
- |
- scoped_ptr<DriveEntryProto> dest_parent_proto = result->second.proto.Pass(); |
- if (!dest_parent_proto->file_info().is_directory()) { |
- callback.Run(DRIVE_FILE_ERROR_NOT_A_DIRECTORY); |
- return; |
- } |
- |
- // If the file/directory is moved to the same directory, just rename it. |
- const FilePath& src_file_path = result->first.path; |
- const FilePath& dest_parent_path = result->second.path; |
- if (src_file_path.DirName() == dest_parent_path) { |
- FileMoveCallback final_file_path_update_callback = |
- base::Bind(&GDataFileSystem::OnFilePathUpdated, |
- ui_weak_ptr_, |
- callback); |
- |
- Rename(src_file_path, dest_file_path.BaseName().value(), |
- final_file_path_update_callback); |
- return; |
- } |
- |
- // Otherwise, the move operation involves three steps: |
- // 1. Renames the file at |src_file_path| to basename(|dest_file_path|) |
- // within the same directory. The rename operation is a no-op if |
- // basename(|src_file_path|) equals to basename(|dest_file_path|). |
- // 2. Removes the file from its parent directory (the file is not deleted), |
- // which effectively moves the file to the root directory. |
- // 3. Adds the file to the parent directory of |dest_file_path|, which |
- // effectively moves the file from the root directory to the parent |
- // directory of |dest_file_path|. |
- const FileMoveCallback add_file_to_directory_callback = |
- base::Bind(&GDataFileSystem::MoveEntryFromRootDirectory, |
- ui_weak_ptr_, |
- dest_file_path.DirName(), |
- callback); |
- |
- const FileMoveCallback remove_file_from_directory_callback = |
- base::Bind(&GDataFileSystem::RemoveEntryFromNonRootDirectory, |
- ui_weak_ptr_, |
- add_file_to_directory_callback); |
- |
- Rename(src_file_path, dest_file_path.BaseName().value(), |
- remove_file_from_directory_callback); |
-} |
- |
-void GDataFileSystem::MoveEntryFromRootDirectory( |
- const FilePath& dir_path, |
- const FileOperationCallback& callback, |
- DriveFileError error, |
- const FilePath& file_path) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- DCHECK_EQ(kDriveRootDirectory, file_path.DirName().value()); |
- |
- // Return if there is an error or |dir_path| is the root directory. |
- if (error != DRIVE_FILE_OK || dir_path == FilePath(kDriveRootDirectory)) { |
- callback.Run(error); |
- return; |
- } |
- |
- resource_metadata_->GetEntryInfoPairByPaths( |
- file_path, |
- dir_path, |
- base::Bind( |
- &GDataFileSystem::MoveEntryFromRootDirectoryAfterGetEntryInfoPair, |
- ui_weak_ptr_, |
- callback)); |
-} |
- |
-void GDataFileSystem::MoveEntryFromRootDirectoryAfterGetEntryInfoPair( |
- const FileOperationCallback& callback, |
- scoped_ptr<EntryInfoPairResult> result) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- DCHECK(result.get()); |
- |
- if (result->first.error != DRIVE_FILE_OK) { |
- callback.Run(result->first.error); |
- return; |
- } else if (result->second.error != DRIVE_FILE_OK) { |
- callback.Run(result->second.error); |
- return; |
- } |
- |
- scoped_ptr<DriveEntryProto> src_proto = result->first.proto.Pass(); |
- scoped_ptr<DriveEntryProto> dir_proto = result->second.proto.Pass(); |
- |
- if (!dir_proto->file_info().is_directory()) { |
- callback.Run(DRIVE_FILE_ERROR_NOT_A_DIRECTORY); |
- return; |
- } |
- |
- const FilePath& file_path = result->first.path; |
- const FilePath& dir_path = result->second.path; |
- drive_service_->AddResourceToDirectory( |
- GURL(dir_proto->content_url()), |
- GURL(src_proto->edit_url()), |
- base::Bind(&GDataFileSystem::OnMoveEntryFromRootDirectoryCompleted, |
- ui_weak_ptr_, |
- callback, |
- file_path, |
- dir_path)); |
-} |
- |
-void GDataFileSystem::RemoveEntryFromNonRootDirectory( |
- const FileMoveCallback& callback, |
- DriveFileError error, |
- const FilePath& file_path) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- const FilePath dir_path = file_path.DirName(); |
- // Return if there is an error or |dir_path| is the root directory. |
- if (error != DRIVE_FILE_OK || dir_path == FilePath(kDriveRootDirectory)) { |
- callback.Run(error, file_path); |
- return; |
- } |
- |
- resource_metadata_->GetEntryInfoPairByPaths( |
- file_path, |
- dir_path, |
- base::Bind( |
- &GDataFileSystem::RemoveEntryFromNonRootDirectoryAfterEntryInfoPair, |
- ui_weak_ptr_, |
- callback)); |
-} |
- |
-void GDataFileSystem::RemoveEntryFromNonRootDirectoryAfterEntryInfoPair( |
- const FileMoveCallback& callback, |
- scoped_ptr<EntryInfoPairResult> result) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- DCHECK(result.get()); |
- |
- const FilePath& file_path = result->first.path; |
- const FilePath& dir_path = result->second.path; |
- if (result->first.error != DRIVE_FILE_OK) { |
- callback.Run(result->first.error, file_path); |
- return; |
- } else if (result->second.error != DRIVE_FILE_OK) { |
- callback.Run(result->second.error, file_path); |
- return; |
- } |
- |
- scoped_ptr<DriveEntryProto> entry_proto = result->first.proto.Pass(); |
- scoped_ptr<DriveEntryProto> dir_proto = result->second.proto.Pass(); |
- |
- if (!dir_proto->file_info().is_directory()) { |
- callback.Run(DRIVE_FILE_ERROR_NOT_A_DIRECTORY, file_path); |
- return; |
- } |
- |
- drive_service_->RemoveResourceFromDirectory( |
- GURL(dir_proto->content_url()), |
- GURL(entry_proto->edit_url()), |
- entry_proto->resource_id(), |
- base::Bind(&GDataFileSystem::MoveEntryToRootDirectoryLocally, |
- ui_weak_ptr_, |
- callback, |
- file_path, |
- dir_path)); |
-} |
- |
-void GDataFileSystem::Remove(const FilePath& file_path, |
- bool is_recursive, |
- const FileOperationCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
- BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- RunTaskOnUIThread(base::Bind(&GDataFileSystem::RemoveOnUIThread, |
- ui_weak_ptr_, |
- file_path, |
- is_recursive, |
- CreateRelayCallback(callback))); |
-} |
- |
-void GDataFileSystem::RemoveOnUIThread( |
- const FilePath& file_path, |
- bool is_recursive, |
- const FileOperationCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- // Get the edit URL of an entry at |file_path|. |
- resource_metadata_->GetEntryInfoByPath( |
- file_path, |
- base::Bind( |
- &GDataFileSystem::RemoveOnUIThreadAfterGetEntryInfo, |
- ui_weak_ptr_, |
- file_path, |
- is_recursive, |
- callback)); |
-} |
- |
-void GDataFileSystem::RemoveOnUIThreadAfterGetEntryInfo( |
- const FilePath& file_path, |
- bool /* is_recursive */, |
- const FileOperationCallback& callback, |
- DriveFileError error, |
- scoped_ptr<DriveEntryProto> entry_proto) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- if (error != DRIVE_FILE_OK) { |
- if (!callback.is_null()) { |
- base::MessageLoopProxy::current()->PostTask( |
- FROM_HERE, base::Bind(callback, error)); |
- } |
- return; |
- } |
- |
- DCHECK(entry_proto.get()); |
- drive_service_->DeleteDocument( |
- GURL(entry_proto->edit_url()), |
- base::Bind(&GDataFileSystem::OnRemovedDocument, |
- ui_weak_ptr_, |
- callback, |
- file_path)); |
-} |
- |
-void GDataFileSystem::CreateDirectory( |
- const FilePath& directory_path, |
- bool is_exclusive, |
- bool is_recursive, |
- const FileOperationCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
- BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- RunTaskOnUIThread(base::Bind(&GDataFileSystem::CreateDirectoryOnUIThread, |
- ui_weak_ptr_, |
- directory_path, |
- is_exclusive, |
- is_recursive, |
- CreateRelayCallback(callback))); |
-} |
- |
-void GDataFileSystem::CreateDirectoryOnUIThread( |
- const FilePath& directory_path, |
- bool is_exclusive, |
- bool is_recursive, |
- const FileOperationCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- FilePath last_parent_dir_path; |
- FilePath first_missing_path; |
- GURL last_parent_dir_url; |
- FindMissingDirectoryResult result = |
- FindFirstMissingParentDirectory(directory_path, |
- &last_parent_dir_url, |
- &first_missing_path); |
- switch (result) { |
- case FOUND_INVALID: { |
- if (!callback.is_null()) { |
- MessageLoop::current()->PostTask(FROM_HERE, |
- base::Bind(callback, DRIVE_FILE_ERROR_NOT_FOUND)); |
- } |
- |
- return; |
- } |
- case DIRECTORY_ALREADY_PRESENT: { |
- if (!callback.is_null()) { |
- MessageLoop::current()->PostTask(FROM_HERE, |
- base::Bind(callback, |
- is_exclusive ? DRIVE_FILE_ERROR_EXISTS : |
- DRIVE_FILE_OK)); |
- } |
- |
- return; |
- } |
- case FOUND_MISSING: { |
- // There is a missing folder to be created here, move on with the rest of |
- // this function. |
- break; |
- } |
- default: { |
- NOTREACHED(); |
- break; |
- } |
- } |
- |
- // Do we have a parent directory here as well? We can't then create target |
- // directory if this is not a recursive operation. |
- if (directory_path != first_missing_path && !is_recursive) { |
- if (!callback.is_null()) { |
- MessageLoop::current()->PostTask(FROM_HERE, |
- base::Bind(callback, DRIVE_FILE_ERROR_NOT_FOUND)); |
- } |
- return; |
- } |
- |
- drive_service_->CreateDirectory( |
- last_parent_dir_url, |
- first_missing_path.BaseName().value(), |
- base::Bind(&GDataFileSystem::OnCreateDirectoryCompleted, |
- ui_weak_ptr_, |
- CreateDirectoryParams( |
- first_missing_path, |
- directory_path, |
- is_exclusive, |
- is_recursive, |
- callback))); |
-} |
- |
-void GDataFileSystem::CreateFile(const FilePath& file_path, |
- bool is_exclusive, |
- const FileOperationCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
- BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- DCHECK(!callback.is_null()); |
- |
- RunTaskOnUIThread(base::Bind(&GDataFileSystem::CreateFileOnUIThread, |
- ui_weak_ptr_, |
- file_path, |
- is_exclusive, |
- CreateRelayCallback(callback))); |
-} |
- |
-void GDataFileSystem::CreateFileOnUIThread( |
- const FilePath& file_path, |
- bool is_exclusive, |
- const FileOperationCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- // First, checks the existence of a file at |file_path|. |
- resource_metadata_->GetEntryInfoByPath( |
- file_path, |
- base::Bind(&GDataFileSystem::OnGetEntryInfoForCreateFile, |
- ui_weak_ptr_, |
- file_path, |
- is_exclusive, |
- callback)); |
-} |
- |
-void GDataFileSystem::OnGetEntryInfoForCreateFile( |
- const FilePath& file_path, |
- bool is_exclusive, |
- const FileOperationCallback& callback, |
- DriveFileError result, |
- scoped_ptr<DriveEntryProto> entry_proto) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- // The |file_path| is invalid. It is an error. |
- if (result != DRIVE_FILE_ERROR_NOT_FOUND && |
- result != DRIVE_FILE_OK) { |
- callback.Run(result); |
- return; |
- } |
- |
- // An entry already exists at |file_path|. |
- if (result == DRIVE_FILE_OK) { |
- DCHECK(entry_proto.get()); |
- // If an exclusive mode is requested, or the entry is not a regular file, |
- // it is an error. |
- if (is_exclusive || |
- entry_proto->file_info().is_directory() || |
- entry_proto->file_specific_info().is_hosted_document()) { |
- callback.Run(DRIVE_FILE_ERROR_EXISTS); |
- return; |
- } |
- |
- // Otherwise nothing more to do. Succeeded. |
- callback.Run(DRIVE_FILE_OK); |
- return; |
- } |
- |
- // No entry found at |file_path|. Let's create a brand new file. |
- // For now, it is implemented by uploading an empty file (/dev/null). |
- // TODO(kinaba): http://crbug.com/135143. Implement in a nicer way. |
- TransferRegularFile(FilePath(kEmptyFilePath), file_path, callback); |
-} |
- |
-void GDataFileSystem::GetFileByPath( |
- const FilePath& file_path, |
- const GetFileCallback& get_file_callback, |
- const GetContentCallback& get_content_callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
- BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- RunTaskOnUIThread( |
- base::Bind(&GDataFileSystem::GetFileByPathOnUIThread, |
- ui_weak_ptr_, |
- file_path, |
- CreateRelayCallback(get_file_callback), |
- CreateRelayCallback(get_content_callback))); |
-} |
- |
-void GDataFileSystem::GetFileByPathOnUIThread( |
- const FilePath& file_path, |
- const GetFileCallback& get_file_callback, |
- const GetContentCallback& get_content_callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- resource_metadata_->GetEntryInfoByPath( |
- file_path, |
- base::Bind(&GDataFileSystem::OnGetEntryInfoCompleteForGetFileByPath, |
- ui_weak_ptr_, |
- file_path, |
- CreateRelayCallback(get_file_callback), |
- CreateRelayCallback(get_content_callback))); |
-} |
- |
-void GDataFileSystem::OnGetEntryInfoCompleteForGetFileByPath( |
- const FilePath& file_path, |
- const GetFileCallback& get_file_callback, |
- const GetContentCallback& get_content_callback, |
- DriveFileError error, |
- scoped_ptr<DriveEntryProto> entry_proto) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- // If |error| == PLATFORM_FILE_OK then |entry_proto| must be valid. |
- DCHECK(error != DRIVE_FILE_OK || |
- (entry_proto.get() && !entry_proto->resource_id().empty())); |
- GetResolvedFileByPath(file_path, |
- get_file_callback, |
- get_content_callback, |
- error, |
- entry_proto.get()); |
-} |
- |
-void GDataFileSystem::GetResolvedFileByPath( |
- const FilePath& file_path, |
- const GetFileCallback& get_file_callback, |
- const GetContentCallback& get_content_callback, |
- DriveFileError error, |
- const DriveEntryProto* entry_proto) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- if (entry_proto && !entry_proto->has_file_specific_info()) |
- error = DRIVE_FILE_ERROR_NOT_FOUND; |
- |
- if (error != DRIVE_FILE_OK) { |
- if (!get_file_callback.is_null()) { |
- MessageLoop::current()->PostTask( |
- FROM_HERE, |
- base::Bind(get_file_callback, |
- DRIVE_FILE_ERROR_NOT_FOUND, |
- FilePath(), |
- std::string(), |
- REGULAR_FILE)); |
- } |
- return; |
- } |
- |
- // For a hosted document, we create a special JSON file to represent the |
- // document instead of fetching the document content in one of the exported |
- // formats. The JSON file contains the edit URL and resource ID of the |
- // document. |
- if (entry_proto->file_specific_info().is_hosted_document()) { |
- DriveFileError* error = |
- new DriveFileError(DRIVE_FILE_OK); |
- FilePath* temp_file_path = new FilePath; |
- std::string* mime_type = new std::string; |
- DriveFileType* file_type = new DriveFileType(REGULAR_FILE); |
- util::PostBlockingPoolSequencedTaskAndReply( |
- FROM_HERE, |
- blocking_task_runner_, |
- base::Bind(&CreateDocumentJsonFileOnBlockingPool, |
- cache_->GetCacheDirectoryPath( |
- DriveCache::CACHE_TYPE_TMP_DOCUMENTS), |
- GURL(entry_proto->file_specific_info().alternate_url()), |
- entry_proto->resource_id(), |
- error, |
- temp_file_path, |
- mime_type, |
- file_type), |
- base::Bind(&RunGetFileCallbackHelper, |
- get_file_callback, |
- base::Owned(error), |
- base::Owned(temp_file_path), |
- base::Owned(mime_type), |
- base::Owned(file_type))); |
- return; |
- } |
- |
- // Returns absolute path of the file if it were cached or to be cached. |
- FilePath local_tmp_path = cache_->GetCacheFilePath( |
- entry_proto->resource_id(), |
- entry_proto->file_specific_info().file_md5(), |
- DriveCache::CACHE_TYPE_TMP, |
- DriveCache::CACHED_FILE_FROM_SERVER); |
- cache_->GetFileOnUIThread( |
- entry_proto->resource_id(), |
- entry_proto->file_specific_info().file_md5(), |
- base::Bind( |
- &GDataFileSystem::OnGetFileFromCache, |
- ui_weak_ptr_, |
- GetFileFromCacheParams( |
- file_path, |
- local_tmp_path, |
- GURL(entry_proto->content_url()), |
- entry_proto->resource_id(), |
- entry_proto->file_specific_info().file_md5(), |
- entry_proto->file_specific_info().content_mime_type(), |
- get_file_callback, |
- get_content_callback))); |
-} |
- |
-void GDataFileSystem::GetFileByResourceId( |
- const std::string& resource_id, |
- const GetFileCallback& get_file_callback, |
- const GetContentCallback& get_content_callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
- BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- RunTaskOnUIThread( |
- base::Bind(&GDataFileSystem::GetFileByResourceIdOnUIThread, |
- ui_weak_ptr_, |
- resource_id, |
- CreateRelayCallback(get_file_callback), |
- CreateRelayCallback(get_content_callback))); |
-} |
- |
-void GDataFileSystem::GetFileByResourceIdOnUIThread( |
- const std::string& resource_id, |
- const GetFileCallback& get_file_callback, |
- const GetContentCallback& get_content_callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- resource_metadata_->GetEntryByResourceIdAsync(resource_id, |
- base::Bind(&GDataFileSystem::GetFileByEntryOnUIThread, |
- ui_weak_ptr_, |
- get_file_callback, |
- get_content_callback)); |
-} |
- |
-void GDataFileSystem::GetFileByEntryOnUIThread( |
- const GetFileCallback& get_file_callback, |
- const GetContentCallback& get_content_callback, |
- DriveEntry* entry) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- FilePath file_path; |
- if (entry) { |
- DriveFile* file = entry->AsDriveFile(); |
- if (file) |
- file_path = file->GetFilePath(); |
- } |
- |
- // Report an error immediately if the file for the resource ID is not |
- // found. |
- if (file_path.empty()) { |
- if (!get_file_callback.is_null()) { |
- base::MessageLoopProxy::current()->PostTask( |
- FROM_HERE, |
- base::Bind(get_file_callback, |
- DRIVE_FILE_ERROR_NOT_FOUND, |
- FilePath(), |
- std::string(), |
- REGULAR_FILE)); |
- } |
- return; |
- } |
- |
- GetFileByPath(file_path, get_file_callback, get_content_callback); |
-} |
- |
-void GDataFileSystem::OnGetFileFromCache(const GetFileFromCacheParams& params, |
- DriveFileError error, |
- const std::string& resource_id, |
- const std::string& md5, |
- const FilePath& cache_file_path) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- // Have we found the file in cache? If so, return it back to the caller. |
- if (error == DRIVE_FILE_OK) { |
- if (!params.get_file_callback.is_null()) { |
- params.get_file_callback.Run(error, |
- cache_file_path, |
- params.mime_type, |
- REGULAR_FILE); |
- } |
- return; |
- } |
- |
- // If cache file is not found, try to download the file from the server |
- // instead. This logic is rather complicated but here's how this works: |
- // |
- // Retrieve fresh file metadata from server. We will extract file size and |
- // content url from there (we want to make sure used content url is not |
- // stale). |
- // |
- // Check if we have enough space, based on the expected file size. |
- // - if we don't have enough space, try to free up the disk space |
- // - if we still don't have enough space, return "no space" error |
- // - if we have enough space, start downloading the file from the server |
- drive_service_->GetDocumentEntry( |
- resource_id, |
- base::Bind(&GDataFileSystem::OnGetDocumentEntry, |
- ui_weak_ptr_, |
- cache_file_path, |
- GetFileFromCacheParams(params.virtual_file_path, |
- params.local_tmp_path, |
- params.content_url, |
- params.resource_id, |
- params.md5, |
- params.mime_type, |
- params.get_file_callback, |
- params.get_content_callback))); |
-} |
- |
-void GDataFileSystem::OnGetDocumentEntry(const FilePath& cache_file_path, |
- const GetFileFromCacheParams& params, |
- GDataErrorCode status, |
- scoped_ptr<base::Value> data) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- DriveFileError error = util::GDataToDriveFileError(status); |
- |
- scoped_ptr<DriveEntry> fresh_entry; |
- if (error == DRIVE_FILE_OK) { |
- scoped_ptr<DocumentEntry> doc_entry(DocumentEntry::ExtractAndParse(*data)); |
- if (doc_entry.get()) |
- fresh_entry.reset(resource_metadata_->FromDocumentEntry(*doc_entry)); |
- if (!fresh_entry.get() || !fresh_entry->AsDriveFile()) { |
- LOG(ERROR) << "Got invalid entry from server for " << params.resource_id; |
- error = DRIVE_FILE_ERROR_FAILED; |
- } |
- } |
- |
- if (error != DRIVE_FILE_OK) { |
- if (!params.get_file_callback.is_null()) { |
- params.get_file_callback.Run(error, |
- cache_file_path, |
- params.mime_type, |
- REGULAR_FILE); |
- } |
- return; |
- } |
- |
- GURL content_url = fresh_entry->content_url(); |
- int64 file_size = fresh_entry->file_info().size; |
- |
- DCHECK_EQ(params.resource_id, fresh_entry->resource_id()); |
- scoped_ptr<DriveFile> fresh_entry_as_file( |
- fresh_entry.release()->AsDriveFile()); |
- resource_metadata_->RefreshFile(fresh_entry_as_file.Pass()); |
- |
- bool* has_enough_space = new bool(false); |
- util::PostBlockingPoolSequencedTaskAndReply( |
- FROM_HERE, |
- blocking_task_runner_, |
- base::Bind(&DriveCache::FreeDiskSpaceIfNeededFor, |
- base::Unretained(cache_), |
- file_size, |
- has_enough_space), |
- base::Bind(&GDataFileSystem::StartDownloadFileIfEnoughSpace, |
- ui_weak_ptr_, |
- params, |
- content_url, |
- cache_file_path, |
- base::Owned(has_enough_space))); |
-} |
- |
-void GDataFileSystem::StartDownloadFileIfEnoughSpace( |
- const GetFileFromCacheParams& params, |
- const GURL& content_url, |
- const FilePath& cache_file_path, |
- bool* has_enough_space) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- if (!*has_enough_space) { |
- // If no enough space, return PLATFORM_FILE_ERROR_NO_SPACE. |
- if (!params.get_file_callback.is_null()) { |
- params.get_file_callback.Run(DRIVE_FILE_ERROR_NO_SPACE, |
- cache_file_path, |
- params.mime_type, |
- REGULAR_FILE); |
- } |
- return; |
- } |
- |
- // We have enough disk space. Start downloading the file. |
- drive_service_->DownloadFile( |
- params.virtual_file_path, |
- params.local_tmp_path, |
- content_url, |
- base::Bind(&GDataFileSystem::OnFileDownloaded, |
- ui_weak_ptr_, |
- params), |
- params.get_content_callback); |
-} |
- |
-void GDataFileSystem::GetEntryInfoByPath(const FilePath& file_path, |
- const GetEntryInfoCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
- BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- DCHECK(!callback.is_null()); |
- |
- RunTaskOnUIThread( |
- base::Bind(&GDataFileSystem::GetEntryInfoByPathOnUIThread, |
- ui_weak_ptr_, |
- file_path, |
- CreateRelayCallback(callback))); |
-} |
- |
-void GDataFileSystem::GetEntryInfoByPathOnUIThread( |
- const FilePath& file_path, |
- const GetEntryInfoCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- LoadFeedIfNeeded( |
- base::Bind(&GDataFileSystem::GetEntryInfoByPathOnUIThreadAfterLoad, |
- ui_weak_ptr_, |
- file_path, |
- callback)); |
-} |
- |
-void GDataFileSystem::GetEntryInfoByPathOnUIThreadAfterLoad( |
- const FilePath& file_path, |
- const GetEntryInfoCallback& callback, |
- DriveFileError error) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- if (error != DRIVE_FILE_OK) { |
- callback.Run(error, scoped_ptr<DriveEntryProto>()); |
- return; |
- } |
- |
- resource_metadata_->GetEntryInfoByPath( |
- file_path, |
- base::Bind(&GDataFileSystem::GetEntryInfoByPathOnUIThreadAfterGetEntry, |
- ui_weak_ptr_, |
- callback)); |
-} |
- |
-void GDataFileSystem::GetEntryInfoByPathOnUIThreadAfterGetEntry( |
- const GetEntryInfoCallback& callback, |
- DriveFileError error, |
- scoped_ptr<DriveEntryProto> entry_proto) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- if (error != DRIVE_FILE_OK) { |
- callback.Run(error, scoped_ptr<DriveEntryProto>()); |
- return; |
- } |
- DCHECK(entry_proto.get()); |
- |
- CheckLocalModificationAndRun(entry_proto.Pass(), callback); |
-} |
- |
-void GDataFileSystem::ReadDirectoryByPath( |
- const FilePath& file_path, |
- const ReadDirectoryWithSettingCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
- BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- DCHECK(!callback.is_null()); |
- |
- RunTaskOnUIThread( |
- base::Bind(&GDataFileSystem::ReadDirectoryByPathOnUIThread, |
- ui_weak_ptr_, |
- file_path, |
- CreateRelayCallback(callback))); |
-} |
- |
-void GDataFileSystem::ReadDirectoryByPathOnUIThread( |
- const FilePath& file_path, |
- const ReadDirectoryWithSettingCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- LoadFeedIfNeeded( |
- base::Bind(&GDataFileSystem::ReadDirectoryByPathOnUIThreadAfterLoad, |
- ui_weak_ptr_, |
- file_path, |
- callback)); |
-} |
- |
-void GDataFileSystem::ReadDirectoryByPathOnUIThreadAfterLoad( |
- const FilePath& file_path, |
- const ReadDirectoryWithSettingCallback& callback, |
- DriveFileError error) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- if (error != DRIVE_FILE_OK) { |
- callback.Run(error, |
- hide_hosted_docs_, |
- scoped_ptr<DriveEntryProtoVector>()); |
- return; |
- } |
- |
- resource_metadata_->ReadDirectoryByPath( |
- file_path, |
- base::Bind(&GDataFileSystem::ReadDirectoryByPathOnUIThreadAfterRead, |
- ui_weak_ptr_, |
- callback)); |
-} |
- |
-void GDataFileSystem::ReadDirectoryByPathOnUIThreadAfterRead( |
- const ReadDirectoryWithSettingCallback& callback, |
- DriveFileError error, |
- scoped_ptr<DriveEntryProtoVector> entries) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- if (error != DRIVE_FILE_OK) { |
- callback.Run(error, |
- hide_hosted_docs_, |
- scoped_ptr<DriveEntryProtoVector>()); |
- return; |
- } |
- DCHECK(entries.get()); // This is valid for emptry directories too. |
- |
- callback.Run(DRIVE_FILE_OK, hide_hosted_docs_, entries.Pass()); |
-} |
- |
-void GDataFileSystem::RequestDirectoryRefresh(const FilePath& file_path) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
- BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- RunTaskOnUIThread( |
- base::Bind(&GDataFileSystem::RequestDirectoryRefreshOnUIThread, |
- ui_weak_ptr_, |
- file_path)); |
-} |
- |
-void GDataFileSystem::RequestDirectoryRefreshOnUIThread( |
- const FilePath& file_path) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- // Make sure the destination directory exists. |
- resource_metadata_->GetEntryInfoByPath( |
- file_path, |
- base::Bind( |
- &GDataFileSystem::RequestDirectoryRefreshOnUIThreadAfterGetEntryInfo, |
- ui_weak_ptr_, |
- file_path)); |
-} |
- |
-void GDataFileSystem::RequestDirectoryRefreshOnUIThreadAfterGetEntryInfo( |
- const FilePath& file_path, |
- DriveFileError error, |
- scoped_ptr<DriveEntryProto> entry_proto) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- if (error != DRIVE_FILE_OK || |
- !entry_proto->file_info().is_directory()) { |
- LOG(ERROR) << "Directory entry not found: " << file_path.value(); |
- return; |
- } |
- |
- feed_loader_->LoadDirectoryFromServer( |
- resource_metadata_->origin(), |
- entry_proto->resource_id(), |
- base::Bind(&GDataFileSystem::OnRequestDirectoryRefresh, |
- ui_weak_ptr_, |
- file_path)); |
-} |
- |
-void GDataFileSystem::OnRequestDirectoryRefresh( |
- const FilePath& directory_path, |
- GetDocumentsParams* params, |
- DriveFileError error) { |
- DCHECK(params); |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- if (error != DRIVE_FILE_OK) { |
- LOG(ERROR) << "Failed to refresh directory: " << directory_path.value() |
- << ": " << error; |
- return; |
- } |
- |
- int64 unused_delta_feed_changestamp = 0; |
- FeedToFileResourceMapUmaStats unused_uma_stats; |
- FileResourceIdMap file_map; |
- GDataWapiFeedProcessor feed_processor(resource_metadata_.get()); |
- error = feed_processor.FeedToFileResourceMap( |
- *params->feed_list, |
- &file_map, |
- &unused_delta_feed_changestamp, |
- &unused_uma_stats); |
- if (error != DRIVE_FILE_OK) { |
- LOG(ERROR) << "Failed to convert feed: " << directory_path.value() |
- << ": " << error; |
- return; |
- } |
- |
- resource_metadata_->RefreshDirectory( |
- params->directory_resource_id, |
- file_map, |
- base::Bind(&GDataFileSystem::OnDirectoryChangeFileMoveCallback, |
- ui_weak_ptr_)); |
-} |
- |
-void GDataFileSystem::UpdateFileByResourceId( |
- const std::string& resource_id, |
- const FileOperationCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
- BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- DCHECK(!callback.is_null()); |
- |
- RunTaskOnUIThread( |
- base::Bind(&GDataFileSystem::UpdateFileByResourceIdOnUIThread, |
- ui_weak_ptr_, |
- resource_id, |
- CreateRelayCallback(callback))); |
-} |
- |
-void GDataFileSystem::UpdateFileByResourceIdOnUIThread( |
- const std::string& resource_id, |
- const FileOperationCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- // TODO(satorux): GetEntryInfoByResourceId() is called twice for |
- // UpdateFileByResourceIdOnUIThread(). crbug.com/143873 |
- resource_metadata_->GetEntryInfoByResourceId( |
- resource_id, |
- base::Bind(&GDataFileSystem::UpdateFileByEntryInfo, |
- ui_weak_ptr_, |
- callback)); |
-} |
- |
-void GDataFileSystem::UpdateFileByEntryInfo( |
- const FileOperationCallback& callback, |
- DriveFileError error, |
- const FilePath& /* dive_file_path */, |
- scoped_ptr<DriveEntryProto> entry_proto) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- if (error != DRIVE_FILE_OK) { |
- callback.Run(error); |
- return; |
- } |
- |
- DCHECK(entry_proto.get()); |
- if (entry_proto->file_info().is_directory()) { |
- callback.Run(DRIVE_FILE_ERROR_NOT_FOUND); |
- return; |
- } |
- |
- cache_->GetFileOnUIThread( |
- entry_proto->resource_id(), |
- entry_proto->file_specific_info().file_md5(), |
- base::Bind(&GDataFileSystem::OnGetFileCompleteForUpdateFile, |
- ui_weak_ptr_, |
- callback)); |
-} |
- |
-void GDataFileSystem::OnGetFileCompleteForUpdateFile( |
- const FileOperationCallback& callback, |
- DriveFileError error, |
- const std::string& resource_id, |
- const std::string& /* md5 */, |
- const FilePath& cache_file_path) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- if (error != DRIVE_FILE_OK) { |
- callback.Run(error); |
- return; |
- } |
- |
- // Gets the size of the cache file. Since the file is locally modified, the |
- // file size information stored in DriveEntry is not correct. |
- DriveFileError* get_size_error = new DriveFileError(DRIVE_FILE_ERROR_FAILED); |
- int64* file_size = new int64(-1); |
- util::PostBlockingPoolSequencedTaskAndReply( |
- FROM_HERE, |
- blocking_task_runner_, |
- base::Bind(&GetLocalFileSizeOnBlockingPool, |
- cache_file_path, |
- get_size_error, |
- file_size), |
- base::Bind(&GDataFileSystem::OnGetFileSizeCompleteForUpdateFile, |
- ui_weak_ptr_, |
- callback, |
- resource_id, |
- cache_file_path, |
- base::Owned(get_size_error), |
- base::Owned(file_size))); |
-} |
- |
-void GDataFileSystem::OnGetFileSizeCompleteForUpdateFile( |
- const FileOperationCallback& callback, |
- const std::string& resource_id, |
- const FilePath& cache_file_path, |
- DriveFileError* error, |
- int64* file_size) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- if (*error != DRIVE_FILE_OK) { |
- callback.Run(*error); |
- return; |
- } |
- |
- // TODO(satorux): GetEntryInfoByResourceId() is called twice for |
- // UpdateFileByResourceIdOnUIThread(). crbug.com/143873 |
- resource_metadata_->GetEntryInfoByResourceId( |
- resource_id, |
- base::Bind(&GDataFileSystem::OnGetFileCompleteForUpdateFileByEntry, |
- ui_weak_ptr_, |
- callback, |
- *file_size, |
- cache_file_path)); |
-} |
- |
-void GDataFileSystem::OnGetFileCompleteForUpdateFileByEntry( |
- const FileOperationCallback& callback, |
- int64 file_size, |
- const FilePath& cache_file_path, |
- DriveFileError error, |
- const FilePath& drive_file_path, |
- scoped_ptr<DriveEntryProto> entry_proto) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- if (error != DRIVE_FILE_OK) { |
- callback.Run(error); |
- return; |
- } |
- |
- DCHECK(entry_proto.get()); |
- if (entry_proto->file_info().is_directory()) { |
- callback.Run(DRIVE_FILE_ERROR_NOT_FOUND); |
- return; |
- } |
- |
- uploader_->UploadExistingFile( |
- GURL(entry_proto->upload_url()), |
- drive_file_path, |
- cache_file_path, |
- file_size, |
- entry_proto->file_specific_info().content_mime_type(), |
- base::Bind(&GDataFileSystem::OnUpdatedFileUploaded, |
- ui_weak_ptr_, |
- callback)); |
-} |
- |
-void GDataFileSystem::OnUpdatedFileUploaded( |
- const FileOperationCallback& callback, |
- DriveFileError error, |
- scoped_ptr<UploadFileInfo> upload_file_info) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(upload_file_info.get()); |
- |
- if (error != DRIVE_FILE_OK) { |
- if (!callback.is_null()) |
- callback.Run(error); |
- return; |
- } |
- |
- AddUploadedFile(UPLOAD_EXISTING_FILE, |
- upload_file_info->gdata_path.DirName(), |
- upload_file_info->entry.Pass(), |
- upload_file_info->file_path, |
- DriveCache::FILE_OPERATION_MOVE, |
- base::Bind(&OnAddUploadFileCompleted, callback, error)); |
-} |
- |
-void GDataFileSystem::GetAvailableSpace( |
- const GetAvailableSpaceCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
- BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- RunTaskOnUIThread(base::Bind(&GDataFileSystem::GetAvailableSpaceOnUIThread, |
- ui_weak_ptr_, |
- CreateRelayCallback(callback))); |
-} |
- |
-void GDataFileSystem::GetAvailableSpaceOnUIThread( |
- const GetAvailableSpaceCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- drive_service_->GetAccountMetadata( |
- gdata::util::IsDriveV2ApiEnabled() ? |
- base::Bind(&GDataFileSystem::OnGetAboutResource, |
- ui_weak_ptr_, |
- callback) : |
- base::Bind(&GDataFileSystem::OnGetAvailableSpace, |
- ui_weak_ptr_, |
- callback)); |
-} |
- |
-void GDataFileSystem::OnGetAvailableSpace( |
- const GetAvailableSpaceCallback& callback, |
- GDataErrorCode status, |
- scoped_ptr<base::Value> data) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- DriveFileError error = util::GDataToDriveFileError(status); |
- if (error != DRIVE_FILE_OK) { |
- callback.Run(error, -1, -1); |
- return; |
- } |
- |
- scoped_ptr<AccountMetadataFeed> feed; |
- if (data.get()) |
- feed = AccountMetadataFeed::CreateFrom(*data); |
- if (!feed.get()) { |
- callback.Run(DRIVE_FILE_ERROR_FAILED, -1, -1); |
- return; |
- } |
- |
- callback.Run(DRIVE_FILE_OK, |
- feed->quota_bytes_total(), |
- feed->quota_bytes_used()); |
-} |
- |
-void GDataFileSystem::OnGetAboutResource( |
- const GetAvailableSpaceCallback& callback, |
- GDataErrorCode status, |
- scoped_ptr<base::Value> resource_json) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- DriveFileError error = util::GDataToDriveFileError(status); |
- if (error != DRIVE_FILE_OK) { |
- callback.Run(error, -1, -1); |
- return; |
- } |
- |
- scoped_ptr<AboutResource> about; |
- if (resource_json.get()) |
- about = AboutResource::CreateFrom(*resource_json); |
- |
- if (!about.get()) { |
- callback.Run(DRIVE_FILE_ERROR_FAILED, -1, -1); |
- return; |
- } |
- |
- callback.Run(DRIVE_FILE_OK, |
- about->quota_bytes_total(), |
- about->quota_bytes_used()); |
-} |
- |
-void GDataFileSystem::OnCreateDirectoryCompleted( |
- const CreateDirectoryParams& params, |
- GDataErrorCode status, |
- scoped_ptr<base::Value> data) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- DriveFileError error = util::GDataToDriveFileError(status); |
- if (error != DRIVE_FILE_OK) { |
- if (!params.callback.is_null()) |
- params.callback.Run(error); |
- |
- return; |
- } |
- |
- base::DictionaryValue* dict_value = NULL; |
- base::Value* created_entry = NULL; |
- if (data.get() && data->GetAsDictionary(&dict_value) && dict_value) |
- dict_value->Get("entry", &created_entry); |
- error = AddNewDirectory(params.created_directory_path.DirName(), |
- created_entry); |
- |
- if (error != DRIVE_FILE_OK) { |
- if (!params.callback.is_null()) |
- params.callback.Run(error); |
- |
- return; |
- } |
- |
- // Not done yet with recursive directory creation? |
- if (params.target_directory_path != params.created_directory_path && |
- params.is_recursive) { |
- CreateDirectory(params.target_directory_path, |
- params.is_exclusive, |
- params.is_recursive, |
- params.callback); |
- return; |
- } |
- |
- if (!params.callback.is_null()) { |
- // Finally done with the create request. |
- params.callback.Run(DRIVE_FILE_OK); |
- } |
-} |
- |
-void GDataFileSystem::OnSearch(const SearchCallback& callback, |
- GetDocumentsParams* params, |
- DriveFileError error) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- if (error != DRIVE_FILE_OK) { |
- if (!callback.is_null()) |
- callback.Run(error, GURL(), scoped_ptr<std::vector<SearchResultInfo> >()); |
- return; |
- } |
- |
- // The search results will be returned using virtual directory. |
- // The directory is not really part of the file system, so it has no parent or |
- // root. |
- std::vector<SearchResultInfo>* results(new std::vector<SearchResultInfo>()); |
- |
- DCHECK_EQ(1u, params->feed_list->size()); |
- DocumentFeed* feed = params->feed_list->at(0); |
- |
- // TODO(tbarzic): Limit total number of returned results for the query. |
- GURL next_feed; |
- feed->GetNextFeedURL(&next_feed); |
- |
- if (feed->entries().empty()) { |
- scoped_ptr<std::vector<SearchResultInfo> > result_vec(results); |
- if (!callback.is_null()) |
- callback.Run(error, next_feed, result_vec.Pass()); |
- return; |
- } |
- |
- // Go through all entires generated by the feed and add them to the search |
- // result directory. |
- for (size_t i = 0; i < feed->entries().size(); ++i) { |
- DocumentEntry* doc = const_cast<DocumentEntry*>(feed->entries()[i]); |
- scoped_ptr<DriveEntry> entry(resource_metadata_->FromDocumentEntry(*doc)); |
- |
- if (!entry.get()) |
- continue; |
- |
- DCHECK_EQ(doc->resource_id(), entry->resource_id()); |
- DCHECK(!entry->is_deleted()); |
- |
- std::string entry_resource_id = entry->resource_id(); |
- |
- // This will do nothing if the entry is not already present in file system. |
- if (entry->AsDriveFile()) { |
- scoped_ptr<DriveFile> entry_as_file(entry.release()->AsDriveFile()); |
- resource_metadata_->RefreshFile(entry_as_file.Pass()); |
- // We shouldn't use entry object after this point. |
- DCHECK(!entry.get()); |
- } |
- |
- // We will need information about result entry to create info for callback. |
- // We can't use |entry| anymore, so we have to refetch entry from file |
- // system. Also, |entry| doesn't have file path set before |RefreshFile| |
- // call, so we can't get file path from there. |
- resource_metadata_->GetEntryByResourceIdAsync(entry_resource_id, |
- base::Bind(&AddEntryToSearchResults, |
- results, |
- callback, |
- base::Bind(&GDataFileSystem::CheckForUpdates, ui_weak_ptr_), |
- error, |
- i+1 == feed->entries().size(), |
- next_feed)); |
- } |
-} |
- |
-void GDataFileSystem::Search(const std::string& search_query, |
- const GURL& next_feed, |
- const SearchCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
- BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- RunTaskOnUIThread(base::Bind(&GDataFileSystem::SearchAsyncOnUIThread, |
- ui_weak_ptr_, |
- search_query, |
- next_feed, |
- CreateRelayCallback(callback))); |
-} |
- |
-void GDataFileSystem::SearchAsyncOnUIThread( |
- const std::string& search_query, |
- const GURL& next_feed, |
- const SearchCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- feed_loader_->SearchFromServer( |
- resource_metadata_->origin(), |
- search_query, |
- next_feed, |
- base::Bind(&GDataFileSystem::OnSearch, ui_weak_ptr_, callback)); |
-} |
- |
-void GDataFileSystem::OnDirectoryChanged(const FilePath& directory_path) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- FOR_EACH_OBSERVER(GDataFileSystemInterface::Observer, observers_, |
- OnDirectoryChanged(directory_path)); |
-} |
- |
-void GDataFileSystem::OnDocumentFeedFetched(int num_accumulated_entries) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- FOR_EACH_OBSERVER(GDataFileSystemInterface::Observer, observers_, |
- OnDocumentFeedFetched(num_accumulated_entries)); |
-} |
- |
-void GDataFileSystem::OnFeedFromServerLoaded() { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- FOR_EACH_OBSERVER(GDataFileSystemInterface::Observer, observers_, |
- OnFeedFromServerLoaded()); |
-} |
- |
-void GDataFileSystem::LoadRootFeedFromCacheForTesting() { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- feed_loader_->LoadFromCache( |
- false, // should_load_from_server. |
- FileOperationCallback()); |
-} |
- |
-DriveFileError GDataFileSystem::UpdateFromFeedForTesting( |
- const std::vector<DocumentFeed*>& feed_list, |
- int64 start_changestamp, |
- int64 root_feed_changestamp) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- return feed_loader_->UpdateFromFeed(feed_list, |
- start_changestamp, |
- root_feed_changestamp); |
-} |
- |
-void GDataFileSystem::OnFilePathUpdated(const FileOperationCallback& callback, |
- DriveFileError error, |
- const FilePath& /* file_path */) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- if (!callback.is_null()) |
- callback.Run(error); |
-} |
- |
-void GDataFileSystem::OnCopyDocumentCompleted( |
- const FilePath& dir_path, |
- const FileOperationCallback& callback, |
- GDataErrorCode status, |
- scoped_ptr<base::Value> data) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- DriveFileError error = util::GDataToDriveFileError(status); |
- if (error != DRIVE_FILE_OK) { |
- callback.Run(error); |
- return; |
- } |
- |
- scoped_ptr<DocumentEntry> doc_entry(DocumentEntry::ExtractAndParse(*data)); |
- if (!doc_entry.get()) { |
- callback.Run(DRIVE_FILE_ERROR_FAILED); |
- return; |
- } |
- |
- DriveEntry* entry = resource_metadata_->FromDocumentEntry(*doc_entry); |
- if (!entry) { |
- callback.Run(DRIVE_FILE_ERROR_FAILED); |
- return; |
- } |
- |
- // |entry| was added in the root directory on the server, so we should |
- // first add it to |root_| to mirror the state and then move it to the |
- // destination directory by MoveEntryFromRootDirectory(). |
- resource_metadata_->AddEntryToDirectory( |
- resource_metadata_->root(), |
- entry, |
- base::Bind(&GDataFileSystem::MoveEntryFromRootDirectory, |
- ui_weak_ptr_, |
- dir_path, |
- callback)); |
-} |
- |
-void GDataFileSystem::OnMoveEntryFromRootDirectoryCompleted( |
- const FileOperationCallback& callback, |
- const FilePath& file_path, |
- const FilePath& dir_path, |
- GDataErrorCode status, |
- const GURL& document_url) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- DriveFileError error = util::GDataToDriveFileError(status); |
- if (error == DRIVE_FILE_OK) { |
- DriveEntry* entry = resource_metadata_->FindEntryByPathSync(file_path); |
- if (entry) { |
- DCHECK_EQ(resource_metadata_->root(), entry->parent()); |
- resource_metadata_->MoveEntryToDirectory( |
- dir_path, |
- entry, |
- base::Bind( |
- &GDataFileSystem::NotifyAndRunFileOperationCallback, |
- ui_weak_ptr_, |
- callback)); |
- return; |
- } else { |
- error = DRIVE_FILE_ERROR_NOT_FOUND; |
- } |
- } |
- |
- callback.Run(error); |
-} |
- |
-void GDataFileSystem::OnRemovedDocument( |
- const FileOperationCallback& callback, |
- const FilePath& file_path, |
- GDataErrorCode status, |
- const GURL& document_url) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- DriveFileError error = util::GDataToDriveFileError(status); |
- |
- if (error == DRIVE_FILE_OK) |
- error = RemoveEntryAndCacheLocally(file_path); |
- |
- if (!callback.is_null()) { |
- callback.Run(error); |
- } |
-} |
- |
-void GDataFileSystem::OnFileDownloaded( |
- const GetFileFromCacheParams& params, |
- GDataErrorCode status, |
- const GURL& content_url, |
- const FilePath& downloaded_file_path) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- // If user cancels download of a pinned-but-not-fetched file, mark file as |
- // unpinned so that we do not sync the file again. |
- if (status == GDATA_CANCELLED) { |
- cache_->GetCacheEntryOnUIThread( |
- params.resource_id, |
- params.md5, |
- base::Bind(&GDataFileSystem::UnpinIfPinned, |
- ui_weak_ptr_, |
- params.resource_id, |
- params.md5)); |
- } |
- |
- // At this point, the disk can be full or nearly full for several reasons: |
- // - The expected file size was incorrect and the file was larger |
- // - There was an in-flight download operation and it used up space |
- // - The disk became full for some user actions we cannot control |
- // (ex. the user might have downloaded a large file from a regular web site) |
- // |
- // If we don't have enough space, we return PLATFORM_FILE_ERROR_NO_SPACE, |
- // and try to free up space, even if the file was downloaded successfully. |
- bool* has_enough_space = new bool(false); |
- util::PostBlockingPoolSequencedTaskAndReply( |
- FROM_HERE, |
- blocking_task_runner_, |
- base::Bind(&DriveCache::FreeDiskSpaceIfNeededFor, |
- base::Unretained(cache_), |
- 0, |
- has_enough_space), |
- base::Bind(&GDataFileSystem::OnFileDownloadedAndSpaceChecked, |
- ui_weak_ptr_, |
- params, |
- status, |
- content_url, |
- downloaded_file_path, |
- base::Owned(has_enough_space))); |
-} |
- |
-void GDataFileSystem::UnpinIfPinned( |
- const std::string& resource_id, |
- const std::string& md5, |
- bool success, |
- const DriveCacheEntry& cache_entry) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- // TODO(hshi): http://crbug.com/127138 notify when file properties change. |
- // This allows file manager to clear the "Available offline" checkbox. |
- if (success && cache_entry.is_pinned()) |
- cache_->UnpinOnUIThread(resource_id, md5, CacheOperationCallback()); |
-} |
- |
-void GDataFileSystem::OnFileDownloadedAndSpaceChecked( |
- const GetFileFromCacheParams& params, |
- GDataErrorCode status, |
- const GURL& content_url, |
- const FilePath& downloaded_file_path, |
- bool* has_enough_space) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- DriveFileError error = util::GDataToDriveFileError(status); |
- |
- // Make sure that downloaded file is properly stored in cache. We don't have |
- // to wait for this operation to finish since the user can already use the |
- // downloaded file. |
- if (error == DRIVE_FILE_OK) { |
- if (*has_enough_space) { |
- cache_->StoreOnUIThread( |
- params.resource_id, |
- params.md5, |
- downloaded_file_path, |
- DriveCache::FILE_OPERATION_MOVE, |
- base::Bind(&GDataFileSystem::OnDownloadStoredToCache, |
- ui_weak_ptr_)); |
- } else { |
- // If we don't have enough space, remove the downloaded file, and |
- // report "no space" error. |
- util::PostBlockingPoolSequencedTask( |
- FROM_HERE, |
- blocking_task_runner_, |
- base::Bind(base::IgnoreResult(&file_util::Delete), |
- downloaded_file_path, |
- false /* recursive*/)); |
- error = DRIVE_FILE_ERROR_NO_SPACE; |
- } |
- } |
- |
- if (!params.get_file_callback.is_null()) { |
- params.get_file_callback.Run(error, |
- downloaded_file_path, |
- params.mime_type, |
- REGULAR_FILE); |
- } |
-} |
- |
-void GDataFileSystem::OnDownloadStoredToCache(DriveFileError error, |
- const std::string& resource_id, |
- const std::string& md5) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- // Nothing much to do here for now. |
-} |
- |
-void GDataFileSystem::RenameEntryLocally( |
- const FilePath& file_path, |
- const FilePath::StringType& new_name, |
- const FileMoveCallback& callback, |
- GDataErrorCode status, |
- const GURL& document_url) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- const DriveFileError error = util::GDataToDriveFileError(status); |
- if (error != DRIVE_FILE_OK) { |
- if (!callback.is_null()) |
- callback.Run(error, FilePath()); |
- return; |
- } |
- |
- DriveEntry* entry = resource_metadata_->FindEntryByPathSync(file_path); |
- if (!entry) { |
- if (!callback.is_null()) |
- callback.Run(DRIVE_FILE_ERROR_NOT_FOUND, FilePath()); |
- return; |
- } |
- |
- DCHECK(entry->parent()); |
- entry->set_title(new_name); |
- // After changing the title of the entry, call MoveEntryToDirectory() to |
- // remove the entry from its parent directory and then add it back in order to |
- // go through the file name de-duplication. |
- // TODO(achuith/satorux/zel): This code is fragile. The title has been |
- // changed, but not the file_name. MoveEntryToDirectory calls RemoveChild to |
- // remove the child based on the old file_name, and then re-adds the child by |
- // first assigning the new title to file_name. http://crbug.com/30157 |
- resource_metadata_->MoveEntryToDirectory( |
- entry->parent()->GetFilePath(), |
- entry, |
- base::Bind(&GDataFileSystem::NotifyAndRunFileMoveCallback, |
- ui_weak_ptr_, |
- callback)); |
-} |
- |
-void GDataFileSystem::MoveEntryToRootDirectoryLocally( |
- const FileMoveCallback& callback, |
- const FilePath& file_path, |
- const FilePath& dir_path, |
- GDataErrorCode status, |
- const GURL& document_url) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- const DriveFileError error = util::GDataToDriveFileError(status); |
- if (error != DRIVE_FILE_OK) { |
- callback.Run(error, FilePath()); |
- return; |
- } |
- |
- DriveEntry* entry = resource_metadata_->FindEntryByPathSync(file_path); |
- if (!entry) { |
- callback.Run(DRIVE_FILE_ERROR_NOT_FOUND, FilePath()); |
- return; |
- } |
- |
- resource_metadata_->MoveEntryToDirectory( |
- resource_metadata_->root()->GetFilePath(), |
- entry, |
- base::Bind(&GDataFileSystem::NotifyAndRunFileMoveCallback, |
- ui_weak_ptr_, |
- callback)); |
-} |
- |
-void GDataFileSystem::NotifyAndRunFileMoveCallback( |
- const FileMoveCallback& callback, |
- DriveFileError error, |
- const FilePath& moved_file_path) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- if (error == DRIVE_FILE_OK) |
- OnDirectoryChanged(moved_file_path.DirName()); |
- |
- if (!callback.is_null()) |
- callback.Run(error, moved_file_path); |
-} |
- |
-void GDataFileSystem::NotifyAndRunFileOperationCallback( |
- const FileOperationCallback& callback, |
- DriveFileError error, |
- const FilePath& moved_file_path) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- if (error == DRIVE_FILE_OK) |
- OnDirectoryChanged(moved_file_path.DirName()); |
- |
- callback.Run(error); |
-} |
- |
-void GDataFileSystem::OnDirectoryChangeFileMoveCallback( |
- DriveFileError error, |
- const FilePath& directory_path) { |
- if (error == DRIVE_FILE_OK) |
- OnDirectoryChanged(directory_path); |
-} |
- |
-DriveFileError GDataFileSystem::RemoveEntryAndCacheLocally( |
- const FilePath& file_path) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- std::string resource_id; |
- DriveFileError error = RemoveEntryLocally(file_path, &resource_id); |
- if (error != DRIVE_FILE_OK) |
- return error; |
- |
- // If resource_id is not empty, remove its corresponding file from cache. |
- if (!resource_id.empty()) |
- cache_->RemoveOnUIThread(resource_id, CacheOperationCallback()); |
- |
- return DRIVE_FILE_OK; |
-} |
- |
-void GDataFileSystem::RemoveStaleEntryOnUpload( |
- const std::string& resource_id, |
- DriveDirectory* parent_dir, |
- const FileMoveCallback& callback, |
- DriveEntry* existing_entry) { |
- if (existing_entry && |
- // This should always match, but just in case. |
- existing_entry->parent() == parent_dir) { |
- resource_metadata_->RemoveEntryFromParent(existing_entry, callback); |
- } else { |
- callback.Run(DRIVE_FILE_ERROR_NOT_FOUND, FilePath()); |
- LOG(ERROR) << "Entry for the existing file not found: " << resource_id; |
- } |
-} |
- |
-void GDataFileSystem::NotifyFileSystemMounted() { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- DVLOG(1) << "File System is mounted"; |
- // Notify the observers that the file system is mounted. |
- FOR_EACH_OBSERVER(GDataFileSystemInterface::Observer, observers_, |
- OnFileSystemMounted()); |
-} |
- |
-void GDataFileSystem::NotifyFileSystemToBeUnmounted() { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- DVLOG(1) << "File System is to be unmounted"; |
- // Notify the observers that the file system is being unmounted. |
- FOR_EACH_OBSERVER(GDataFileSystemInterface::Observer, observers_, |
- OnFileSystemBeingUnmounted()); |
-} |
- |
-void GDataFileSystem::NotifyInitialLoadFinishedAndRun( |
- const FileOperationCallback& callback, |
- DriveFileError error) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- // Notify the observers that root directory has been initialized. |
- FOR_EACH_OBSERVER(GDataFileSystemInterface::Observer, observers_, |
- OnInitialLoadFinished()); |
- |
- callback.Run(error); |
-} |
- |
-DriveFileError GDataFileSystem::AddNewDirectory( |
- const FilePath& directory_path, base::Value* entry_value) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- if (!entry_value) |
- return DRIVE_FILE_ERROR_FAILED; |
- |
- scoped_ptr<DocumentEntry> doc_entry(DocumentEntry::CreateFrom(*entry_value)); |
- |
- if (!doc_entry.get()) |
- return DRIVE_FILE_ERROR_FAILED; |
- |
- // Find parent directory element within the cached file system snapshot. |
- DriveEntry* entry = resource_metadata_->FindEntryByPathSync(directory_path); |
- if (!entry) |
- return DRIVE_FILE_ERROR_FAILED; |
- |
- // Check if parent is a directory since in theory since this is a callback |
- // something could in the meantime have nuked the parent dir and created a |
- // file with the exact same name. |
- DriveDirectory* parent_dir = entry->AsDriveDirectory(); |
- if (!parent_dir) |
- return DRIVE_FILE_ERROR_FAILED; |
- |
- DriveEntry* new_entry = |
- resource_metadata_->FromDocumentEntry(*doc_entry); |
- if (!new_entry) |
- return DRIVE_FILE_ERROR_FAILED; |
- |
- resource_metadata_->AddEntryToDirectory( |
- parent_dir, |
- new_entry, |
- base::Bind(&GDataFileSystem::NotifyAndRunFileMoveCallback, |
- ui_weak_ptr_, |
- FileMoveCallback())); |
- return DRIVE_FILE_OK; |
-} |
- |
-GDataFileSystem::FindMissingDirectoryResult |
-GDataFileSystem::FindFirstMissingParentDirectory( |
- const FilePath& directory_path, |
- GURL* last_dir_content_url, |
- FilePath* first_missing_parent_path) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- // Let's find which how deep is the existing directory structure and |
- // get the first element that's missing. |
- std::vector<FilePath::StringType> path_parts; |
- directory_path.GetComponents(&path_parts); |
- FilePath current_path; |
- |
- for (std::vector<FilePath::StringType>::const_iterator iter = |
- path_parts.begin(); |
- iter != path_parts.end(); ++iter) { |
- current_path = current_path.Append(*iter); |
- DriveEntry* entry = resource_metadata_->FindEntryByPathSync(current_path); |
- if (entry) { |
- if (entry->file_info().is_directory) { |
- *last_dir_content_url = entry->content_url(); |
- } else { |
- // Huh, the segment found is a file not a directory? |
- return FOUND_INVALID; |
- } |
- } else { |
- *first_missing_parent_path = current_path; |
- return FOUND_MISSING; |
- } |
- } |
- return DIRECTORY_ALREADY_PRESENT; |
-} |
- |
-DriveFileError GDataFileSystem::RemoveEntryLocally( |
- const FilePath& file_path, std::string* resource_id) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- resource_id->clear(); |
- |
- // Find directory element within the cached file system snapshot. |
- DriveEntry* entry = resource_metadata_->FindEntryByPathSync(file_path); |
- |
- if (!entry) |
- return DRIVE_FILE_ERROR_NOT_FOUND; |
- |
- // You can't remove root element. |
- if (!entry->parent()) |
- return DRIVE_FILE_ERROR_ACCESS_DENIED; |
- |
- // If it's a file (only files have resource id), get its resource id so that |
- // we can remove it after releasing the auto lock. |
- if (entry->AsDriveFile()) |
- *resource_id = entry->AsDriveFile()->resource_id(); |
- |
- resource_metadata_->RemoveEntryFromParent( |
- entry, |
- base::Bind(&GDataFileSystem::OnDirectoryChangeFileMoveCallback, |
- ui_weak_ptr_)); |
- return DRIVE_FILE_OK; |
-} |
- |
-void GDataFileSystem::AddUploadedFile( |
- UploadMode upload_mode, |
- const FilePath& virtual_dir_path, |
- scoped_ptr<DocumentEntry> entry, |
- const FilePath& file_content_path, |
- DriveCache::FileOperationType cache_operation, |
- const base::Closure& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- // Post a task to the same thread, rather than calling it here, as |
- // AddUploadedFile() is asynchronous. |
- base::MessageLoopProxy::current()->PostTask( |
- FROM_HERE, |
- base::Bind(&GDataFileSystem::AddUploadedFileOnUIThread, |
- ui_weak_ptr_, |
- upload_mode, |
- virtual_dir_path, |
- base::Passed(&entry), |
- file_content_path, |
- cache_operation, |
- callback)); |
-} |
- |
-void GDataFileSystem::AddUploadedFileOnUIThread( |
- UploadMode upload_mode, |
- const FilePath& virtual_dir_path, |
- scoped_ptr<DocumentEntry> entry, |
- const FilePath& file_content_path, |
- DriveCache::FileOperationType cache_operation, |
- const base::Closure& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- // ScopedClosureRunner ensures that the specified callback is always invoked |
- // upon return or passed on. |
- base::ScopedClosureRunner callback_runner(callback); |
- |
- if (!entry.get()) { |
- NOTREACHED(); |
- return; |
- } |
- |
- DriveEntry* dir_entry = resource_metadata_->FindEntryByPathSync( |
- virtual_dir_path); |
- if (!dir_entry) |
- return; |
- |
- DriveDirectory* parent_dir = dir_entry->AsDriveDirectory(); |
- if (!parent_dir) |
- return; |
- |
- scoped_ptr<DriveEntry> new_entry( |
- resource_metadata_->FromDocumentEntry(*entry)); |
- if (!new_entry.get()) |
- return; |
- |
- const std::string& resource_id = new_entry->resource_id(); |
- AddUploadedFileParams* params = |
- new AddUploadedFileParams(upload_mode, |
- parent_dir, |
- new_entry.Pass(), |
- file_content_path, |
- cache_operation, |
- callback_runner.Release()); |
- |
- const FileMoveCallback file_move_callback = |
- base::Bind(&GDataFileSystem::ContinueAddUploadedFile, |
- ui_weak_ptr_, params); |
- |
- if (upload_mode == UPLOAD_EXISTING_FILE) { |
- // Remove an existing entry, which should be present. |
- resource_metadata_->GetEntryByResourceIdAsync( |
- resource_id, |
- base::Bind(&GDataFileSystem::RemoveStaleEntryOnUpload, |
- ui_weak_ptr_, |
- resource_id, |
- parent_dir, |
- file_move_callback)); |
- } else { |
- file_move_callback.Run(DRIVE_FILE_OK, FilePath()); |
- } |
-} |
- |
-void GDataFileSystem::ContinueAddUploadedFile( |
- AddUploadedFileParams* params, |
- DriveFileError error, |
- const FilePath& file_path) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK_EQ(DRIVE_FILE_OK, error); |
- DCHECK(params->new_entry.get()); |
- DriveFile* file = params->new_entry->AsDriveFile(); |
- DCHECK(file); |
- |
- params->resource_id = file->resource_id(); |
- params->md5 = file->file_md5(); |
- resource_metadata_->AddEntryToDirectory( |
- params->parent_dir, |
- params->new_entry.release(), |
- base::Bind(&GDataFileSystem::NotifyAndRunFileMoveCallback, |
- ui_weak_ptr_, |
- base::Bind(&GDataFileSystem::AddUploadedFileToCache, |
- ui_weak_ptr_, |
- base::Owned(params)))); |
-} |
- |
-void GDataFileSystem::AddUploadedFileToCache( |
- AddUploadedFileParams* params, |
- DriveFileError error, |
- const FilePath& file_path) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- if (params->upload_mode == UPLOAD_NEW_FILE) { |
- // Add the file to the cache if we have uploaded a new file. |
- cache_->StoreOnUIThread(params->resource_id, |
- params->md5, |
- params->file_content_path, |
- params->cache_operation, |
- base::Bind(&OnCacheUpdatedForAddUploadedFile, |
- params->callback)); |
- } else if (params->upload_mode == UPLOAD_EXISTING_FILE) { |
- // Clear the dirty bit if we have updated an existing file. |
- cache_->ClearDirtyOnUIThread(params->resource_id, |
- params->md5, |
- base::Bind(&OnCacheUpdatedForAddUploadedFile, |
- params->callback)); |
- } else { |
- NOTREACHED() << "Unexpected upload mode: " << params->upload_mode; |
- // Shouldn't reach here, so the line below should not make much sense, but |
- // since calling |callback| exactly once is our obligation, we'd better call |
- // it for not to clutter further more. |
- params->callback.Run(); |
- } |
-} |
- |
-void GDataFileSystem::UpdateEntryData(const std::string& resource_id, |
- const std::string& md5, |
- scoped_ptr<DocumentEntry> entry, |
- const FilePath& file_content_path, |
- const base::Closure& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- // Post a task to the same thread, rather than calling it here, as |
- // UpdateEntryData() is asynchronous. |
- base::MessageLoopProxy::current()->PostTask( |
- FROM_HERE, |
- base::Bind(&GDataFileSystem::UpdateEntryDataOnUIThread, |
- ui_weak_ptr_, |
- resource_id, |
- md5, |
- base::Passed(&entry), |
- file_content_path, |
- callback)); |
-} |
- |
-void GDataFileSystem::UpdateEntryDataOnUIThread( |
- const std::string& resource_id, |
- const std::string& md5, |
- scoped_ptr<DocumentEntry> entry, |
- const FilePath& file_content_path, |
- const base::Closure& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- scoped_ptr<DriveFile> new_entry( |
- resource_metadata_->FromDocumentEntry(*entry)->AsDriveFile()); |
- if (!new_entry.get()) { |
- return; |
- } |
- |
- resource_metadata_->RefreshFile(new_entry.Pass()); |
- |
- // Add the file to the cache if we have uploaded a new file. |
- cache_->StoreOnUIThread(resource_id, |
- md5, |
- file_content_path, |
- DriveCache::FILE_OPERATION_MOVE, |
- base::Bind(&OnCacheUpdatedForAddUploadedFile, |
- callback)); |
-} |
- |
-void GDataFileSystem::Observe(int type, |
- const content::NotificationSource& source, |
- const content::NotificationDetails& details) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- if (type == chrome::NOTIFICATION_PREF_CHANGED) { |
- PrefService* pref_service = profile_->GetPrefs(); |
- std::string* pref_name = content::Details<std::string>(details).ptr(); |
- if (*pref_name == prefs::kDisableGDataHostedFiles) { |
- SetHideHostedDocuments( |
- pref_service->GetBoolean(prefs::kDisableGDataHostedFiles)); |
- } |
- } else { |
- NOTREACHED(); |
- } |
-} |
- |
-void GDataFileSystem::SetHideHostedDocuments(bool hide) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- if (hide == hide_hosted_docs_) |
- return; |
- |
- hide_hosted_docs_ = hide; |
- const FilePath root_path = resource_metadata_->root()->GetFilePath(); |
- |
- // Kick off directory refresh when this setting changes. |
- FOR_EACH_OBSERVER(GDataFileSystemInterface::Observer, observers_, |
- OnDirectoryChanged(root_path)); |
-} |
- |
-//============= GDataFileSystem: internal helper functions ===================== |
- |
-void GDataFileSystem::InitializePreferenceObserver() { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- pref_registrar_.reset(new PrefChangeRegistrar()); |
- pref_registrar_->Init(profile_->GetPrefs()); |
- pref_registrar_->Add(prefs::kDisableGDataHostedFiles, this); |
-} |
- |
-void GDataFileSystem::OpenFile(const FilePath& file_path, |
- const OpenFileCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
- BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- RunTaskOnUIThread(base::Bind(&GDataFileSystem::OpenFileOnUIThread, |
- ui_weak_ptr_, |
- file_path, |
- CreateRelayCallback(callback))); |
-} |
- |
-void GDataFileSystem::OpenFileOnUIThread(const FilePath& file_path, |
- const OpenFileCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- // If the file is already opened, it cannot be opened again before closed. |
- // This is for avoiding simultaneous modification to the file, and moreover |
- // to avoid an inconsistent cache state (suppose an operation sequence like |
- // Open->Open->modify->Close->modify->Close; the second modify may not be |
- // synchronized to the server since it is already Closed on the cache). |
- if (open_files_.find(file_path) != open_files_.end()) { |
- MessageLoop::current()->PostTask( |
- FROM_HERE, |
- base::Bind(callback, DRIVE_FILE_ERROR_IN_USE, FilePath())); |
- return; |
- } |
- open_files_.insert(file_path); |
- |
- resource_metadata_->GetEntryInfoByPath( |
- file_path, |
- base::Bind(&GDataFileSystem::OnGetEntryInfoCompleteForOpenFile, |
- ui_weak_ptr_, |
- file_path, |
- base::Bind(&GDataFileSystem::OnOpenFileFinished, |
- ui_weak_ptr_, |
- file_path, |
- callback))); |
-} |
- |
-void GDataFileSystem::OnGetEntryInfoCompleteForOpenFile( |
- const FilePath& file_path, |
- const OpenFileCallback& callback, |
- DriveFileError error, |
- scoped_ptr<DriveEntryProto> entry_proto) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- if (entry_proto.get() && !entry_proto->has_file_specific_info()) |
- error = DRIVE_FILE_ERROR_NOT_FOUND; |
- |
- if (error == DRIVE_FILE_OK) { |
- if (entry_proto->file_specific_info().file_md5().empty() || |
- entry_proto->file_specific_info().is_hosted_document()) { |
- // No support for opening a directory or hosted document. |
- error = DRIVE_FILE_ERROR_INVALID_OPERATION; |
- } |
- } |
- |
- if (error != DRIVE_FILE_OK) { |
- if (!callback.is_null()) |
- callback.Run(error, FilePath()); |
- return; |
- } |
- |
- DCHECK(!entry_proto->resource_id().empty()); |
- GetResolvedFileByPath( |
- file_path, |
- base::Bind(&GDataFileSystem::OnGetFileCompleteForOpenFile, |
- ui_weak_ptr_, |
- callback, |
- GetFileCompleteForOpenParams( |
- entry_proto->resource_id(), |
- entry_proto->file_specific_info().file_md5())), |
- GetContentCallback(), |
- error, |
- entry_proto.get()); |
-} |
- |
-void GDataFileSystem::OnGetFileCompleteForOpenFile( |
- const OpenFileCallback& callback, |
- const GetFileCompleteForOpenParams& entry_proto, |
- DriveFileError error, |
- const FilePath& file_path, |
- const std::string& mime_type, |
- DriveFileType file_type) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- if (error != DRIVE_FILE_OK) { |
- if (!callback.is_null()) |
- callback.Run(error, FilePath()); |
- return; |
- } |
- |
- // OpenFileOnUIThread ensures that the file is a regular file. |
- DCHECK_EQ(REGULAR_FILE, file_type); |
- |
- cache_->MarkDirtyOnUIThread( |
- entry_proto.resource_id, |
- entry_proto.md5, |
- base::Bind(&GDataFileSystem::OnMarkDirtyInCacheCompleteForOpenFile, |
- ui_weak_ptr_, |
- callback)); |
-} |
- |
-void GDataFileSystem::OnMarkDirtyInCacheCompleteForOpenFile( |
- const OpenFileCallback& callback, |
- DriveFileError error, |
- const std::string& resource_id, |
- const std::string& md5, |
- const FilePath& cache_file_path) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- if (!callback.is_null()) |
- callback.Run(error, cache_file_path); |
-} |
- |
-void GDataFileSystem::OnOpenFileFinished(const FilePath& file_path, |
- const OpenFileCallback& callback, |
- DriveFileError result, |
- const FilePath& cache_file_path) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- // All the invocation of |callback| from operations initiated from OpenFile |
- // must go through here. Removes the |file_path| from the remembered set when |
- // the file was not successfully opened. |
- if (result != DRIVE_FILE_OK) |
- open_files_.erase(file_path); |
- |
- if (!callback.is_null()) |
- callback.Run(result, cache_file_path); |
-} |
- |
-void GDataFileSystem::CloseFile(const FilePath& file_path, |
- const FileOperationCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
- BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- DCHECK(!callback.is_null()); |
- |
- RunTaskOnUIThread(base::Bind(&GDataFileSystem::CloseFileOnUIThread, |
- ui_weak_ptr_, |
- file_path, |
- CreateRelayCallback(callback))); |
-} |
- |
-void GDataFileSystem::CloseFileOnUIThread( |
- const FilePath& file_path, |
- const FileOperationCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- if (open_files_.find(file_path) == open_files_.end()) { |
- // The file is not being opened. |
- MessageLoop::current()->PostTask( |
- FROM_HERE, |
- base::Bind(callback, DRIVE_FILE_ERROR_NOT_FOUND)); |
- return; |
- } |
- |
- // Step 1 of CloseFile: Get resource_id and md5 for |file_path|. |
- resource_metadata_->GetEntryInfoByPath( |
- file_path, |
- base::Bind(&GDataFileSystem::CloseFileOnUIThreadAfterGetEntryInfo, |
- ui_weak_ptr_, |
- file_path, |
- base::Bind(&GDataFileSystem::CloseFileOnUIThreadFinalize, |
- ui_weak_ptr_, |
- file_path, |
- callback))); |
-} |
- |
-void GDataFileSystem::CloseFileOnUIThreadAfterGetEntryInfo( |
- const FilePath& file_path, |
- const FileOperationCallback& callback, |
- DriveFileError error, |
- scoped_ptr<DriveEntryProto> entry_proto) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- if (entry_proto.get() && !entry_proto->has_file_specific_info()) |
- error = DRIVE_FILE_ERROR_NOT_FOUND; |
- |
- if (error != DRIVE_FILE_OK) { |
- callback.Run(error); |
- return; |
- } |
- |
- // Step 2 of CloseFile: Commit the modification in cache. This will trigger |
- // background upload. |
- // TODO(benchan,kinaba): Call ClearDirtyInCache instead of CommitDirtyInCache |
- // if the file has not been modified. Come up with a way to detect the |
- // intactness effectively, or provide a method for user to declare it when |
- // calling CloseFile(). |
- cache_->CommitDirtyOnUIThread( |
- entry_proto->resource_id(), |
- entry_proto->file_specific_info().file_md5(), |
- base::Bind(&GDataFileSystem::CloseFileOnUIThreadAfterCommitDirtyInCache, |
- ui_weak_ptr_, |
- callback)); |
-} |
- |
-void GDataFileSystem::CloseFileOnUIThreadAfterCommitDirtyInCache( |
- const FileOperationCallback& callback, |
- DriveFileError error, |
- const std::string& /* resource_id */, |
- const std::string& /* md5 */) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- callback.Run(error); |
-} |
- |
-void GDataFileSystem::CloseFileOnUIThreadFinalize( |
- const FilePath& file_path, |
- const FileOperationCallback& callback, |
- DriveFileError result) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- // Step 3 of CloseFile. |
- // All the invocation of |callback| from operations initiated from CloseFile |
- // must go through here. Removes the |file_path| from the remembered set so |
- // that subsequent operations can open the file again. |
- open_files_.erase(file_path); |
- |
- // Then invokes the user-supplied callback function. |
- callback.Run(result); |
-} |
- |
-void GDataFileSystem::CheckLocalModificationAndRun( |
- scoped_ptr<DriveEntryProto> entry_proto, |
- const GetEntryInfoCallback& callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(entry_proto.get()); |
- DCHECK(!callback.is_null()); |
- |
- // For entries that will never be cached, use the original entry info as is. |
- if (!entry_proto->has_file_specific_info() || |
- entry_proto->file_specific_info().is_hosted_document()) { |
- callback.Run(DRIVE_FILE_OK, entry_proto.Pass()); |
- return; |
- } |
- |
- // Checks if the file is cached and modified locally. |
- const std::string resource_id = entry_proto->resource_id(); |
- const std::string md5 = entry_proto->file_specific_info().file_md5(); |
- cache_->GetCacheEntryOnUIThread( |
- resource_id, |
- md5, |
- base::Bind( |
- &GDataFileSystem::CheckLocalModificationAndRunAfterGetCacheEntry, |
- ui_weak_ptr_, base::Passed(&entry_proto), callback)); |
-} |
- |
-void GDataFileSystem::CheckLocalModificationAndRunAfterGetCacheEntry( |
- scoped_ptr<DriveEntryProto> entry_proto, |
- const GetEntryInfoCallback& callback, |
- bool success, |
- const DriveCacheEntry& cache_entry) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- // When no dirty cache is found, use the original entry info as is. |
- if (!success || !cache_entry.is_dirty()) { |
- callback.Run(DRIVE_FILE_OK, entry_proto.Pass()); |
- return; |
- } |
- |
- // Gets the cache file path. |
- const std::string& resource_id = entry_proto->resource_id(); |
- const std::string& md5 = entry_proto->file_specific_info().file_md5(); |
- cache_->GetFileOnUIThread( |
- resource_id, |
- md5, |
- base::Bind( |
- &GDataFileSystem::CheckLocalModificationAndRunAfterGetCacheFile, |
- ui_weak_ptr_, base::Passed(&entry_proto), callback)); |
-} |
- |
-void GDataFileSystem::CheckLocalModificationAndRunAfterGetCacheFile( |
- scoped_ptr<DriveEntryProto> entry_proto, |
- const GetEntryInfoCallback& callback, |
- DriveFileError error, |
- const std::string& resource_id, |
- const std::string& md5, |
- const FilePath& local_cache_path) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- // When no dirty cache is found, use the original entry info as is. |
- if (error != DRIVE_FILE_OK) { |
- callback.Run(DRIVE_FILE_OK, entry_proto.Pass()); |
- return; |
- } |
- |
- // If the cache is dirty, obtain the file info from the cache file itself. |
- base::PlatformFileInfo* file_info = new base::PlatformFileInfo; |
- bool* get_file_info_result = new bool(false); |
- util::PostBlockingPoolSequencedTaskAndReply( |
- FROM_HERE, |
- blocking_task_runner_, |
- base::Bind(&GetFileInfoOnBlockingPool, |
- local_cache_path, |
- base::Unretained(file_info), |
- base::Unretained(get_file_info_result)), |
- base::Bind(&GDataFileSystem::CheckLocalModificationAndRunAfterGetFileInfo, |
- ui_weak_ptr_, |
- base::Passed(&entry_proto), |
- callback, |
- base::Owned(file_info), |
- base::Owned(get_file_info_result))); |
-} |
- |
-void GDataFileSystem::CheckLocalModificationAndRunAfterGetFileInfo( |
- scoped_ptr<DriveEntryProto> entry_proto, |
- const GetEntryInfoCallback& callback, |
- base::PlatformFileInfo* file_info, |
- bool* get_file_info_result) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!callback.is_null()); |
- |
- if (!*get_file_info_result) { |
- callback.Run(DRIVE_FILE_ERROR_NOT_FOUND, scoped_ptr<DriveEntryProto>()); |
- return; |
- } |
- |
- PlatformFileInfoProto entry_file_info; |
- DriveEntry::ConvertPlatformFileInfoToProto(*file_info, &entry_file_info); |
- *entry_proto->mutable_file_info() = entry_file_info; |
- callback.Run(DRIVE_FILE_OK, entry_proto.Pass()); |
-} |
- |
-} // namespace gdata |