summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkinaba@chromium.org <kinaba@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-16 05:06:11 +0000
committerkinaba@chromium.org <kinaba@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-16 05:06:11 +0000
commitb1abc6a57f507c372e3f9b1dd17354a4cb2ecf05 (patch)
tree733cc3689ffad73fafe94f55f8e847cd2d3714a8
parent127f18ec329490d72c21ffaac2af086534f95412 (diff)
downloadchromium_src-b1abc6a57f507c372e3f9b1dd17354a4cb2ecf05.zip
chromium_src-b1abc6a57f507c372e3f9b1dd17354a4cb2ecf05.tar.gz
chromium_src-b1abc6a57f507c372e3f9b1dd17354a4cb2ecf05.tar.bz2
Truncate() operation for GData file system.
BUG=127097 TEST=browser_test --gest_filter='*RemoteFileSystem*' TEST=unit_tests --gtest_filter='*GData*' Review URL: https://chromiumcodereview.appspot.com/10441015 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@142579 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chromeos/gdata/gdata_file_system_proxy.cc96
-rw-r--r--chrome/browser/chromeos/gdata/gdata_file_system_proxy.h19
-rw-r--r--chrome/test/data/extensions/api_test/filebrowser_component/remote.js37
-rw-r--r--webkit/chromeos/fileapi/remote_file_system_operation.cc6
-rw-r--r--webkit/chromeos/fileapi/remote_file_system_proxy.h8
5 files changed, 165 insertions, 1 deletions
diff --git a/chrome/browser/chromeos/gdata/gdata_file_system_proxy.cc b/chrome/browser/chromeos/gdata/gdata_file_system_proxy.cc
index e739abe..ed07c3a 100644
--- a/chrome/browser/chromeos/gdata/gdata_file_system_proxy.cc
+++ b/chrome/browser/chromeos/gdata/gdata_file_system_proxy.cc
@@ -123,6 +123,34 @@ void OnClose(const FilePath& local_path, base::PlatformFileError error_code) {
DVLOG(1) << "Closed: " << local_path.AsUTF8Unsafe() << ": " << error_code;
}
+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 fileapi::FileSystemOperationInterface::StatusCallback& callback,
+ base::PlatformFileError truncate_result,
+ base::PlatformFileError close_result) {
+ // Reports the first error.
+ callback.Run(truncate_result == base::PLATFORM_FILE_OK ? close_result
+ : truncate_result);
+}
+
} // namespace
namespace gdata {
@@ -265,6 +293,74 @@ void GDataFileSystemProxy::CreateDirectory(
file_system_->CreateDirectory(file_path, exclusive, recursive, callback);
}
+void GDataFileSystemProxy::Truncate(const GURL& file_url, int64 length,
+ const fileapi::FileSystemOperationInterface::StatusCallback& callback) {
+ 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(&GDataFileSystemProxy::OnFileOpenedForTruncate,
+ this,
+ file_path,
+ length,
+ callback));
+}
+
+void GDataFileSystemProxy::OnFileOpenedForTruncate(
+ const FilePath& virtual_path,
+ int64 length,
+ const fileapi::FileSystemOperationInterface::StatusCallback& callback,
+ base::PlatformFileError open_result,
+ const FilePath& local_cache_path) {
+ if (open_result != base::PLATFORM_FILE_OK) {
+ callback.Run(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(&GDataFileSystemProxy::DidTruncate,
+ this,
+ virtual_path,
+ callback,
+ base::Owned(result)));
+ DCHECK(posted);
+}
+
+void GDataFileSystemProxy::DidTruncate(
+ const FilePath& virtual_path,
+ const fileapi::FileSystemOperationInterface::StatusCallback& callback,
+ base::PlatformFileError* truncate_result) {
+ // 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,
+ *truncate_result));
+}
+
void GDataFileSystemProxy::OpenFile(
const GURL& file_url,
int file_flags,
diff --git a/chrome/browser/chromeos/gdata/gdata_file_system_proxy.h b/chrome/browser/chromeos/gdata/gdata_file_system_proxy.h
index d587463..39b1008 100644
--- a/chrome/browser/chromeos/gdata/gdata_file_system_proxy.h
+++ b/chrome/browser/chromeos/gdata/gdata_file_system_proxy.h
@@ -47,6 +47,9 @@ class GDataFileSystemProxy : public fileapi::RemoteFileSystemProxyInterface {
bool recursive,
const fileapi::FileSystemOperationInterface::StatusCallback& callback)
OVERRIDE;
+ virtual void Truncate(const GURL& file_url, int64 length,
+ const fileapi::FileSystemOperationInterface::StatusCallback& callback)
+ OVERRIDE;
virtual void CreateSnapshotFile(
const GURL& path,
const fileapi::FileSystemOperationInterface::SnapshotFileCallback&
@@ -111,6 +114,22 @@ class GDataFileSystemProxy : public fileapi::RemoteFileSystemProxyInterface {
const FilePath& virtual_path,
const FilePath& local_path);
+ // Invoked during Truncate() operation. This is called when a local modifiable
+ // cache is ready for truncation.
+ void OnFileOpenedForTruncate(
+ const FilePath& virtual_path,
+ int64 length,
+ const fileapi::FileSystemOperationInterface::StatusCallback& callback,
+ base::PlatformFileError open_result,
+ const FilePath& local_cache_path);
+
+ // Invoked during Truncate() operation. This is called when the truncation of
+ // a local cache file is finished on FILE thread.
+ void DidTruncate(
+ const FilePath& virtual_path,
+ const fileapi::FileSystemOperationInterface::StatusCallback& callback,
+ base::PlatformFileError* truncate_result);
+
// GDataFileSystemProxy is owned by Profile, which outlives
// GDataFileSystemProxy, which is owned by CrosMountPointProvider (i.e. by
// the time Profile is removed, the file manager is already gone). Hence
diff --git a/chrome/test/data/extensions/api_test/filebrowser_component/remote.js b/chrome/test/data/extensions/api_test/filebrowser_component/remote.js
index 2748a59..61ce941 100644
--- a/chrome/test/data/extensions/api_test/filebrowser_component/remote.js
+++ b/chrome/test/data/extensions/api_test/filebrowser_component/remote.js
@@ -18,6 +18,10 @@ var kExpectedContents = 'hello, world\0';
var kWriteOffset = 12;
var kWriteData = '!!!';
var kExpectedAfterWrite = 'hello, world!!!';
+var kTruncateShortLength = 5;
+var kExpectedAfterTruncateShort = 'hello';
+var kTruncateLongLength = 7;
+var kExpectedAfterTruncateLong = 'hello\0\0';
var kNewDirectoryPath = 'drive/FolderNew';
// Gets local filesystem used in tests.
@@ -86,6 +90,25 @@ TestRunner.prototype.runWriteFileTest = function(fileName) {
self.errorCallback_.bind(self, 'Error opening file: '));
};
+TestRunner.prototype.runTruncateFileTest = function(fileName, length) {
+ var self = this;
+ chrome.test.assertTrue(!!this.directoryEntry_);
+ this.directoryEntry_.getFile(fileName, {},
+ function(entry) {
+ entry.createWriter(
+ function(writer) {
+ writer.onerror = self.errorCallback_.bind(self,
+ 'Error writing file: ');
+ writer.onwriteend = function(e) {
+ chrome.test.succeed();
+ };
+ writer.truncate(length);
+ },
+ self.errorCallback_.bind(self, 'Error creating writer: '));
+ },
+ self.errorCallback_.bind(self, 'Error opening file: '));
+};
+
TestRunner.prototype.runExecuteReadTask = function() {
chrome.test.assertTrue(!!this.fileEntry_);
@@ -211,6 +234,20 @@ chrome.test.runTests([function initTests() {
function readFileAfterWrite() {
testRunner.runReadFileTest(kFileName, kExpectedAfterWrite);
},
+ function truncateFileShort() {
+ // Opens a file in the directory and make it shorter.
+ testRunner.runTruncateFileTest(kFileName, kTruncateShortLength);
+ },
+ function readFileAfterTruncateShort() {
+ testRunner.runReadFileTest(kFileName, kExpectedAfterTruncateShort);
+ },
+ function truncateFileLong() {
+ // Opens a file in the directory and make it longer.
+ testRunner.runTruncateFileTest(kFileName, kTruncateLongLength);
+ },
+ function readFileAfterTruncateLong() {
+ testRunner.runReadFileTest(kFileName, kExpectedAfterTruncateLong);
+ },
function createDir() {
// Creates new directory.
testRunner.runGetDirTest(kNewDirectoryPath, true);
diff --git a/webkit/chromeos/fileapi/remote_file_system_operation.cc b/webkit/chromeos/fileapi/remote_file_system_operation.cc
index 3404f37..e3a551b 100644
--- a/webkit/chromeos/fileapi/remote_file_system_operation.cc
+++ b/webkit/chromeos/fileapi/remote_file_system_operation.cc
@@ -129,7 +129,11 @@ void RemoteFileSystemOperation::Write(
void RemoteFileSystemOperation::Truncate(const GURL& path,
int64 length,
const StatusCallback& callback) {
- NOTIMPLEMENTED();
+ DCHECK(SetPendingOperationType(kOperationTruncate));
+
+ remote_proxy_->Truncate(path, length,
+ base::Bind(&RemoteFileSystemOperation::DidFinishFileOperation,
+ base::Owned(this), callback));
}
void RemoteFileSystemOperation::Cancel(const StatusCallback& cancel_callback) {
diff --git a/webkit/chromeos/fileapi/remote_file_system_proxy.h b/webkit/chromeos/fileapi/remote_file_system_proxy.h
index 214b624..77e4a04 100644
--- a/webkit/chromeos/fileapi/remote_file_system_proxy.h
+++ b/webkit/chromeos/fileapi/remote_file_system_proxy.h
@@ -64,6 +64,14 @@ class RemoteFileSystemProxyInterface :
bool recursive,
const FileSystemOperationInterface::StatusCallback& callback) = 0;
+ // Changes the length of an existing file at |path| to |length|. If |length|
+ // is negative, an error is raised. If |length| is more than the current size
+ // of the file, zero is padded for the extended part.
+ virtual void Truncate(
+ const GURL& path,
+ int64 length,
+ const FileSystemOperationInterface::StatusCallback& callback) = 0;
+
// Creates a local snapshot file for a given |path| and returns the
// metadata and platform path of the snapshot file via |callback|.
// See also FileSystemOperationInterface::CreateSnapshotFile().