Index: content/browser/loader/redirect_to_file_resource_handler.cc |
diff --git a/content/browser/loader/redirect_to_file_resource_handler.cc b/content/browser/loader/redirect_to_file_resource_handler.cc |
index 06f9216e3751226117cfa74c8554238dab8730ac..1b98f1cce41f977184a7fa602ace4992db38e1d2 100644 |
--- a/content/browser/loader/redirect_to_file_resource_handler.cc |
+++ b/content/browser/loader/redirect_to_file_resource_handler.cc |
@@ -5,14 +5,11 @@ |
#include "content/browser/loader/redirect_to_file_resource_handler.h" |
#include "base/bind.h" |
-#include "base/files/file_util_proxy.h" |
#include "base/logging.h" |
-#include "base/message_loop/message_loop_proxy.h" |
#include "base/platform_file.h" |
#include "base/threading/thread_restrictions.h" |
-#include "content/browser/loader/resource_dispatcher_host_impl.h" |
#include "content/browser/loader/resource_request_info_impl.h" |
-#include "content/public/browser/browser_thread.h" |
+#include "content/public/browser/resource_controller.h" |
#include "content/public/common/resource_response.h" |
#include "net/base/file_stream.h" |
#include "net/base/io_buffer.h" |
@@ -56,17 +53,17 @@ static const int kMaxReadBufSize = 524288; |
RedirectToFileResourceHandler::RedirectToFileResourceHandler( |
scoped_ptr<ResourceHandler> next_handler, |
net::URLRequest* request, |
- ResourceDispatcherHostImpl* host) |
+ TemporaryFileStreamFactory* file_stream_factory) |
: LayeredResourceHandler(request, next_handler.Pass()), |
- weak_factory_(this), |
- host_(host), |
+ file_stream_factory_(file_stream_factory), |
buf_(new net::GrowableIOBuffer()), |
buf_write_pending_(false), |
write_cursor_(0), |
write_callback_pending_(false), |
next_buffer_size_(kInitialReadBufSize), |
did_defer_(false), |
- completed_during_write_(false) { |
+ completed_during_write_(false), |
+ weak_factory_(this) { |
} |
RedirectToFileResourceHandler::~RedirectToFileResourceHandler() { |
@@ -91,10 +88,11 @@ bool RedirectToFileResourceHandler::OnWillStart(int request_id, |
// Defer starting the request until we have created the temporary file. |
// TODO(darin): This is sub-optimal. We should not delay starting the |
// network request like this. |
+ will_start_url_ = url; |
did_defer_ = *defer = true; |
- base::FileUtilProxy::CreateTemporary( |
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE).get(), |
- base::PLATFORM_FILE_ASYNC, |
+ const ResourceRequestInfo* info = GetRequestInfo(); |
+ file_stream_factory_->CreateTemporary( |
+ info->GetChildID(), info->GetRequestID(), |
base::Bind(&RedirectToFileResourceHandler::DidCreateTemporaryFile, |
weak_factory_.GetWeakPtr())); |
return true; |
@@ -155,28 +153,32 @@ void RedirectToFileResourceHandler::OnResponseCompleted( |
completed_during_write_ = true; |
completed_status_ = status; |
completed_security_info_ = security_info; |
- *defer = true; |
+ did_defer_ = *defer = true; |
return; |
} |
next_handler_->OnResponseCompleted(request_id, status, security_info, defer); |
} |
void RedirectToFileResourceHandler::DidCreateTemporaryFile( |
- base::PlatformFileError /*error_code*/, |
- base::PassPlatformFile file_handle, |
- const base::FilePath& file_path) { |
- deletable_file_ = ShareableFileReference::GetOrCreate( |
- file_path, |
- ShareableFileReference::DELETE_ON_FINAL_RELEASE, |
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE).get()); |
- file_stream_.reset( |
- new net::FileStream(file_handle.ReleaseValue(), |
- base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC, |
- NULL)); |
- const ResourceRequestInfo* info = GetRequestInfo(); |
- host_->RegisterDownloadedTempFile( |
- info->GetChildID(), info->GetRequestID(), deletable_file_.get()); |
- ResumeIfDeferred(); |
+ base::PlatformFileError error_code, |
+ scoped_ptr<net::FileStream> file_stream, |
+ scoped_refptr<ShareableFileReference> deletable_file) { |
+ if (error_code != base::PLATFORM_FILE_OK) { |
+ controller()->CancelWithError(net::PlatformFileErrorToNetError(error_code)); |
+ return; |
+ } |
+ |
+ deletable_file_ = deletable_file; |
+ file_stream_ = file_stream.Pass(); |
+ |
+ // Resume the request. |
+ bool defer = false; |
+ if (!next_handler_->OnWillStart(GetRequestID(), will_start_url_, &defer)) { |
+ controller()->Cancel(); |
+ } else if (!defer) { |
+ ResumeIfDeferred(); |
+ } |
+ will_start_url_ = GURL(); |
} |
void RedirectToFileResourceHandler::DidWriteToFile(int result) { |
@@ -193,8 +195,21 @@ void RedirectToFileResourceHandler::DidWriteToFile(int result) { |
} |
if (failed) { |
- ResumeIfDeferred(); |
- } else if (completed_during_write_) { |
+ // TODO(davidben): Recover the error code from WriteMore or |result|, as |
+ // appropriate. |
+ if (completed_during_write_ && completed_status_.is_success()) { |
+ // If the request successfully completed mid-write, but the write failed, |
+ // convert the status to a failure for downstream. |
+ completed_status_.set_status(net::URLRequestStatus::CANCELED); |
+ completed_status_.set_error(net::ERR_FAILED); |
+ } |
+ controller()->CancelWithError(net::ERR_FAILED); |
+ } |
+ |
+ if (completed_during_write_ && !write_callback_pending_) { |
+ // Resume shutdown now that all data has been written to disk. Note that |
+ // this should run even in the |failed| case above, otherwise a failed write |
+ // leaves the handler stuck. |
bool defer = false; |
next_handler_->OnResponseCompleted(request_id, |
completed_status_, |