Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(990)

Unified Diff: chrome/browser/chromeos/gdata/gdata_file_system.cc

Issue 10874028: Rename GDataFileSystem* to DriveFileSystem* (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
« no previous file with comments | « chrome/browser/chromeos/gdata/gdata_file_system.h ('k') | chrome/browser/chromeos/gdata/gdata_file_system_interface.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698