diff options
author | ericu@google.com <ericu@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-07 19:55:00 +0000 |
---|---|---|
committer | ericu@google.com <ericu@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-07 19:55:00 +0000 |
commit | 368ddad78d3f2eac1ea7a92cfb9716ecd0166279 (patch) | |
tree | 12991a1cf9204760a254dfacd954158035e4d52b | |
parent | c1973bdf0c94687f96155af8249358a4b585e381 (diff) | |
download | chromium_src-368ddad78d3f2eac1ea7a92cfb9716ecd0166279.zip chromium_src-368ddad78d3f2eac1ea7a92cfb9716ecd0166279.tar.gz chromium_src-368ddad78d3f2eac1ea7a92cfb9716ecd0166279.tar.bz2 |
Add the actual writing-files part of FileWriter.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/3476002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@61833 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/file_system/file_system_dispatcher_host.cc | 14 | ||||
-rw-r--r-- | chrome/browser/file_system/file_system_dispatcher_host.h | 11 | ||||
-rw-r--r-- | chrome/browser/renderer_host/resource_message_filter.cc | 3 | ||||
-rw-r--r-- | chrome/browser/worker_host/worker_process_host.cc | 3 | ||||
-rw-r--r-- | chrome/common/file_system/webfilewriter_impl.cc | 66 | ||||
-rw-r--r-- | chrome/common/file_system/webfilewriter_impl.h | 28 | ||||
-rw-r--r-- | webkit/fileapi/file_system_operation.cc | 60 | ||||
-rw-r--r-- | webkit/fileapi/file_system_operation.h | 19 | ||||
-rw-r--r-- | webkit/fileapi/file_writer_delegate.cc | 164 | ||||
-rw-r--r-- | webkit/fileapi/file_writer_delegate.h | 71 | ||||
-rw-r--r-- | webkit/fileapi/webkit_fileapi.gypi | 2 |
11 files changed, 391 insertions, 50 deletions
diff --git a/chrome/browser/file_system/file_system_dispatcher_host.cc b/chrome/browser/file_system/file_system_dispatcher_host.cc index 177c98d..e81fc27 100644 --- a/chrome/browser/file_system/file_system_dispatcher_host.cc +++ b/chrome/browser/file_system/file_system_dispatcher_host.cc @@ -13,9 +13,11 @@ #include "chrome/browser/file_system/file_system_host_context.h" #include "chrome/browser/host_content_settings_map.h" #include "chrome/browser/renderer_host/browser_render_process_host.h" +#include "chrome/common/net/url_request_context_getter.h" #include "chrome/common/render_messages.h" #include "chrome/common/render_messages_params.h" #include "googleurl/src/gurl.h" +#include "net/url_request/url_request_context.h" // A class to hold an ongoing openFileSystem completion task. struct OpenFileSystemCompletionTask { @@ -69,12 +71,14 @@ struct OpenFileSystemCompletionTask { FileSystemDispatcherHost::FileSystemDispatcherHost( IPC::Message::Sender* sender, FileSystemHostContext* file_system_host_context, - HostContentSettingsMap* host_content_settings_map) + HostContentSettingsMap* host_content_settings_map, + URLRequestContextGetter* request_context_getter) : message_sender_(sender), process_handle_(0), shutdown_(false), context_(file_system_host_context), - host_content_settings_map_(host_content_settings_map) { + host_content_settings_map_(host_content_settings_map), + request_context_getter_(request_context_getter) { DCHECK(message_sender_); } @@ -87,6 +91,9 @@ void FileSystemDispatcherHost::Init(base::ProcessHandle process_handle) { DCHECK(!process_handle_); DCHECK(process_handle); process_handle_ = process_handle; + DCHECK(request_context_getter_.get()); + DCHECK(!request_context_.get()); + request_context_ = request_context_getter_->GetURLRequestContext(); } void FileSystemDispatcherHost::Shutdown() { @@ -214,7 +221,8 @@ void FileSystemDispatcherHost::OnWrite( int64 offset) { if (!CheckValidFileSystemPath(path, request_id)) return; - GetNewOperation(request_id)->Write(path, blob_url, offset); + GetNewOperation(request_id)->Write( + request_context_, path, blob_url, offset); } void FileSystemDispatcherHost::OnTruncate( diff --git a/chrome/browser/file_system/file_system_dispatcher_host.h b/chrome/browser/file_system/file_system_dispatcher_host.h index 68110be..201ade6 100644 --- a/chrome/browser/file_system/file_system_dispatcher_host.h +++ b/chrome/browser/file_system/file_system_dispatcher_host.h @@ -26,13 +26,17 @@ class GURL; class HostContentSettingsMap; class Receiver; class ResourceMessageFilter; +class URLRequestContextGetter; class FileSystemDispatcherHost : public base::RefCountedThreadSafe<FileSystemDispatcherHost> { public: + // TODO(ericu): Split this into two constructors when adding worker FileWriter + // support. FileSystemDispatcherHost(IPC::Message::Sender* sender, FileSystemHostContext* file_system_host_context, - HostContentSettingsMap* host_content_settings_map); + HostContentSettingsMap* host_content_settings_map, + URLRequestContextGetter* url_request_context_getter); ~FileSystemDispatcherHost(); void Init(base::ProcessHandle process_handle); void Shutdown(); @@ -97,6 +101,11 @@ class FileSystemDispatcherHost typedef IDMap<fileapi::FileSystemOperation, IDMapOwnPointer> OperationsMap; OperationsMap operations_; + // This holds the URLRequestContextGetter until Init() can be called from the + // IO thread, which will extract the URLRequestContext from it. + scoped_refptr<URLRequestContextGetter> request_context_getter_; + scoped_refptr<URLRequestContext> request_context_; + DISALLOW_COPY_AND_ASSIGN(FileSystemDispatcherHost); }; diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc index 0e05808..a03cfe1 100644 --- a/chrome/browser/renderer_host/resource_message_filter.cc +++ b/chrome/browser/renderer_host/resource_message_filter.cc @@ -257,7 +257,8 @@ ResourceMessageFilter::ResourceMessageFilter( ALLOW_THIS_IN_INITIALIZER_LIST(file_system_dispatcher_host_( new FileSystemDispatcherHost(this, profile->GetFileSystemHostContext(), - profile->GetHostContentSettingsMap()))), + profile->GetHostContentSettingsMap(), + profile->GetRequestContext()))), ALLOW_THIS_IN_INITIALIZER_LIST(blob_dispatcher_host_( new BlobDispatcherHost( this->id(), profile->GetBlobStorageContext()))) { diff --git a/chrome/browser/worker_host/worker_process_host.cc b/chrome/browser/worker_host/worker_process_host.cc index 4532e36..12dfe2d 100644 --- a/chrome/browser/worker_host/worker_process_host.cc +++ b/chrome/browser/worker_host/worker_process_host.cc @@ -72,7 +72,8 @@ WorkerProcessHost::WorkerProcessHost( ALLOW_THIS_IN_INITIALIZER_LIST(file_system_dispatcher_host_( new FileSystemDispatcherHost(this, request_context->file_system_host_context(), - request_context->host_content_settings_map()))) { + request_context->host_content_settings_map(), + NULL /* TODO(ericu)*/))) { next_route_id_callback_.reset(NewCallbackWithReturnValue( WorkerService::GetInstance(), &WorkerService::next_worker_route_id)); db_dispatcher_host_ = new DatabaseDispatcherHost( diff --git a/chrome/common/file_system/webfilewriter_impl.cc b/chrome/common/file_system/webfilewriter_impl.cc index f579e25..6314c91 100644 --- a/chrome/common/file_system/webfilewriter_impl.cc +++ b/chrome/common/file_system/webfilewriter_impl.cc @@ -11,6 +11,44 @@ #include "third_party/WebKit/WebKit/chromium/public/WebURL.h" #include "webkit/glue/webkit_glue.h" +class WebFileWriterImpl::FileSystemCallbackDispatcherImpl : + public fileapi::FileSystemCallbackDispatcher { + public: + explicit FileSystemCallbackDispatcherImpl( + const base::WeakPtr<WebFileWriterImpl>& impl) : m_impl(impl) { + } + virtual ~FileSystemCallbackDispatcherImpl() { + } + + virtual void DidReadMetadata(const base::PlatformFileInfo&) { + NOTREACHED(); + } + virtual void DidReadDirectory( + const std::vector<base::file_util_proxy::Entry>& entries, + bool has_more) { + NOTREACHED(); + } + virtual void DidOpenFileSystem(const std::string& name, + const FilePath& root_path) { + NOTREACHED(); + } + virtual void DidSucceed() { + if (m_impl) + m_impl->DidSucceed(); + } + virtual void DidFail(base::PlatformFileError error_code) { + if (m_impl) + m_impl->DidFail(error_code); + } + virtual void DidWrite(int64 bytes, bool complete) { + if (m_impl) + m_impl->DidWrite(bytes, complete); + } + + private: + base::WeakPtr<WebFileWriterImpl> m_impl; +}; + WebFileWriterImpl::WebFileWriterImpl( const WebKit::WebString& path, WebKit::WebFileWriterClient* client) : path_(webkit_glue::WebStringToFilePath(path)), @@ -30,7 +68,9 @@ void WebFileWriterImpl::truncate( operation_ = kOperationTruncate; FileSystemDispatcher* dispatcher = ChildThread::current()->file_system_dispatcher(); - dispatcher->Truncate(path_, length, &request_id_, this); + dispatcher->Truncate( + path_, length, &request_id_, + new FileSystemCallbackDispatcherImpl(AsWeakPtr())); } void WebFileWriterImpl::write( @@ -41,7 +81,9 @@ void WebFileWriterImpl::write( operation_ = kOperationWrite; FileSystemDispatcher* dispatcher = ChildThread::current()->file_system_dispatcher(); - dispatcher->Write(path_, blob_url, position, &request_id_, this); + dispatcher->Write( + path_, blob_url, position, &request_id_, + new FileSystemCallbackDispatcherImpl(AsWeakPtr())); } // When we cancel a write/truncate, we always get back the result of the write @@ -65,15 +107,8 @@ void WebFileWriterImpl::cancel() { cancel_state_ = kCancelSent; FileSystemDispatcher* dispatcher = ChildThread::current()->file_system_dispatcher(); - dispatcher->Cancel(request_id_, this); -} - -void WebFileWriterImpl::FinishCancel() { - DCHECK(kCancelReceivedWriteResponse == cancel_state_); - DCHECK(kOperationNone != operation_); - cancel_state_ = kCancelNotInProgress; - operation_ = kOperationNone; - client_->didFail(WebKit::WebFileErrorAbort); + dispatcher->Cancel( + request_id_, new FileSystemCallbackDispatcherImpl(AsWeakPtr())); } void WebFileWriterImpl::DidSucceed() { @@ -148,3 +183,12 @@ void WebFileWriterImpl::DidWrite(int64 bytes, bool complete) { NOTREACHED(); } } + +void WebFileWriterImpl::FinishCancel() { + DCHECK(kCancelReceivedWriteResponse == cancel_state_); + DCHECK(kOperationNone != operation_); + cancel_state_ = kCancelNotInProgress; + operation_ = kOperationNone; + client_->didFail(WebKit::WebFileErrorAbort); +} + diff --git a/chrome/common/file_system/webfilewriter_impl.h b/chrome/common/file_system/webfilewriter_impl.h index 574440f..6f1c0a7 100644 --- a/chrome/common/file_system/webfilewriter_impl.h +++ b/chrome/common/file_system/webfilewriter_impl.h @@ -5,10 +5,8 @@ #ifndef CHROME_COMMON_FILE_SYSTEM_WEBFILEWRITER_IMPL_H_ #define CHROME_COMMON_FILE_SYSTEM_WEBFILEWRITER_IMPL_H_ -#include <string> -#include <vector> - #include "base/basictypes.h" +#include "base/weak_ptr.h" #include "chrome/common/file_system/file_system_dispatcher.h" #include "third_party/WebKit/WebKit/chromium/public/WebFileWriter.h" @@ -20,7 +18,7 @@ class WebURL; class WebFileWriterImpl : public WebKit::WebFileWriter, - public fileapi::FileSystemCallbackDispatcher { + public base::SupportsWeakPtr<WebFileWriterImpl> { public: WebFileWriterImpl( const WebKit::WebString& path, WebKit::WebFileWriterClient* client); @@ -31,24 +29,8 @@ class WebFileWriterImpl virtual void write(long long position, const WebKit::WebURL& blobURL); virtual void cancel(); - // FileSystemCallbackDispatcher implementation - virtual void DidReadMetadata(const base::PlatformFileInfo&) { - NOTREACHED(); - } - virtual void DidReadDirectory( - const std::vector<base::file_util_proxy::Entry>& entries, - bool has_more) { - NOTREACHED(); - } - virtual void DidOpenFileSystem(const std::string& name, - const FilePath& root_path) { - NOTREACHED(); - } - virtual void DidSucceed(); - virtual void DidFail(base::PlatformFileError error_code); - virtual void DidWrite(int64 bytes, bool complete); - private: + class FileSystemCallbackDispatcherImpl; enum OperationType { kOperationNone, kOperationWrite, @@ -61,6 +43,9 @@ class WebFileWriterImpl kCancelReceivedWriteResponse, }; + void DidSucceed(); + void DidFail(base::PlatformFileError error_code); + void DidWrite(int64 bytes, bool complete); void FinishCancel(); FilePath path_; @@ -71,4 +56,3 @@ class WebFileWriterImpl }; #endif // CHROME_COMMON_FILE_SYSTEM_WEBFILEWRITER_IMPL_H_ - diff --git a/webkit/fileapi/file_system_operation.cc b/webkit/fileapi/file_system_operation.cc index 29336a8..29690b9 100644 --- a/webkit/fileapi/file_system_operation.cc +++ b/webkit/fileapi/file_system_operation.cc @@ -5,8 +5,9 @@ #include "webkit/fileapi/file_system_operation.h" #include "base/time.h" -#include "googleurl/src/gurl.h" +#include "net/url_request/url_request_context.h" #include "webkit/fileapi/file_system_callback_dispatcher.h" +#include "webkit/fileapi/file_writer_delegate.h" namespace fileapi { @@ -24,6 +25,8 @@ FileSystemOperation::FileSystemOperation( } FileSystemOperation::~FileSystemOperation() { + if (file_writer_delegate_.get()) + base::FileUtilProxy::Close(proxy_, file_writer_delegate_->file(), NULL); } void FileSystemOperation::CreateFile(const FilePath& path, @@ -130,6 +133,7 @@ void FileSystemOperation::Remove(const FilePath& path, bool recursive) { } void FileSystemOperation::Write( + scoped_refptr<URLRequestContext> url_request_context, const FilePath& path, const GURL& blob_url, int64 offset) { @@ -137,7 +141,28 @@ void FileSystemOperation::Write( DCHECK(kOperationNone == pending_operation_); pending_operation_ = kOperationWrite; #endif - NOTREACHED(); + DCHECK(blob_url.is_valid()); + file_writer_delegate_.reset(new FileWriterDelegate(this, offset)); + blob_request_.reset(new URLRequest(blob_url, file_writer_delegate_.get())); + blob_request_->set_context(url_request_context); + base::FileUtilProxy::CreateOrOpen( + proxy_, + path, + base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE | + base::PLATFORM_FILE_ASYNC, + callback_factory_.NewCallback( + &FileSystemOperation::OnFileOpenedForWrite)); +} + +void FileSystemOperation::OnFileOpenedForWrite( + base::PlatformFileError rv, + base::PassPlatformFile file, + bool created) { + if (base::PLATFORM_FILE_OK != rv) { + dispatcher_->DidFail(rv); + return; + } + file_writer_delegate_->Start(file.ReleaseValue(), blob_request_.get()); } void FileSystemOperation::Truncate(const FilePath& path, int64 length) { @@ -166,15 +191,32 @@ void FileSystemOperation::TouchFile(const FilePath& path, // 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) { + if (file_writer_delegate_.get()) { #ifndef NDEBUG - DCHECK(kOperationTruncate == pending_operation_); - // FIXME(ericu): Cancelling for writes coming soon. + DCHECK(kOperationWrite == pending_operation_); #endif - // 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; + // Writes are done without proxying through FileUtilProxy after the initial + // opening of the PlatformFile. All state changes are done on this thread, + // so we're guaranteed to be able to shut down atomically. We do need to + // check that the file has been opened [which means the blob_request_ has + // been created], so we know how much we need to do. + if (blob_request_.get()) + // This halts any calls to file_writer_delegate_ from blob_request_. + blob_request_->Cancel(); + + // This deletes us, and by proxy deletes file_writer_delegate_ if any. + dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_ABORT); + cancel_operation->dispatcher_->DidSucceed(); + } else { +#ifndef NDEBUG + DCHECK(kOperationTruncate == pending_operation_); +#endif + // 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( diff --git a/webkit/fileapi/file_system_operation.h b/webkit/fileapi/file_system_operation.h index ba65b7d..bfa4141 100644 --- a/webkit/fileapi/file_system_operation.h +++ b/webkit/fileapi/file_system_operation.h @@ -14,16 +14,20 @@ #include "base/ref_counted.h" #include "base/scoped_callback_factory.h" #include "base/scoped_ptr.h" +#include "googleurl/src/gurl.h" namespace base { class Time; } class GURL; +class URLRequest; +class URLRequestContext; namespace fileapi { class FileSystemCallbackDispatcher; +class FileWriterDelegate; // This class is designed to serve one-time file system operation per instance. // Only one method(CreateFile, CreateDirectory, Copy, Move, DirectoryExists, @@ -58,7 +62,9 @@ class FileSystemOperation { void Remove(const FilePath& path, bool recursive); - void Write(const FilePath& path, const GURL& blob_url, int64 offset); + void Write( + scoped_refptr<URLRequestContext> url_request_context, + const FilePath& path, const GURL& blob_url, int64 offset); void Truncate(const FilePath& path, int64 length); @@ -107,10 +113,19 @@ class FileSystemOperation { void DidTouchFile(base::PlatformFileError rv); - scoped_ptr<FileSystemCallbackDispatcher> dispatcher_; + // Helper for Write(). + void OnFileOpenedForWrite( + base::PlatformFileError rv, + base::PassPlatformFile file, + bool created); + scoped_ptr<FileSystemCallbackDispatcher> dispatcher_; base::ScopedCallbackFactory<FileSystemOperation> callback_factory_; + // These are all used only by Write(). + friend class FileWriterDelegate; + scoped_ptr<FileWriterDelegate> file_writer_delegate_; + scoped_ptr<URLRequest> blob_request_; FileSystemOperation* cancel_operation_; #ifndef NDEBUG diff --git a/webkit/fileapi/file_writer_delegate.cc b/webkit/fileapi/file_writer_delegate.cc new file mode 100644 index 0000000..d84d22f32 --- /dev/null +++ b/webkit/fileapi/file_writer_delegate.cc @@ -0,0 +1,164 @@ +// Copyright (c) 2010 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 "webkit/fileapi/file_writer_delegate.h" + +#include "base/message_loop.h" +#include "net/base/net_errors.h" +#include "webkit/fileapi/file_system_operation.h" + +namespace fileapi { + +static const int kReadBufSize = 32768; + +FileWriterDelegate::FileWriterDelegate( + FileSystemOperation* file_system_operation, + int64 offset) + : file_system_operation_(file_system_operation), + file_(base::kInvalidPlatformFileValue), + offset_(offset), + bytes_read_backlog_(0), + bytes_written_(0), + bytes_read_(0), + io_buffer_(new net::IOBufferWithSize(kReadBufSize)), + callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), + method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { +} + +FileWriterDelegate::~FileWriterDelegate() { +} + +void FileWriterDelegate::Start(base::PlatformFile file, URLRequest* request) { + file_ = file; + request_ = request; + file_stream_.reset( + new net::FileStream( + file, + base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE | + base::PLATFORM_FILE_ASYNC)); + request_->Start(); +} + +void FileWriterDelegate::OnReceivedRedirect( + URLRequest* request, const GURL& new_url, bool* defer_redirect) { + NOTREACHED(); + OnError(base::PLATFORM_FILE_ERROR_SECURITY); +} + +void FileWriterDelegate::OnAuthRequired( + URLRequest* request, net::AuthChallengeInfo* auth_info) { + NOTREACHED(); + OnError(base::PLATFORM_FILE_ERROR_SECURITY); +} + +void FileWriterDelegate::OnCertificateRequested( + URLRequest* request, net::SSLCertRequestInfo* cert_request_info) { + NOTREACHED(); + OnError(base::PLATFORM_FILE_ERROR_SECURITY); +} + +void FileWriterDelegate::OnSSLCertificateError( + URLRequest* request, int cert_error, net::X509Certificate* cert) { + NOTREACHED(); + OnError(base::PLATFORM_FILE_ERROR_SECURITY); +} + +void FileWriterDelegate::OnResponseStarted(URLRequest* request) { + DCHECK_EQ(request_, request); + if (!request->status().is_success()) { + OnError(base::PLATFORM_FILE_ERROR_FAILED); + return; + } + int64 error = file_stream_->Seek(net::FROM_BEGIN, offset_); + if (error != offset_) { + OnError(base::PLATFORM_FILE_ERROR_FAILED); + return; + } + Read(); +} + +void FileWriterDelegate::OnReadCompleted(URLRequest* request, int bytes_read) { + DCHECK_EQ(request_, request); + if (!request->status().is_success()) { + OnError(base::PLATFORM_FILE_ERROR_FAILED); + return; + } + OnDataReceived(bytes_read); +} + +void FileWriterDelegate::Read() { + bytes_written_ = 0; + bytes_read_ = 0; + if (request_->Read(io_buffer_.get(), io_buffer_->size(), &bytes_read_)) { + MessageLoop::current()->PostTask( + FROM_HERE, + method_factory_.NewRunnableMethod( + &FileWriterDelegate::OnDataReceived, bytes_read_)); + } else if (!request_->status().is_io_pending()) { + OnError(base::PLATFORM_FILE_ERROR_FAILED); + } +} + +void FileWriterDelegate::OnDataReceived(int bytes_read) { + bytes_read_ = bytes_read; + if (!bytes_read_) { // We're done. + OnProgress(0, true); + } else { + // This could easily be optimized to rotate between a pool of buffers, so + // that we could read and write at the same time. It's not yet clear that + // it's necessary. + Write(); + } +} + +void FileWriterDelegate::Write() { + int write_response = file_stream_->Write( + io_buffer_->data() + bytes_written_, + bytes_read_ - bytes_written_, + callback_factory_.NewCallback(&FileWriterDelegate::OnDataWritten)); + if (write_response > 0) + MessageLoop::current()->PostTask( + FROM_HERE, + method_factory_.NewRunnableMethod( + &FileWriterDelegate::OnDataWritten, write_response)); + else if (net::ERR_IO_PENDING != write_response) + OnError(base::PLATFORM_FILE_ERROR_FAILED); +} + +void FileWriterDelegate::OnDataWritten(int write_response) { + if (write_response > 0) { + OnProgress(write_response, false); + bytes_written_ += write_response; + if (bytes_written_ == bytes_read_) + Read(); + else + Write(); + } else { + OnError(base::PLATFORM_FILE_ERROR_FAILED); + } +} + +void FileWriterDelegate::OnError(base::PlatformFileError error) { + request_->Cancel(); + file_system_operation_->DidWrite(error, 0, true); +} + +void FileWriterDelegate::OnProgress(int bytes_read, bool done) { + DCHECK(bytes_read + bytes_read_backlog_ >= bytes_read_backlog_); + static const int kMinProgressDelayMS = 200; + base::Time currentTime = base::Time::Now(); + if (done || last_progress_event_time_.is_null() || + (currentTime - last_progress_event_time_).InMilliseconds() > + kMinProgressDelayMS) { + file_system_operation_->DidWrite(base::PLATFORM_FILE_OK, + bytes_read + bytes_read_backlog_, done); + last_progress_event_time_ = currentTime; + bytes_read_backlog_ = 0; + } else { + bytes_read_backlog_ += bytes_read; + } +} + +} // namespace fileapi + diff --git a/webkit/fileapi/file_writer_delegate.h b/webkit/fileapi/file_writer_delegate.h new file mode 100644 index 0000000..ed35ce6 --- /dev/null +++ b/webkit/fileapi/file_writer_delegate.h @@ -0,0 +1,71 @@ +// Copyright (c) 2010 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. + +#ifndef WEBKIT_FILEAPI_FILE_WRITER_DELEGATE_H_ +#define WEBKIT_FILEAPI_FILE_WRITER_DELEGATE_H_ + +#include "base/file_path.h" +#include "base/platform_file.h" +#include "base/ref_counted.h" +#include "base/scoped_callback_factory.h" +#include "base/scoped_ptr.h" +#include "base/task.h" +#include "base/time.h" +#include "net/base/file_stream.h" +#include "net/base/io_buffer.h" +#include "net/url_request/url_request.h" + +namespace fileapi { + +class FileSystemOperation; + +class FileWriterDelegate : public URLRequest::Delegate { + public: + FileWriterDelegate( + FileSystemOperation* write_operation, + int64 offset); + virtual ~FileWriterDelegate(); + + void Start(base::PlatformFile file, URLRequest* request); + base::PlatformFile file() { + return file_; + } + + virtual void OnReceivedRedirect( + URLRequest* request, const GURL& new_url, bool* defer_redirect); + virtual void OnAuthRequired( + URLRequest* request, net::AuthChallengeInfo* auth_info); + virtual void OnCertificateRequested( + URLRequest* request, net::SSLCertRequestInfo* cert_request_info); + virtual void OnSSLCertificateError( + URLRequest* request, int cert_error, net::X509Certificate* cert); + virtual void OnResponseStarted(URLRequest* request); + virtual void OnReadCompleted(URLRequest* request, int bytes_read); + + private: + void Read(); + void OnDataReceived(int bytes_read); + void Write(); + void OnDataWritten(int write_response); + void OnError(base::PlatformFileError error); + void OnProgress(int bytes_read, bool done); + + FileSystemOperation* file_system_operation_; + base::PlatformFile file_; + int64 offset_; + base::Time last_progress_event_time_; + int bytes_read_backlog_; + int bytes_written_; + int bytes_read_; + scoped_refptr<net::IOBufferWithSize> io_buffer_; + scoped_ptr<net::FileStream> file_stream_; + URLRequest* request_; + base::ScopedCallbackFactory<FileWriterDelegate> callback_factory_; + ScopedRunnableMethodFactory<FileWriterDelegate> method_factory_; +}; + +} // namespace fileapi + +#endif // WEBKIT_FILEAPI_FILE_WRITER_DELEGATE_H_ + diff --git a/webkit/fileapi/webkit_fileapi.gypi b/webkit/fileapi/webkit_fileapi.gypi index b94cf9e..a795da4 100644 --- a/webkit/fileapi/webkit_fileapi.gypi +++ b/webkit/fileapi/webkit_fileapi.gypi @@ -18,6 +18,8 @@ 'file_system_operation.cc', 'file_system_operation.h', 'file_system_types.h', + 'file_writer_delegate.cc', + 'file_writer_delegate.h', ], 'conditions': [ ['inside_chromium_build==0', { |