diff options
author | kinaba@chromium.org <kinaba@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-01 05:54:26 +0000 |
---|---|---|
committer | kinaba@chromium.org <kinaba@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-01 05:54:26 +0000 |
commit | a95ce07699b8ce79df8b59e36fe53b345a5921b2 (patch) | |
tree | c4b54622b37e7aa21e004e3570b6fb6299b00973 | |
parent | 2f729cd95a5452af56269f594ffbe4f539303182 (diff) | |
download | chromium_src-a95ce07699b8ce79df8b59e36fe53b345a5921b2.zip chromium_src-a95ce07699b8ce79df8b59e36fe53b345a5921b2.tar.gz chromium_src-a95ce07699b8ce79df8b59e36fe53b345a5921b2.tar.bz2 |
Flush at the end of local file writing in FileWriter API.
This CL ensures the written content is flushed physically before
fileWriter.write() invokes the "onwriteend" event, for native local files.
Remote files (Google Drive files in Chrome OS) nor FileSystem API
files (in PERSISTENT or TEMPORARY storage) aren't affected.
The summary of the changes:
* Call Flush() before the final callback.
(webkit/fileapi/file_writer_delegate.cc)
* Delegate Flush() to net::FileStream::Flush
(webkit/fileapi/local_file_stream_writer.cc)
* No-op implementation for Flush().
(webkit/fileapi/sanbox_file_stream_writer.cc)
(webkit/chromeos/fileapi/remote_file_stream_writer.cc)
* Implementation of asynchronous Flush.
(net/base/file_stream_{posix,win}.cc)
* Other files are just for reflecting the rename Flush -> FlushSync.
BUG=144790
R=willchan@chromium.org,kinuko@chromium.org,benjhayden@chromium.org
TBR=marja@chromium.org
TEST=out/Debug/browser_tests --gtest_filter='*FileSystemApi*'
TEST=./webkit/tools/layout_tests/run_webkit_tests.sh fast/filesystem
TEST=Manual steps reported in the issue.
Review URL: https://codereview.chromium.org/10986045
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@159454 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/sessions/session_backend.cc | 2 | ||||
-rw-r--r-- | content/browser/download/base_file.cc | 2 | ||||
-rw-r--r-- | net/base/file_stream.cc | 8 | ||||
-rw-r--r-- | net/base/file_stream.h | 25 | ||||
-rw-r--r-- | net/base/file_stream_posix.cc | 37 | ||||
-rw-r--r-- | net/base/file_stream_posix.h | 3 | ||||
-rw-r--r-- | net/base/file_stream_win.cc | 49 | ||||
-rw-r--r-- | net/base/file_stream_win.h | 9 | ||||
-rw-r--r-- | net/base/mock_file_stream.cc | 8 | ||||
-rw-r--r-- | net/base/mock_file_stream.h | 3 | ||||
-rw-r--r-- | webkit/chromeos/fileapi/remote_file_stream_writer.cc | 6 | ||||
-rw-r--r-- | webkit/chromeos/fileapi/remote_file_stream_writer.h | 1 | ||||
-rw-r--r-- | webkit/fileapi/file_stream_writer.h | 10 | ||||
-rw-r--r-- | webkit/fileapi/file_writer_delegate.cc | 41 | ||||
-rw-r--r-- | webkit/fileapi/file_writer_delegate.h | 7 | ||||
-rw-r--r-- | webkit/fileapi/local_file_stream_writer.cc | 35 | ||||
-rw-r--r-- | webkit/fileapi/local_file_stream_writer.h | 7 | ||||
-rw-r--r-- | webkit/fileapi/sandbox_file_stream_writer.cc | 6 | ||||
-rw-r--r-- | webkit/fileapi/sandbox_file_stream_writer.h | 1 |
19 files changed, 243 insertions, 17 deletions
diff --git a/chrome/browser/sessions/session_backend.cc b/chrome/browser/sessions/session_backend.cc index 39ec9b3..95cc5d1 100644 --- a/chrome/browser/sessions/session_backend.cc +++ b/chrome/browser/sessions/session_backend.cc @@ -343,7 +343,7 @@ bool SessionBackend::AppendCommandsToFile(net::FileStream* file, } } } - file->Flush(); + file->FlushSync(); return true; } diff --git a/content/browser/download/base_file.cc b/content/browser/download/base_file.cc index 6ada5c8..cc7871f 100644 --- a/content/browser/download/base_file.cc +++ b/content/browser/download/base_file.cc @@ -527,7 +527,7 @@ void BaseFile::Close() { #if defined(OS_CHROMEOS) // Currently we don't really care about the return value, since if it fails // theres not much we can do. But we might in the future. - file_stream_->Flush(); + file_stream_->FlushSync(); #endif file_stream_->CloseSync(); ClearStream(net::OK); diff --git a/net/base/file_stream.cc b/net/base/file_stream.cc index 1707fb7..df18ad0 100644 --- a/net/base/file_stream.cc +++ b/net/base/file_stream.cc @@ -78,8 +78,12 @@ int64 FileStream::Truncate(int64 bytes) { return impl_.Truncate(bytes); } -int FileStream::Flush() { - return impl_.Flush(); +int FileStream::Flush(const CompletionCallback& callback) { + return impl_.Flush(callback); +} + +int FileStream::FlushSync() { + return impl_.FlushSync(); } void FileStream::EnableErrorStatistics() { diff --git a/net/base/file_stream.h b/net/base/file_stream.h index 2031bd0..f4cfff2 100644 --- a/net/base/file_stream.h +++ b/net/base/file_stream.h @@ -197,10 +197,31 @@ class NET_EXPORT FileStream { // not have to be called, it just forces one to happen at the time of // calling. // - /// Returns an error code if the operation could not be performed. + // The file must be opened with PLATFORM_FILE_ASYNC, and a non-null + // callback must be passed to this method. If the write could not + // complete synchronously, then ERR_IO_PENDING is returned, and the + // callback will be run on the thread where Flush() was called when + // the write has completed. + // + // It is valid to destroy or close the file stream while there is an + // asynchronous flush in progress. That will cancel the flush and allow + // the buffer to be freed. + // + // It is invalid to request any asynchronous operations while there is an + // in-flight asynchronous operation. + // + // This method should not be called if the stream was opened READ_ONLY. + virtual int Flush(const CompletionCallback& callback); + + // Forces out a filesystem sync on this file to make sure that the file was + // written out to disk and is not currently sitting in the buffer. This does + // not have to be called, it just forces one to happen at the time of + // calling. + // + // Returns an error code if the operation could not be performed. // // This method should not be called if the stream was opened READ_ONLY. - virtual int Flush(); + virtual int FlushSync(); // Turns on UMA error statistics gathering. void EnableErrorStatistics(); diff --git a/net/base/file_stream_posix.cc b/net/base/file_stream_posix.cc index 0cbd0bd..5613fe3 100644 --- a/net/base/file_stream_posix.cc +++ b/net/base/file_stream_posix.cc @@ -231,6 +231,16 @@ int FlushFile(base::PlatformFile file, return res; } +// Flushes a file using FlushFile() and signals the completion. +void FlushFileAndSignal(base::PlatformFile file, + int* result, + bool record_uma, + base::WaitableEvent* on_io_complete, + const net::BoundNetLog& bound_net_log) { + *result = FlushFile(file, record_uma, bound_net_log); + on_io_complete->Signal(); +} + // Called when Read(), Write() or Seek() is completed. // |result| contains the result or a network error code. template <typename R> @@ -588,7 +598,32 @@ int64 FileStreamPosix::Truncate(int64 bytes) { bound_net_log_); } -int FileStreamPosix::Flush() { +int FileStreamPosix::Flush(const CompletionCallback& callback) { + if (!IsOpen()) + return ERR_UNEXPECTED; + + // Make sure we're async and we have no other in-flight async operations. + DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); + DCHECK(!weak_ptr_factory_.HasWeakPtrs()); + DCHECK(!on_io_complete_.get()); + + on_io_complete_.reset(new base::WaitableEvent( + false /* manual_reset */, false /* initially_signaled */)); + + int* result = new int(OK); + const bool posted = base::WorkerPool::PostTaskAndReply( + FROM_HERE, + base::Bind(&FlushFileAndSignal, file_, result, + record_uma_, on_io_complete_.get(), bound_net_log_), + base::Bind(&OnIOComplete<int>, + weak_ptr_factory_.GetWeakPtr(), + callback, base::Owned(result)), + true /* task is slow */); + DCHECK(posted); + return ERR_IO_PENDING; +} + +int FileStreamPosix::FlushSync() { if (!IsOpen()) return ERR_UNEXPECTED; diff --git a/net/base/file_stream_posix.h b/net/base/file_stream_posix.h index 0f1ee01..2ac7d63 100644 --- a/net/base/file_stream_posix.h +++ b/net/base/file_stream_posix.h @@ -48,7 +48,8 @@ class NET_EXPORT FileStreamPosix { int Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback); int WriteSync(const char* buf, int buf_len); int64 Truncate(int64 bytes); - int Flush(); + int Flush(const CompletionCallback& callback); + int FlushSync(); void EnableErrorStatistics(); void SetBoundNetLogSource( const net::BoundNetLog& owner_bound_net_log); diff --git a/net/base/file_stream_win.cc b/net/base/file_stream_win.cc index fe820b1..88e1dc7 100644 --- a/net/base/file_stream_win.cc +++ b/net/base/file_stream_win.cc @@ -587,7 +587,37 @@ int FileStreamWin::WriteSync( return rv; } -int FileStreamWin::Flush() { +int FileStreamWin::Flush(const CompletionCallback& callback) { + if (!IsOpen()) + return ERR_UNEXPECTED; + + // Make sure we're async and we have no other in-flight async operations. + DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); + DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); + DCHECK(!weak_ptr_factory_.HasWeakPtrs()); + DCHECK(!on_io_complete_.get()); + + on_io_complete_.reset(new base::WaitableEvent( + false /* manual_reset */, false /* initially_signaled */)); + + int* result = new int(OK); + const bool posted = base::WorkerPool::PostTaskAndReply( + FROM_HERE, + base::Bind(&InvokeAndSignal, + // Unretained should be fine as we wait for a signal on + // on_io_complete_ at the destructor. + base::Bind(&FileStreamWin::FlushFile, base::Unretained(this), + result), + on_io_complete_.get()), + base::Bind(&FileStreamWin::OnFlushed, + weak_ptr_factory_.GetWeakPtr(), + callback, base::Owned(result)), + true /* task is slow */); + DCHECK(posted); + return ERR_IO_PENDING; +} + +int FileStreamWin::FlushSync() { base::ThreadRestrictions::AssertIOAllowed(); if (!IsOpen()) @@ -692,6 +722,17 @@ void FileStreamWin::SeekFile(Whence whence, int64 offset, int64* result) { *result = res.QuadPart; } +void FileStreamWin::FlushFile(int* result) { + if (FlushFileBuffers(file_)) { + *result = OK; + } else { + *result = RecordAndMapError(GetLastError(), + FILE_ERROR_SOURCE_FLUSH, + record_uma_, + bound_net_log_); + } +} + void FileStreamWin::OnOpened(const CompletionCallback& callback, int* result) { if (*result == OK) { async_context_.reset(new AsyncContext(bound_net_log_)); @@ -714,6 +755,12 @@ void FileStreamWin::OnSeeked( callback.Run(*result); } +void FileStreamWin::OnFlushed(const CompletionCallback& callback, int* result) { + // Reset this before Run() as Run() may issue a new async operation. + ResetOnIOComplete(); + callback.Run(*result); +} + void FileStreamWin::ResetOnIOComplete() { on_io_complete_.reset(); weak_ptr_factory_.InvalidateWeakPtrs(); diff --git a/net/base/file_stream_win.h b/net/base/file_stream_win.h index 4feb7a2..e241f4c 100644 --- a/net/base/file_stream_win.h +++ b/net/base/file_stream_win.h @@ -49,7 +49,8 @@ class NET_EXPORT FileStreamWin { int Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback); int WriteSync(const char* buf, int buf_len); int64 Truncate(int64 bytes); - int Flush(); + int Flush(const CompletionCallback& callback); + int FlushSync(); void EnableErrorStatistics(); void SetBoundNetLogSource(const net::BoundNetLog& owner_bound_net_log); base::PlatformFile GetPlatformFileForTesting(); @@ -60,6 +61,9 @@ class NET_EXPORT FileStreamWin { // A helper method for Seek. void SeekFile(Whence whence, int64 offset, int64* result); + // A helper method for Flush. + void FlushFile(int* result); + // Called when the file_ is opened asynchronously. |result| contains the // result as a network error code. void OnOpened(const CompletionCallback& callback, int* result); @@ -70,6 +74,9 @@ class NET_EXPORT FileStreamWin { // Called when the file_ is seeked asynchronously. void OnSeeked(const Int64CompletionCallback& callback, int64* result); + // Called when the file_ is flushed asynchronously. + void OnFlushed(const CompletionCallback& callback, int* result); + // Resets on_io_complete_ and WeakPtr's. // Called in OnOpened, OnClosed and OnSeeked. void ResetOnIOComplete(); diff --git a/net/base/mock_file_stream.cc b/net/base/mock_file_stream.cc index 42c23cb..fccb7a0 100644 --- a/net/base/mock_file_stream.cc +++ b/net/base/mock_file_stream.cc @@ -54,8 +54,12 @@ int64 MockFileStream::Truncate(int64 bytes) { return ReturnError64(FileStream::Truncate(bytes)); } -int MockFileStream::Flush() { - return ReturnError(FileStream::Flush()); +int MockFileStream::Flush(const CompletionCallback& callback) { + return ReturnError(FileStream::Flush(callback)); +} + +int MockFileStream::FlushSync() { + return ReturnError(FileStream::FlushSync()); } } // namespace testing diff --git a/net/base/mock_file_stream.h b/net/base/mock_file_stream.h index 18b7127..f9c8bbd 100644 --- a/net/base/mock_file_stream.h +++ b/net/base/mock_file_stream.h @@ -43,7 +43,8 @@ class MockFileStream : public net::FileStream { const CompletionCallback& callback) OVERRIDE; virtual int WriteSync(const char* buf, int buf_len) OVERRIDE; virtual int64 Truncate(int64 bytes) OVERRIDE; - virtual int Flush() OVERRIDE; + virtual int Flush(const CompletionCallback& callback) OVERRIDE; + virtual int FlushSync() OVERRIDE; void set_forced_error(int error) { forced_error_ = error; } void clear_forced_error() { forced_error_ = net::OK; } diff --git a/webkit/chromeos/fileapi/remote_file_stream_writer.cc b/webkit/chromeos/fileapi/remote_file_stream_writer.cc index fd9ab53..187a79a 100644 --- a/webkit/chromeos/fileapi/remote_file_stream_writer.cc +++ b/webkit/chromeos/fileapi/remote_file_stream_writer.cc @@ -104,6 +104,12 @@ int RemoteFileStreamWriter::Cancel(const net::CompletionCallback& callback) { return net::ERR_UNEXPECTED; } +int RemoteFileStreamWriter::Flush(const net::CompletionCallback& callback) { + // For remote file writer, Flush() is a no-op. Synchronization to the remote + // server is not done until the file is closed. + return net::OK; +} + void RemoteFileStreamWriter::InvokePendingCancelCallback(int result) { net::CompletionCallback callback = pending_cancel_callback_; pending_cancel_callback_.Reset(); diff --git a/webkit/chromeos/fileapi/remote_file_stream_writer.h b/webkit/chromeos/fileapi/remote_file_stream_writer.h index fc88773..cf341bd3 100644 --- a/webkit/chromeos/fileapi/remote_file_stream_writer.h +++ b/webkit/chromeos/fileapi/remote_file_stream_writer.h @@ -42,6 +42,7 @@ class RemoteFileStreamWriter : public fileapi::FileStreamWriter { virtual int Write(net::IOBuffer* buf, int buf_len, const net::CompletionCallback& callback) OVERRIDE; virtual int Cancel(const net::CompletionCallback& callback) OVERRIDE; + virtual int Flush(const net::CompletionCallback& callback) OVERRIDE; private: // Callback function to do the continuation of the work of the first Write() diff --git a/webkit/fileapi/file_stream_writer.h b/webkit/fileapi/file_stream_writer.h index 967d501..f3f6398 100644 --- a/webkit/fileapi/file_stream_writer.h +++ b/webkit/fileapi/file_stream_writer.h @@ -55,6 +55,16 @@ class FILEAPI_EXPORT_PRIVATE FileStreamWriter { // operation is dismissed immediately when Cancel() is called, and thus // will never be called. virtual int Cancel(const net::CompletionCallback& callback) = 0; + + // Flushes the data written so far. + // + // If the flush finished synchronously, it return net::OK. If the flush could + // not be performed, it returns an error code. Otherwise, net::ERR_IO_PENDING + // is returned, and the callback will be run on the thread where Flush() was + // called when the flush has completed. + // + // It is invalid to call Flush while there is an in-flight async operation. + virtual int Flush(const net::CompletionCallback& callback) = 0; }; } // namespace fileapi diff --git a/webkit/fileapi/file_writer_delegate.cc b/webkit/fileapi/file_writer_delegate.cc index 3794edd..df97a23 100644 --- a/webkit/fileapi/file_writer_delegate.cc +++ b/webkit/fileapi/file_writer_delegate.cc @@ -24,6 +24,8 @@ namespace { base::PlatformFileError NetErrorToPlatformFileError(int error) { // TODO(kinuko): Move this static method to more convenient place. switch (error) { + case net::OK: + return base::PLATFORM_FILE_OK; case net::ERR_FILE_NO_SPACE: return base::PLATFORM_FILE_ERROR_NO_SPACE; case net::ERR_FILE_NOT_FOUND: @@ -187,7 +189,10 @@ void FileWriterDelegate::OnError(base::PlatformFileError error) { request_->Cancel(); } - write_callback_.Run(error, 0, GetCompletionStatusOnError()); + if (writing_started_) + FlushForCompletion(error, 0, ERROR_WRITE_STARTED); + else + write_callback_.Run(error, 0, ERROR_WRITE_NOT_STARTED); } void FileWriterDelegate::OnProgress(int bytes_written, bool done) { @@ -201,8 +206,13 @@ void FileWriterDelegate::OnProgress(int bytes_written, bool done) { last_progress_event_time_ = currentTime; bytes_written_backlog_ = 0; - WriteProgressStatus status = done ? SUCCESS_COMPLETED : SUCCESS_IO_PENDING; - write_callback_.Run(base::PLATFORM_FILE_OK, bytes_written, status); + if (done) { + FlushForCompletion(base::PLATFORM_FILE_OK, bytes_written, + SUCCESS_COMPLETED); + } else { + write_callback_.Run(base::PLATFORM_FILE_OK, bytes_written, + SUCCESS_IO_PENDING); + } return; } bytes_written_backlog_ += bytes_written; @@ -213,4 +223,29 @@ void FileWriterDelegate::OnWriteCancelled(int status) { GetCompletionStatusOnError()); } +void FileWriterDelegate::FlushForCompletion( + base::PlatformFileError error, + int bytes_written, + WriteProgressStatus progress_status) { + int flush_error = file_stream_writer_->Flush( + base::Bind(&FileWriterDelegate::OnFlushed, + weak_factory_.GetWeakPtr(), + error, bytes_written, progress_status)); + if (flush_error != net::ERR_IO_PENDING) + OnFlushed(error, bytes_written, progress_status, flush_error); +} + +void FileWriterDelegate::OnFlushed(base::PlatformFileError error, + int bytes_written, + WriteProgressStatus progress_status, + int flush_error) { + if (error == base::PLATFORM_FILE_OK && flush_error != net::OK) { + // If the Flush introduced an error, overwrite the status. + // Otherwise, keep the original error status. + error = NetErrorToPlatformFileError(flush_error); + progress_status = GetCompletionStatusOnError(); + } + write_callback_.Run(error, bytes_written, progress_status); +} + } // namespace fileapi diff --git a/webkit/fileapi/file_writer_delegate.h b/webkit/fileapi/file_writer_delegate.h index 6a6dff8..5629623 100644 --- a/webkit/fileapi/file_writer_delegate.h +++ b/webkit/fileapi/file_writer_delegate.h @@ -77,6 +77,13 @@ class FILEAPI_EXPORT_PRIVATE FileWriterDelegate void OnError(base::PlatformFileError error); void OnProgress(int bytes_read, bool done); void OnWriteCancelled(int status); + void FlushForCompletion(base::PlatformFileError error, + int bytes_written, + WriteProgressStatus progress_status); + void OnFlushed(base::PlatformFileError error, + int bytes_written, + WriteProgressStatus progress_status, + int flush_error); FileSystemQuotaUtil* quota_util() const; WriteProgressStatus GetCompletionStatusOnError() const; diff --git a/webkit/fileapi/local_file_stream_writer.cc b/webkit/fileapi/local_file_stream_writer.cc index 95a2a7e..f3679f9 100644 --- a/webkit/fileapi/local_file_stream_writer.cc +++ b/webkit/fileapi/local_file_stream_writer.cc @@ -64,6 +64,21 @@ int LocalFileStreamWriter::Cancel(const net::CompletionCallback& callback) { return net::ERR_IO_PENDING; } +int LocalFileStreamWriter::Flush(const net::CompletionCallback& callback) { + DCHECK(!has_pending_operation_); + DCHECK(cancel_callback_.is_null()); + + // Write() is not called yet, so there's nothing to flush. + if (!stream_impl_.get()) + return net::OK; + + has_pending_operation_ = true; + int result = InitiateFlush(callback); + if (result != net::ERR_IO_PENDING) + has_pending_operation_ = false; + return result; +} + int LocalFileStreamWriter::InitiateOpen( const net::CompletionCallback& error_callback, const base::Closure& main_operation) { @@ -179,6 +194,26 @@ void LocalFileStreamWriter::DidWrite(const net::CompletionCallback& callback, callback.Run(result); } +int LocalFileStreamWriter::InitiateFlush( + const net::CompletionCallback& callback) { + DCHECK(has_pending_operation_); + DCHECK(stream_impl_.get()); + + return stream_impl_->Flush(base::Bind(&LocalFileStreamWriter::DidFlush, + weak_factory_.GetWeakPtr(), + callback)); +} + +void LocalFileStreamWriter::DidFlush(const net::CompletionCallback& callback, + int result) { + DCHECK(has_pending_operation_); + + if (CancelIfRequested()) + return; + has_pending_operation_ = false; + callback.Run(result); +} + bool LocalFileStreamWriter::CancelIfRequested() { DCHECK(has_pending_operation_); diff --git a/webkit/fileapi/local_file_stream_writer.h b/webkit/fileapi/local_file_stream_writer.h index 8962bd2..41b9f88f 100644 --- a/webkit/fileapi/local_file_stream_writer.h +++ b/webkit/fileapi/local_file_stream_writer.h @@ -30,10 +30,11 @@ class FILEAPI_EXPORT_PRIVATE LocalFileStreamWriter : public FileStreamWriter { LocalFileStreamWriter(const FilePath& file_path, int64 initial_offset); virtual ~LocalFileStreamWriter(); - // FileStreamWriteroverrides. + // FileStreamWriter overrides. virtual int Write(net::IOBuffer* buf, int buf_len, const net::CompletionCallback& callback) OVERRIDE; virtual int Cancel(const net::CompletionCallback& callback) OVERRIDE; + virtual int Flush(const net::CompletionCallback& callback) OVERRIDE; private: // Opens |file_path_| and if it succeeds, proceeds to InitiateSeek(). @@ -61,6 +62,10 @@ class FILEAPI_EXPORT_PRIVATE LocalFileStreamWriter : public FileStreamWriter { const net::CompletionCallback& callback); void DidWrite(const net::CompletionCallback& callback, int result); + // Flushes asynchronously to the file. + int InitiateFlush(const net::CompletionCallback& callback); + void DidFlush(const net::CompletionCallback& callback, int result); + // Stops the in-flight operation and calls |cancel_callback_| if it has been // set by Cancel() for the current operation. bool CancelIfRequested(); diff --git a/webkit/fileapi/sandbox_file_stream_writer.cc b/webkit/fileapi/sandbox_file_stream_writer.cc index a12e00e..a00136e 100644 --- a/webkit/fileapi/sandbox_file_stream_writer.cc +++ b/webkit/fileapi/sandbox_file_stream_writer.cc @@ -234,4 +234,10 @@ bool SandboxFileStreamWriter::CancelIfRequested() { return true; } +int SandboxFileStreamWriter::Flush(const net::CompletionCallback& callback) { + // For now, Flush is meaningful only for local native file access. It is no-op + // for sandboxed filesystem files (see the discussion in crbug.com/144790). + return net::OK; +} + } // namespace fileapi diff --git a/webkit/fileapi/sandbox_file_stream_writer.h b/webkit/fileapi/sandbox_file_stream_writer.h index daf3b6a..55067e7 100644 --- a/webkit/fileapi/sandbox_file_stream_writer.h +++ b/webkit/fileapi/sandbox_file_stream_writer.h @@ -34,6 +34,7 @@ class FILEAPI_EXPORT_PRIVATE SandboxFileStreamWriter : public FileStreamWriter { virtual int Write(net::IOBuffer* buf, int buf_len, const net::CompletionCallback& callback) OVERRIDE; virtual int Cancel(const net::CompletionCallback& callback) OVERRIDE; + virtual int Flush(const net::CompletionCallback& callback) OVERRIDE; // Used only by tests. void set_default_quota(int64 quota) { |