Second try at submitting 61462.

BUG=none
TEST=in file_system_operation_unittest.cc

Review URL: http://codereview.chromium.org/3526018

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@61468 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/webkit/fileapi/file_system_operation.cc b/webkit/fileapi/file_system_operation.cc
index 140ade4..e636420 100644
--- a/webkit/fileapi/file_system_operation.cc
+++ b/webkit/fileapi/file_system_operation.cc
@@ -15,10 +15,11 @@
     scoped_refptr<base::MessageLoopProxy> proxy)
     : proxy_(proxy),
       dispatcher_(dispatcher),
-      callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+      callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
+      cancel_operation_(NULL) {
   DCHECK(dispatcher);
 #ifndef NDEBUG
-  operation_pending_ = false;
+  pending_operation_ = kOperationNone;
 #endif
 }
 
@@ -28,8 +29,8 @@
 void FileSystemOperation::CreateFile(const FilePath& path,
                                      bool exclusive) {
 #ifndef NDEBUG
-  DCHECK(!operation_pending_);
-  operation_pending_ = true;
+  DCHECK(kOperationNone == pending_operation_);
+  pending_operation_ = kOperationCreateFile;
 #endif
 
   base::FileUtilProxy::CreateOrOpen(
@@ -43,8 +44,8 @@
                                           bool exclusive,
                                           bool recursive) {
 #ifndef NDEBUG
-  DCHECK(!operation_pending_);
-  operation_pending_ = true;
+  DCHECK(kOperationNone == pending_operation_);
+  pending_operation_ = kOperationCreateDirectory;
 #endif
 
   base::FileUtilProxy::CreateDirectory(
@@ -55,8 +56,8 @@
 void FileSystemOperation::Copy(const FilePath& src_path,
                                const FilePath& dest_path) {
 #ifndef NDEBUG
-  DCHECK(!operation_pending_);
-  operation_pending_ = true;
+  DCHECK(kOperationNone == pending_operation_);
+  pending_operation_ = kOperationCopy;
 #endif
 
   base::FileUtilProxy::Copy(proxy_, src_path, dest_path,
@@ -67,8 +68,8 @@
 void FileSystemOperation::Move(const FilePath& src_path,
                                const FilePath& dest_path) {
 #ifndef NDEBUG
-  DCHECK(!operation_pending_);
-  operation_pending_ = true;
+  DCHECK(kOperationNone == pending_operation_);
+  pending_operation_ = kOperationMove;
 #endif
 
   base::FileUtilProxy::Move(proxy_, src_path, dest_path,
@@ -78,8 +79,8 @@
 
 void FileSystemOperation::DirectoryExists(const FilePath& path) {
 #ifndef NDEBUG
-  DCHECK(!operation_pending_);
-  operation_pending_ = true;
+  DCHECK(kOperationNone == pending_operation_);
+  pending_operation_ = kOperationDirectoryExists;
 #endif
 
   base::FileUtilProxy::GetFileInfo(proxy_, path, callback_factory_.NewCallback(
@@ -88,8 +89,8 @@
 
 void FileSystemOperation::FileExists(const FilePath& path) {
 #ifndef NDEBUG
-  DCHECK(!operation_pending_);
-  operation_pending_ = true;
+  DCHECK(kOperationNone == pending_operation_);
+  pending_operation_ = kOperationFileExists;
 #endif
 
   base::FileUtilProxy::GetFileInfo(proxy_, path, callback_factory_.NewCallback(
@@ -98,8 +99,8 @@
 
 void FileSystemOperation::GetMetadata(const FilePath& path) {
 #ifndef NDEBUG
-  DCHECK(!operation_pending_);
-  operation_pending_ = true;
+  DCHECK(kOperationNone == pending_operation_);
+  pending_operation_ = kOperationGetMetadata;
 #endif
 
   base::FileUtilProxy::GetFileInfo(proxy_, path, callback_factory_.NewCallback(
@@ -108,8 +109,8 @@
 
 void FileSystemOperation::ReadDirectory(const FilePath& path) {
 #ifndef NDEBUG
-  DCHECK(!operation_pending_);
-  operation_pending_ = true;
+  DCHECK(kOperationNone == pending_operation_);
+  pending_operation_ = kOperationReadDirectory;
 #endif
 
   base::FileUtilProxy::ReadDirectory(proxy_, path,
@@ -119,8 +120,8 @@
 
 void FileSystemOperation::Remove(const FilePath& path) {
 #ifndef NDEBUG
-  DCHECK(!operation_pending_);
-  operation_pending_ = true;
+  DCHECK(kOperationNone == pending_operation_);
+  pending_operation_ = kOperationRemove;
 #endif
 
   base::FileUtilProxy::Delete(proxy_, path, callback_factory_.NewCallback(
@@ -128,36 +129,32 @@
 }
 
 void FileSystemOperation::Write(
-    const FilePath&,
-    const GURL&,
-    int64) {
+    const FilePath& path,
+    const GURL& blob_url,
+    int64 offset) {
 #ifndef NDEBUG
-  DCHECK(!operation_pending_);
-  operation_pending_ = true;
+  DCHECK(kOperationNone == pending_operation_);
+  pending_operation_ = kOperationWrite;
 #endif
   NOTREACHED();
-  // TODO(ericu):
-  // Set up a loop that, via multiple callback invocations, reads from a
-  // URLRequest wrapping blob_url, writes the bytes to the file, reports
-  // progress events no more frequently than some set rate, and periodically
-  // checks to see if it's been cancelled.
 }
 
 void FileSystemOperation::Truncate(const FilePath& path, int64 length) {
 #ifndef NDEBUG
-  DCHECK(!operation_pending_);
-  operation_pending_ = true;
+  DCHECK(kOperationNone == pending_operation_);
+  pending_operation_ = kOperationTruncate;
 #endif
-  // TODO(ericu):
-  NOTREACHED();
+  base::FileUtilProxy::Truncate(proxy_, path, length,
+      callback_factory_.NewCallback(
+          &FileSystemOperation::DidFinishFileOperation));
 }
 
 void FileSystemOperation::TouchFile(const FilePath& path,
                                     const base::Time& last_access_time,
                                     const base::Time& last_modified_time) {
 #ifndef NDEBUG
-  DCHECK(!operation_pending_);
-  operation_pending_ = true;
+  DCHECK(kOperationNone == pending_operation_);
+  pending_operation_ = kOperationTouchFile;
 #endif
 
   base::FileUtilProxy::Touch(
@@ -165,15 +162,18 @@
       callback_factory_.NewCallback(&FileSystemOperation::DidTouchFile));
 }
 
-void FileSystemOperation::Cancel() {
+// We can only get here on a write or truncate that's not yet completed.
+// We don't support cancelling any other operation at this time.
+void FileSystemOperation::Cancel(FileSystemOperation* cancel_operation) {
 #ifndef NDEBUG
-  DCHECK(operation_pending_);
+  DCHECK(kOperationTruncate == pending_operation_);
+  // FIXME(ericu): Cancelling for writes coming soon.
 #endif
-  NOTREACHED();
-  // TODO(ericu):
-  // Make sure this was done on a FileSystemOperation used for a Write.
-  // Then set a flag that ensures that the Write loop will exit without
-  // reporting any more progress, with a failure notification.
+  // We're cancelling a truncate operation, but we can't actually stop it
+  // since it's been proxied to another thread.  We need to save the
+  // cancel_operation so that when the truncate returns, it can see that it's
+  // been cancelled, report it, and report that the cancel has succeeded.
+  cancel_operation_ = cancel_operation;
 }
 
 void FileSystemOperation::DidCreateFileExclusive(
@@ -197,10 +197,19 @@
 
 void FileSystemOperation::DidFinishFileOperation(
     base::PlatformFileError rv) {
-  if (rv == base::PLATFORM_FILE_OK)
+  if (cancel_operation_) {
+#ifndef NDEBUG
+    DCHECK(kOperationTruncate == pending_operation_);
+#endif
+    FileSystemOperation *cancel_op = cancel_operation_;
+    // This call deletes us, so we have to extract cancel_op first.
+    dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_ABORT);
+    cancel_op->dispatcher_->DidSucceed();
+  } else if (rv == base::PLATFORM_FILE_OK) {
     dispatcher_->DidSucceed();
-  else
+  } else {
     dispatcher_->DidFail(rv);
+  }
 }
 
 void FileSystemOperation::DidDirectoryExists(
@@ -250,7 +259,7 @@
     int64 bytes,
     bool complete) {
   if (rv == base::PLATFORM_FILE_OK)
-    /* dispatcher_->DidWrite(bytes, complete) TODO(ericu): Coming soon. */ {}
+    dispatcher_->DidWrite(bytes, complete);
   else
     dispatcher_->DidFail(rv);
 }