| 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
|
|
|