Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(519)

Unified Diff: content/browser/renderer_host/redirect_to_file_resource_handler.cc

Issue 11414299: Add content/browser/loader/ for resource loading related classes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/renderer_host/redirect_to_file_resource_handler.cc
===================================================================
--- content/browser/renderer_host/redirect_to_file_resource_handler.cc (revision 171168)
+++ content/browser/renderer_host/redirect_to_file_resource_handler.cc (working copy)
@@ -1,268 +0,0 @@
-// Copyright (c) 2012 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 "content/browser/renderer_host/redirect_to_file_resource_handler.h"
-
-#include "base/bind.h"
-#include "base/file_util.h"
-#include "base/file_util_proxy.h"
-#include "base/logging.h"
-#include "base/message_loop_proxy.h"
-#include "base/platform_file.h"
-#include "base/threading/thread_restrictions.h"
-#include "content/browser/renderer_host/resource_dispatcher_host_impl.h"
-#include "content/public/common/resource_response.h"
-#include "net/base/file_stream.h"
-#include "net/base/io_buffer.h"
-#include "net/base/mime_sniffer.h"
-#include "net/base/net_errors.h"
-#include "webkit/blob/shareable_file_reference.h"
-
-using webkit_blob::ShareableFileReference;
-
-namespace {
-
-// This class is similar to identically named classes in AsyncResourceHandler
-// and BufferedResourceHandler, but not quite.
-// TODO(ncbray) generalize and unify these cases?
-// In general, it's a bad idea to point to a subbuffer (particularly with
-// GrowableIOBuffer) because the backing IOBuffer may realloc its data. In this
-// particular case we know RedirectToFileResourceHandler will not realloc its
-// buffer while a write is occurring, so we should be safe. This property is
-// somewhat fragile, however, and depending on it is dangerous. A more
-// principled approach would require significant refactoring, however, so for
-// the moment we're relying on fragile properties.
-class DependentIOBuffer : public net::WrappedIOBuffer {
- public:
- DependentIOBuffer(net::IOBuffer* backing, char* memory)
- : net::WrappedIOBuffer(memory),
- backing_(backing) {
- }
- private:
- virtual ~DependentIOBuffer() {}
-
- scoped_refptr<net::IOBuffer> backing_;
-};
-
-}
-
-namespace content {
-
-static const int kInitialReadBufSize = 32768;
-static const int kMaxReadBufSize = 524288;
-
-RedirectToFileResourceHandler::RedirectToFileResourceHandler(
- scoped_ptr<ResourceHandler> next_handler,
- int process_id,
- ResourceDispatcherHostImpl* host)
- : LayeredResourceHandler(next_handler.Pass()),
- ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
- host_(host),
- process_id_(process_id),
- request_id_(-1),
- 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) {
-}
-
-RedirectToFileResourceHandler::~RedirectToFileResourceHandler() {
-}
-
-bool RedirectToFileResourceHandler::OnResponseStarted(
- int request_id,
- ResourceResponse* response,
- bool* defer) {
- if (response->head.error_code == net::OK ||
- response->head.error_code == net::ERR_IO_PENDING) {
- DCHECK(deletable_file_ && !deletable_file_->path().empty());
- response->head.download_file_path = deletable_file_->path();
- }
- return next_handler_->OnResponseStarted(request_id, response, defer);
-}
-
-bool RedirectToFileResourceHandler::OnWillStart(int request_id,
- const GURL& url,
- bool* defer) {
- request_id_ = request_id;
- if (!deletable_file_) {
- // 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.
- did_defer_ = *defer = true;
- base::FileUtilProxy::CreateTemporary(
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
- base::PLATFORM_FILE_ASYNC,
- base::Bind(&RedirectToFileResourceHandler::DidCreateTemporaryFile,
- weak_factory_.GetWeakPtr()));
- return true;
- }
- return next_handler_->OnWillStart(request_id, url, defer);
-}
-
-bool RedirectToFileResourceHandler::OnWillRead(int request_id,
- net::IOBuffer** buf,
- int* buf_size,
- int min_size) {
- DCHECK_EQ(-1, min_size);
-
- if (buf_->capacity() < next_buffer_size_)
- buf_->SetCapacity(next_buffer_size_);
-
- // We should have paused this network request already if the buffer is full.
- DCHECK(!BufIsFull());
-
- *buf = buf_;
- *buf_size = buf_->RemainingCapacity();
-
- buf_write_pending_ = true;
- return true;
-}
-
-bool RedirectToFileResourceHandler::OnReadCompleted(int request_id,
- int bytes_read,
- bool* defer) {
- DCHECK(buf_write_pending_);
- buf_write_pending_ = false;
-
- // We use the buffer's offset field to record the end of the buffer.
- int new_offset = buf_->offset() + bytes_read;
- DCHECK(new_offset <= buf_->capacity());
- buf_->set_offset(new_offset);
-
- if (BufIsFull()) {
- did_defer_ = *defer = true;
-
- if (buf_->capacity() == bytes_read) {
- // The network layer has saturated our buffer in one read. Next time, we
- // should give it a bigger buffer for it to fill.
- next_buffer_size_ = std::min(next_buffer_size_ * 2, kMaxReadBufSize);
- }
- }
-
- return WriteMore();
-}
-
-bool RedirectToFileResourceHandler::OnResponseCompleted(
- int request_id,
- const net::URLRequestStatus& status,
- const std::string& security_info) {
- if (write_callback_pending_) {
- completed_during_write_ = true;
- completed_status_ = status;
- completed_security_info_ = security_info;
- return false;
- }
- return next_handler_->OnResponseCompleted(request_id, status, security_info);
-}
-
-void RedirectToFileResourceHandler::DidCreateTemporaryFile(
- base::PlatformFileError /*error_code*/,
- base::PassPlatformFile file_handle,
- const FilePath& file_path) {
- deletable_file_ = ShareableFileReference::GetOrCreate(
- file_path, ShareableFileReference::DELETE_ON_FINAL_RELEASE,
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
- file_stream_.reset(new net::FileStream(file_handle.ReleaseValue(),
- base::PLATFORM_FILE_WRITE |
- base::PLATFORM_FILE_ASYNC,
- NULL));
- host_->RegisterDownloadedTempFile(
- process_id_, request_id_, deletable_file_.get());
- ResumeIfDeferred();
-}
-
-void RedirectToFileResourceHandler::DidWriteToFile(int result) {
- write_callback_pending_ = false;
-
- bool failed = false;
- if (result > 0) {
- next_handler_->OnDataDownloaded(request_id_, result);
- write_cursor_ += result;
- failed = !WriteMore();
- } else {
- failed = true;
- }
-
- if (failed) {
- ResumeIfDeferred();
- } else if (completed_during_write_) {
- if (next_handler_->OnResponseCompleted(request_id_, completed_status_,
- completed_security_info_)) {
- ResumeIfDeferred();
- }
- }
-}
-
-bool RedirectToFileResourceHandler::WriteMore() {
- DCHECK(file_stream_.get());
- for (;;) {
- if (write_cursor_ == buf_->offset()) {
- // We've caught up to the network load, but it may be in the process of
- // appending more data to the buffer.
- if (!buf_write_pending_) {
- if (BufIsFull())
- ResumeIfDeferred();
- buf_->set_offset(0);
- write_cursor_ = 0;
- }
- return true;
- }
- if (write_callback_pending_)
- return true;
- DCHECK(write_cursor_ < buf_->offset());
-
- // Create a temporary buffer pointing to a subsection of the data buffer so
- // that it can be passed to Write. This code makes some crazy scary
- // assumptions about object lifetimes, thread sharing, and that buf_ will
- // not realloc durring the write due to how the state machine in this class
- // works.
- // Note that buf_ is also shared with the code that writes data into the
- // cache, so modifying it can cause some pretty subtle race conditions:
- // https://code.google.com/p/chromium/issues/detail?id=152076
- // We're using DependentIOBuffer instead of DrainableIOBuffer to dodge some
- // of these issues, for the moment.
- // TODO(ncbray) make this code less crazy scary.
- // Also note that Write may increase the refcount of "wrapped" deep in the
- // bowels of its implementation, the use of scoped_refptr here is not
- // spurious.
- scoped_refptr<DependentIOBuffer> wrapped = new DependentIOBuffer(
- buf_, buf_->StartOfBuffer() + write_cursor_);
- int write_len = buf_->offset() - write_cursor_;
-
- int rv = file_stream_->Write(
- wrapped,
- write_len,
- base::Bind(&RedirectToFileResourceHandler::DidWriteToFile,
- base::Unretained(this)));
- if (rv == net::ERR_IO_PENDING) {
- write_callback_pending_ = true;
- return true;
- }
- if (rv <= 0)
- return false;
- next_handler_->OnDataDownloaded(request_id_, rv);
- write_cursor_ += rv;
- }
-}
-
-bool RedirectToFileResourceHandler::BufIsFull() const {
- // This is a hack to workaround BufferedResourceHandler's inability to
- // deal with a ResourceHandler that returns a buffer size of less than
- // 2 * net::kMaxBytesToSniff from its OnWillRead method.
- // TODO(darin): Fix this retardation!
- return buf_->RemainingCapacity() <= (2 * net::kMaxBytesToSniff);
-}
-
-void RedirectToFileResourceHandler::ResumeIfDeferred() {
- if (did_defer_) {
- did_defer_ = false;
- controller()->Resume();
- }
-}
-
-} // namespace content

Powered by Google App Engine
This is Rietveld 408576698