blob: 31070c70fa8ccc3a330bf6fb4e67c277272ea44b [file] [log] [blame]
// 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/drive_file_system_proxy.h"
#include <string>
#include <vector>
#include "base/bind.h"
#include "base/platform_file.h"
#include "base/string_util.h"
#include "base/values.h"
#include "chrome/browser/chromeos/gdata/drive.pb.h"
#include "chrome/browser/chromeos/gdata/drive_file_system_interface.h"
#include "chrome/browser/chromeos/gdata/drive_files.h"
#include "chrome/browser/chromeos/gdata/drive_system_service.h"
#include "chrome/browser/google_apis/gdata_util.h"
#include "content/public/browser/browser_thread.h"
#include "webkit/blob/shareable_file_reference.h"
#include "webkit/fileapi/file_system_file_util_proxy.h"
#include "webkit/fileapi/file_system_types.h"
#include "webkit/fileapi/file_system_url.h"
#include "webkit/fileapi/file_system_util.h"
using base::MessageLoopProxy;
using content::BrowserThread;
using fileapi::FileSystemURL;
using fileapi::FileSystemOperation;
using webkit_blob::ShareableFileReference;
namespace gdata {
namespace {
const char kDriveRootDirectory[] = "drive";
const char kFeedField[] = "feed";
// Helper function that creates platform file on blocking IO thread pool.
void OpenPlatformFileOnIOPool(const FilePath& local_path,
int file_flags,
base::PlatformFile* platform_file,
base::PlatformFileError* open_error) {
bool created;
*platform_file = base::CreatePlatformFile(local_path,
file_flags,
&created,
open_error);
}
// Helper function to run reply on results of OpenPlatformFileOnIOPool() on
// IO thread.
void OnPlatformFileOpened(
const FileSystemOperation::OpenFileCallback& callback,
base::ProcessHandle peer_handle,
base::PlatformFile* platform_file,
base::PlatformFileError* open_error) {
callback.Run(*open_error, *platform_file, peer_handle);
}
// Helper function to run OpenFileCallback from
// DriveFileSystemProxy::OpenFile().
void OnGetFileByPathForOpen(
const FileSystemOperation::OpenFileCallback& callback,
int file_flags,
base::ProcessHandle peer_handle,
DriveFileError file_error,
const FilePath& local_path,
const std::string& unused_mime_type,
DriveFileType file_type) {
base::PlatformFileError error =
util::DriveFileErrorToPlatformError(file_error);
if (error != base::PLATFORM_FILE_OK) {
callback.Run(error, base::kInvalidPlatformFileValue, peer_handle);
return;
}
base::PlatformFile* platform_file = new base::PlatformFile(
base::kInvalidPlatformFileValue);
base::PlatformFileError* open_error =
new base::PlatformFileError(base::PLATFORM_FILE_ERROR_FAILED);
BrowserThread::GetBlockingPool()->PostTaskAndReply(FROM_HERE,
base::Bind(&OpenPlatformFileOnIOPool,
local_path,
file_flags,
platform_file,
open_error),
base::Bind(&OnPlatformFileOpened,
callback,
peer_handle,
base::Owned(platform_file),
base::Owned(open_error)));
}
// Helper function to run SnapshotFileCallback from
// DriveFileSystemProxy::CreateSnapshotFile().
void CallSnapshotFileCallback(
const FileSystemOperation::SnapshotFileCallback& callback,
const base::PlatformFileInfo& file_info,
DriveFileError file_error,
const FilePath& local_path,
const std::string& unused_mime_type,
DriveFileType file_type) {
scoped_refptr<ShareableFileReference> file_ref;
base::PlatformFileError error =
util::DriveFileErrorToPlatformError(file_error);
// If the file is a hosted document, a temporary JSON file is created to
// represent the document. The JSON file is not cached and its lifetime
// is managed by ShareableFileReference.
if (error == base::PLATFORM_FILE_OK && file_type == HOSTED_DOCUMENT) {
file_ref = ShareableFileReference::GetOrCreate(
local_path, ShareableFileReference::DELETE_ON_FINAL_RELEASE,
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
}
// When reading file, last modified time specified in file info will be
// compared to the last modified time of the local version of the drive file.
// Since those two values don't generally match (last modification time on the
// drive server vs. last modification time of the local, downloaded file), so
// we have to opt out from this check. We do this by unsetting last_modified
// value in the file info passed to the CreateSnapshot caller.
base::PlatformFileInfo final_file_info(file_info);
final_file_info.last_modified = base::Time();
callback.Run(error, final_file_info, local_path, file_ref);
}
// Emits debug log when DriveFileSystem::CloseFile() is complete.
void EmitDebugLogForCloseFile(const FilePath& local_path,
DriveFileError file_error) {
DVLOG(1) << "Closed: " << local_path.AsUTF8Unsafe() << ": " << file_error;
}
void DoTruncateOnFileThread(
const FilePath& local_cache_path,
int64 length,
base::PlatformFileError* result) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
base::PlatformFile file = base::CreatePlatformFile(
local_cache_path,
base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE,
NULL,
result);
if (*result == base::PLATFORM_FILE_OK) {
DCHECK_NE(base::kInvalidPlatformFileValue, file);
if (!base::TruncatePlatformFile(file, length))
*result = base::PLATFORM_FILE_ERROR_FAILED;
base::ClosePlatformFile(file);
}
}
void DidCloseFileForTruncate(
const FileSystemOperation::StatusCallback& callback,
base::PlatformFileError truncate_result,
DriveFileError close_result) {
// Reports the first error.
callback.Run(truncate_result == base::PLATFORM_FILE_OK ?
util::DriveFileErrorToPlatformError(close_result) :
truncate_result);
}
} // namespace
base::FileUtilProxy::Entry DriveEntryProtoToFileUtilProxyEntry(
const DriveEntryProto& proto) {
base::PlatformFileInfo file_info;
DriveEntry::ConvertProtoToPlatformFileInfo(proto.file_info(), &file_info);
base::FileUtilProxy::Entry entry;
entry.name = proto.base_name();
entry.is_directory = file_info.is_directory;
entry.size = file_info.size;
entry.last_modified_time = file_info.last_modified;
return entry;
}
// DriveFileSystemProxy class implementation.
DriveFileSystemProxy::DriveFileSystemProxy(
DriveFileSystemInterface* file_system)
: file_system_(file_system) {
// Should be created from the file browser extension API (AddMountFunction)
// on UI thread.
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
void DriveFileSystemProxy::GetFileInfo(const FileSystemURL& file_url,
const FileSystemOperation::GetMetadataCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
FilePath file_path;
if (!ValidateUrl(file_url, &file_path)) {
MessageLoopProxy::current()->PostTask(FROM_HERE,
base::Bind(callback,
base::PLATFORM_FILE_ERROR_NOT_FOUND,
base::PlatformFileInfo(),
FilePath()));
return;
}
file_system_->GetEntryInfoByPath(
file_path,
base::Bind(&DriveFileSystemProxy::OnGetMetadata,
this,
file_path,
callback));
}
void DriveFileSystemProxy::Copy(const FileSystemURL& src_file_url,
const FileSystemURL& dest_file_url,
const FileSystemOperation::StatusCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
FilePath src_file_path, dest_file_path;
if (!ValidateUrl(src_file_url, &src_file_path) ||
!ValidateUrl(dest_file_url, &dest_file_path)) {
MessageLoopProxy::current()->PostTask(FROM_HERE,
base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND));
return;
}
file_system_->Copy(
src_file_path,
dest_file_path,
base::Bind(&DriveFileSystemProxy::OnStatusCallback, this, callback));
}
void DriveFileSystemProxy::Move(const FileSystemURL& src_file_url,
const FileSystemURL& dest_file_url,
const FileSystemOperation::StatusCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
FilePath src_file_path, dest_file_path;
if (!ValidateUrl(src_file_url, &src_file_path) ||
!ValidateUrl(dest_file_url, &dest_file_path)) {
MessageLoopProxy::current()->PostTask(FROM_HERE,
base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND));
return;
}
file_system_->Move(
src_file_path,
dest_file_path,
base::Bind(&DriveFileSystemProxy::OnStatusCallback, this, callback));
}
void DriveFileSystemProxy::ReadDirectory(const FileSystemURL& file_url,
const FileSystemOperation::ReadDirectoryCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
FilePath file_path;
if (!ValidateUrl(file_url, &file_path)) {
base::MessageLoopProxy::current()->PostTask(
FROM_HERE,
base::Bind(callback,
base::PLATFORM_FILE_ERROR_NOT_FOUND,
std::vector<base::FileUtilProxy::Entry>(),
false));
return;
}
file_system_->ReadDirectoryByPath(
file_path,
base::Bind(&DriveFileSystemProxy::OnReadDirectory,
this,
callback));
}
void DriveFileSystemProxy::Remove(const FileSystemURL& file_url, bool recursive,
const FileSystemOperation::StatusCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
FilePath file_path;
if (!ValidateUrl(file_url, &file_path)) {
MessageLoopProxy::current()->PostTask(FROM_HERE,
base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND));
return;
}
file_system_->Remove(
file_path,
recursive,
base::Bind(&DriveFileSystemProxy::OnStatusCallback, this, callback));
}
void DriveFileSystemProxy::CreateDirectory(
const FileSystemURL& file_url,
bool exclusive,
bool recursive,
const FileSystemOperation::StatusCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
FilePath file_path;
if (!ValidateUrl(file_url, &file_path)) {
MessageLoopProxy::current()->PostTask(FROM_HERE,
base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND));
return;
}
file_system_->CreateDirectory(
file_path,
exclusive,
recursive,
base::Bind(&DriveFileSystemProxy::OnStatusCallback, this, callback));
}
void DriveFileSystemProxy::CreateFile(
const FileSystemURL& file_url,
bool exclusive,
const FileSystemOperation::StatusCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
FilePath file_path;
if (!ValidateUrl(file_url, &file_path)) {
MessageLoopProxy::current()->PostTask(FROM_HERE,
base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND));
return;
}
file_system_->CreateFile(
file_path,
exclusive,
base::Bind(&DriveFileSystemProxy::OnStatusCallback, this, callback));
}
void DriveFileSystemProxy::Truncate(
const FileSystemURL& file_url, int64 length,
const FileSystemOperation::StatusCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (length < 0) {
MessageLoopProxy::current()->PostTask(FROM_HERE,
base::Bind(callback, base::PLATFORM_FILE_ERROR_INVALID_OPERATION));
return;
}
FilePath file_path;
if (!ValidateUrl(file_url, &file_path)) {
MessageLoopProxy::current()->PostTask(FROM_HERE,
base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND));
return;
}
// TODO(kinaba): http://crbug.com/132780.
// Optimize the cases for small |length|, at least for |length| == 0.
// CreateWritableSnapshotFile downloads the whole content unnecessarily.
file_system_->OpenFile(
file_path,
base::Bind(&DriveFileSystemProxy::OnFileOpenedForTruncate,
this,
file_path,
length,
callback));
}
void DriveFileSystemProxy::OnOpenFileForWriting(
int file_flags,
base::ProcessHandle peer_handle,
const FileSystemOperation::OpenFileCallback& callback,
DriveFileError file_error,
const FilePath& local_cache_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
base::PlatformFileError error =
util::DriveFileErrorToPlatformError(file_error);
if (error != base::PLATFORM_FILE_OK) {
callback.Run(error, base::kInvalidPlatformFileValue, peer_handle);
return;
}
// Cache file prepared for modification is available. Truncate it.
// File operation must be done on FILE thread, so relay the operation.
base::PlatformFileError* result =
new base::PlatformFileError(base::PLATFORM_FILE_ERROR_FAILED);
base::PlatformFile* platform_file = new base::PlatformFile(
base::kInvalidPlatformFileValue);
bool posted = BrowserThread::GetBlockingPool()->PostTaskAndReply(FROM_HERE,
base::Bind(&OpenPlatformFileOnIOPool,
local_cache_path,
file_flags,
platform_file,
result),
base::Bind(&OnPlatformFileOpened,
callback,
peer_handle,
base::Owned(platform_file),
base::Owned(result)));
DCHECK(posted);
}
void DriveFileSystemProxy::OnCreateFileForOpen(
const FilePath& file_path,
int file_flags,
base::ProcessHandle peer_handle,
const FileSystemOperation::OpenFileCallback& callback,
DriveFileError file_error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
base::PlatformFileError create_result =
util::DriveFileErrorToPlatformError(file_error);
if ((create_result == base::PLATFORM_FILE_OK) ||
((create_result == base::PLATFORM_FILE_ERROR_EXISTS) &&
(file_flags & base::PLATFORM_FILE_CREATE_ALWAYS))) {
// If we are trying to always create an existing file, then
// if it really exists open it as truncated.
file_flags &= ~base::PLATFORM_FILE_CREATE;
file_flags &= ~base::PLATFORM_FILE_CREATE_ALWAYS;
file_flags |= base::PLATFORM_FILE_OPEN_TRUNCATED;
} else {
callback.Run(create_result, base::kInvalidPlatformFileValue, peer_handle);
return;
}
// Open created (or existing) file for writing.
file_system_->OpenFile(
file_path,
base::Bind(&DriveFileSystemProxy::OnOpenFileForWriting,
this,
file_flags,
peer_handle,
callback));
}
void DriveFileSystemProxy::OnFileOpenedForTruncate(
const FilePath& virtual_path,
int64 length,
const fileapi::FileSystemOperation::StatusCallback& callback,
DriveFileError open_result,
const FilePath& local_cache_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (open_result != DRIVE_FILE_OK) {
callback.Run(util::DriveFileErrorToPlatformError(open_result));
return;
}
// Cache file prepared for modification is available. Truncate it.
// File operation must be done on FILE thread, so relay the operation.
base::PlatformFileError* result =
new base::PlatformFileError(base::PLATFORM_FILE_ERROR_FAILED);
bool posted = BrowserThread::GetMessageLoopProxyForThread(
BrowserThread::FILE)->PostTaskAndReply(
FROM_HERE,
base::Bind(&DoTruncateOnFileThread,
local_cache_path,
length,
result),
base::Bind(&DriveFileSystemProxy::DidTruncate,
this,
virtual_path,
callback,
base::Owned(result)));
DCHECK(posted);
}
void DriveFileSystemProxy::DidTruncate(
const FilePath& virtual_path,
const FileSystemOperation::StatusCallback& callback,
base::PlatformFileError* truncate_result) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// Truncation finished. We must close the file no matter |truncate_result|
// indicates an error or not.
file_system_->CloseFile(
virtual_path,
base::Bind(&DidCloseFileForTruncate,
callback,
base::PlatformFileError(*truncate_result)));
}
void DriveFileSystemProxy::OpenFile(
const FileSystemURL& file_url,
int file_flags,
base::ProcessHandle peer_handle,
const FileSystemOperation::OpenFileCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
FilePath file_path;
if (!ValidateUrl(file_url, &file_path)) {
MessageLoopProxy::current()->PostTask(FROM_HERE,
base::Bind(callback,
base::PLATFORM_FILE_ERROR_NOT_FOUND,
base::kInvalidPlatformFileValue,
peer_handle));
return;
}
// TODO(zelidrag): Wire all other file open operations.
if ((file_flags & base::PLATFORM_FILE_DELETE_ON_CLOSE)) {
NOTIMPLEMENTED() << "File create/write operations not yet supported "
<< file_path.value();
MessageLoopProxy::current()->PostTask(FROM_HERE,
base::Bind(callback,
base::PLATFORM_FILE_ERROR_FAILED,
base::kInvalidPlatformFileValue,
peer_handle));
return;
}
if ((file_flags & base::PLATFORM_FILE_OPEN) ||
(file_flags & base::PLATFORM_FILE_OPEN_ALWAYS) ||
(file_flags & base::PLATFORM_FILE_OPEN_TRUNCATED)) {
if ((file_flags & base::PLATFORM_FILE_OPEN_TRUNCATED) ||
(file_flags & base::PLATFORM_FILE_OPEN_ALWAYS) ||
(file_flags & base::PLATFORM_FILE_WRITE) ||
(file_flags & base::PLATFORM_FILE_EXCLUSIVE_WRITE)) {
// Open existing file for writing.
file_system_->OpenFile(
file_path,
base::Bind(&DriveFileSystemProxy::OnOpenFileForWriting,
this,
file_flags,
peer_handle,
callback));
} else {
// Read-only file open.
file_system_->GetFileByPath(file_path,
base::Bind(&OnGetFileByPathForOpen,
callback,
file_flags,
peer_handle),
GetContentCallback());
}
} else if ((file_flags & base::PLATFORM_FILE_CREATE) ||
(file_flags & base::PLATFORM_FILE_CREATE_ALWAYS)) {
// Open existing file for writing.
file_system_->CreateFile(
file_path,
file_flags & base::PLATFORM_FILE_EXCLUSIVE_WRITE,
base::Bind(&DriveFileSystemProxy::OnCreateFileForOpen,
this,
file_path,
file_flags,
peer_handle,
callback));
} else {
NOTREACHED() << "Unhandled file flags combination " << file_flags;
MessageLoopProxy::current()->PostTask(FROM_HERE,
base::Bind(callback,
base::PLATFORM_FILE_ERROR_FAILED,
base::kInvalidPlatformFileValue,
peer_handle));
}
}
void DriveFileSystemProxy::NotifyCloseFile(const FileSystemURL& url) {
FilePath file_path;
if (!ValidateUrl(url, &file_path))
return;
file_system_->CloseFile(file_path,
base::Bind(&EmitDebugLogForCloseFile, file_path));
}
void DriveFileSystemProxy::TouchFile(
const fileapi::FileSystemURL& url,
const base::Time& last_access_time,
const base::Time& last_modified_time,
const FileSystemOperation::StatusCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// TODO(kinaba,kochi): crbug.com/144369. Support this operations once we have
// migrated to the new Drive API.
MessageLoopProxy::current()->PostTask(FROM_HERE,
base::Bind(callback, base::PLATFORM_FILE_ERROR_INVALID_OPERATION));
}
void DriveFileSystemProxy::CreateSnapshotFile(
const FileSystemURL& file_url,
const FileSystemOperation::SnapshotFileCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
FilePath file_path;
if (!ValidateUrl(file_url, &file_path)) {
MessageLoopProxy::current()->PostTask(FROM_HERE,
base::Bind(callback,
base::PLATFORM_FILE_ERROR_NOT_FOUND,
base::PlatformFileInfo(),
FilePath(),
scoped_refptr<ShareableFileReference>(NULL)));
return;
}
file_system_->GetEntryInfoByPath(
file_path,
base::Bind(&DriveFileSystemProxy::OnGetEntryInfoByPath,
this,
file_path,
callback));
}
void DriveFileSystemProxy::OnGetEntryInfoByPath(
const FilePath& entry_path,
const FileSystemOperation::SnapshotFileCallback& callback,
DriveFileError error,
scoped_ptr<DriveEntryProto> entry_proto) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (error != DRIVE_FILE_OK || !entry_proto.get()) {
MessageLoopProxy::current()->PostTask(FROM_HERE,
base::Bind(callback,
base::PLATFORM_FILE_ERROR_NOT_FOUND,
base::PlatformFileInfo(),
FilePath(),
scoped_refptr<ShareableFileReference>(NULL)));
return;
}
base::PlatformFileInfo file_info;
DriveEntry::ConvertProtoToPlatformFileInfo(
entry_proto->file_info(),
&file_info);
file_system_->GetFileByPath(entry_path,
base::Bind(&CallSnapshotFileCallback,
callback,
file_info),
GetContentCallback());
}
void DriveFileSystemProxy::CreateWritableSnapshotFile(
const FileSystemURL& file_url,
const fileapi::WritableSnapshotFile& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
FilePath file_path;
if (!ValidateUrl(file_url, &file_path)) {
MessageLoopProxy::current()->PostTask(FROM_HERE,
base::Bind(callback,
base::PLATFORM_FILE_ERROR_NOT_FOUND,
FilePath(),
scoped_refptr<ShareableFileReference>(NULL)));
return;
}
file_system_->OpenFile(
file_path,
base::Bind(&DriveFileSystemProxy::OnCreateWritableSnapshotFile,
this,
file_path,
callback));
}
DriveFileSystemProxy::~DriveFileSystemProxy() {
// Should be deleted from the CrosMountPointProvider on UI thread.
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
// static.
bool DriveFileSystemProxy::ValidateUrl(
const FileSystemURL& url, FilePath* file_path) {
// what platform you're on.
if (!url.is_valid() || url.type() != fileapi::kFileSystemTypeDrive) {
return false;
}
*file_path = url.virtual_path();
return true;
}
void DriveFileSystemProxy::OnStatusCallback(
const fileapi::FileSystemOperation::StatusCallback& callback,
DriveFileError error) {
callback.Run(util::DriveFileErrorToPlatformError(error));
}
void DriveFileSystemProxy::OnGetMetadata(
const FilePath& file_path,
const FileSystemOperation::GetMetadataCallback& callback,
DriveFileError error,
scoped_ptr<DriveEntryProto> entry_proto) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (error != DRIVE_FILE_OK) {
callback.Run(util::DriveFileErrorToPlatformError(error),
base::PlatformFileInfo(),
FilePath());
return;
}
DCHECK(entry_proto.get());
base::PlatformFileInfo file_info;
DriveEntry::ConvertProtoToPlatformFileInfo(
entry_proto->file_info(),
&file_info);
callback.Run(base::PLATFORM_FILE_OK, file_info, file_path);
}
void DriveFileSystemProxy::OnReadDirectory(
const FileSystemOperation::ReadDirectoryCallback&
callback,
DriveFileError error,
bool hide_hosted_documents,
scoped_ptr<DriveEntryProtoVector> proto_entries) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (error != DRIVE_FILE_OK) {
callback.Run(util::DriveFileErrorToPlatformError(error),
std::vector<base::FileUtilProxy::Entry>(),
false);
return;
}
DCHECK(proto_entries.get());
std::vector<base::FileUtilProxy::Entry> entries;
// Convert Drive files to something File API stack can understand.
for (size_t i = 0; i < proto_entries->size(); ++i) {
const DriveEntryProto& proto = (*proto_entries)[i];
if (proto.has_file_specific_info() &&
proto.file_specific_info().is_hosted_document() &&
hide_hosted_documents) {
continue;
}
entries.push_back(DriveEntryProtoToFileUtilProxyEntry(proto));
}
callback.Run(base::PLATFORM_FILE_OK, entries, false);
}
void DriveFileSystemProxy::OnCreateWritableSnapshotFile(
const FilePath& virtual_path,
const fileapi::WritableSnapshotFile& callback,
DriveFileError result,
const FilePath& local_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
scoped_refptr<ShareableFileReference> file_ref;
if (result == DRIVE_FILE_OK) {
file_ref = ShareableFileReference::GetOrCreate(
local_path,
ShareableFileReference::DONT_DELETE_ON_FINAL_RELEASE,
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
file_ref->AddFinalReleaseCallback(
base::Bind(&DriveFileSystemProxy::CloseWritableSnapshotFile,
this,
virtual_path));
}
callback.Run(
util::DriveFileErrorToPlatformError(result), local_path, file_ref);
}
void DriveFileSystemProxy::CloseWritableSnapshotFile(
const FilePath& virtual_path,
const FilePath& local_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
file_system_->CloseFile(virtual_path,
base::Bind(&EmitDebugLogForCloseFile, virtual_path));
}
} // namespace gdata