| Index: content/browser/renderer_host/async_resource_handler.cc
|
| ===================================================================
|
| --- content/browser/renderer_host/async_resource_handler.cc (revision 170763)
|
| +++ content/browser/renderer_host/async_resource_handler.cc (working copy)
|
| @@ -1,345 +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/async_resource_handler.h"
|
| -
|
| -#include <algorithm>
|
| -#include <vector>
|
| -
|
| -#include "base/command_line.h"
|
| -#include "base/debug/alias.h"
|
| -#include "base/hash_tables.h"
|
| -#include "base/logging.h"
|
| -#include "base/metrics/histogram.h"
|
| -#include "base/shared_memory.h"
|
| -#include "base/string_number_conversions.h"
|
| -#include "content/browser/debugger/devtools_netlog_observer.h"
|
| -#include "content/browser/host_zoom_map_impl.h"
|
| -#include "content/browser/renderer_host/resource_buffer.h"
|
| -#include "content/browser/renderer_host/resource_dispatcher_host_impl.h"
|
| -#include "content/browser/renderer_host/resource_message_filter.h"
|
| -#include "content/browser/renderer_host/resource_request_info_impl.h"
|
| -#include "content/browser/resource_context_impl.h"
|
| -#include "content/common/resource_messages.h"
|
| -#include "content/common/view_messages.h"
|
| -#include "content/public/browser/global_request_id.h"
|
| -#include "content/public/browser/resource_dispatcher_host_delegate.h"
|
| -#include "content/public/common/resource_response.h"
|
| -#include "net/base/io_buffer.h"
|
| -#include "net/base/load_flags.h"
|
| -#include "net/base/net_log.h"
|
| -#include "net/base/net_util.h"
|
| -#include "webkit/glue/resource_loader_bridge.h"
|
| -
|
| -using base::TimeTicks;
|
| -
|
| -namespace content {
|
| -namespace {
|
| -
|
| -static int kBufferSize = 1024 * 512;
|
| -static int kMinAllocationSize = 1024 * 4;
|
| -static int kMaxAllocationSize = 1024 * 32;
|
| -
|
| -void GetNumericArg(const std::string& name, int* result) {
|
| - const std::string& value =
|
| - CommandLine::ForCurrentProcess()->GetSwitchValueASCII(name);
|
| - if (!value.empty())
|
| - base::StringToInt(value, result);
|
| -}
|
| -
|
| -void InitializeResourceBufferConstants() {
|
| - static bool did_init = false;
|
| - if (did_init)
|
| - return;
|
| - did_init = true;
|
| -
|
| - GetNumericArg("resource-buffer-size", &kBufferSize);
|
| - GetNumericArg("resource-buffer-min-allocation-size", &kMinAllocationSize);
|
| - GetNumericArg("resource-buffer-max-allocation-size", &kMaxAllocationSize);
|
| -}
|
| -
|
| -int CalcUsedPercentage(int bytes_read, int buffer_size) {
|
| - double ratio = static_cast<double>(bytes_read) / buffer_size;
|
| - return static_cast<int>(ratio * 100.0 + 0.5); // Round to nearest integer.
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -class DependentIOBuffer : public net::WrappedIOBuffer {
|
| - public:
|
| - DependentIOBuffer(ResourceBuffer* backing, char* memory)
|
| - : net::WrappedIOBuffer(memory),
|
| - backing_(backing) {
|
| - }
|
| - private:
|
| - ~DependentIOBuffer() {}
|
| - scoped_refptr<ResourceBuffer> backing_;
|
| -};
|
| -
|
| -AsyncResourceHandler::AsyncResourceHandler(
|
| - ResourceMessageFilter* filter,
|
| - int routing_id,
|
| - net::URLRequest* request,
|
| - ResourceDispatcherHostImpl* rdh)
|
| - : filter_(filter),
|
| - routing_id_(routing_id),
|
| - request_(request),
|
| - rdh_(rdh),
|
| - pending_data_count_(0),
|
| - allocation_size_(0),
|
| - did_defer_(false),
|
| - sent_received_response_msg_(false),
|
| - sent_first_data_msg_(false) {
|
| - // Set a back-pointer from ResourceRequestInfoImpl to |this|, so that the
|
| - // ResourceDispatcherHostImpl can send us IPC messages.
|
| - // TODO(darin): Implement an IPC message filter instead?
|
| - ResourceRequestInfoImpl::ForRequest(request_)->set_async_handler(this);
|
| -
|
| - InitializeResourceBufferConstants();
|
| -}
|
| -
|
| -AsyncResourceHandler::~AsyncResourceHandler() {
|
| - // Cleanup back-pointer stored on the request info.
|
| - ResourceRequestInfoImpl::ForRequest(request_)->set_async_handler(NULL);
|
| -}
|
| -
|
| -void AsyncResourceHandler::OnFollowRedirect(
|
| - bool has_new_first_party_for_cookies,
|
| - const GURL& new_first_party_for_cookies) {
|
| - if (!request_->status().is_success()) {
|
| - DVLOG(1) << "OnFollowRedirect for invalid request";
|
| - return;
|
| - }
|
| -
|
| - if (has_new_first_party_for_cookies)
|
| - request_->set_first_party_for_cookies(new_first_party_for_cookies);
|
| -
|
| - ResumeIfDeferred();
|
| -}
|
| -
|
| -void AsyncResourceHandler::OnDataReceivedACK() {
|
| - --pending_data_count_;
|
| -
|
| - buffer_->RecycleLeastRecentlyAllocated();
|
| - if (buffer_->CanAllocate())
|
| - ResumeIfDeferred();
|
| -}
|
| -
|
| -bool AsyncResourceHandler::OnUploadProgress(int request_id,
|
| - uint64 position,
|
| - uint64 size) {
|
| - return filter_->Send(new ResourceMsg_UploadProgress(routing_id_, request_id,
|
| - position, size));
|
| -}
|
| -
|
| -bool AsyncResourceHandler::OnRequestRedirected(int request_id,
|
| - const GURL& new_url,
|
| - ResourceResponse* response,
|
| - bool* defer) {
|
| - *defer = did_defer_ = true;
|
| -
|
| - if (rdh_->delegate()) {
|
| - rdh_->delegate()->OnRequestRedirected(new_url, request_,
|
| - filter_->resource_context(),
|
| - response);
|
| - }
|
| -
|
| - DevToolsNetLogObserver::PopulateResponseInfo(request_, response);
|
| - response->head.request_start = request_->creation_time();
|
| - response->head.response_start = TimeTicks::Now();
|
| - return filter_->Send(new ResourceMsg_ReceivedRedirect(
|
| - routing_id_, request_id, new_url, response->head));
|
| -}
|
| -
|
| -bool AsyncResourceHandler::OnResponseStarted(int request_id,
|
| - ResourceResponse* response,
|
| - bool* defer) {
|
| - // For changes to the main frame, inform the renderer of the new URL's
|
| - // per-host settings before the request actually commits. This way the
|
| - // renderer will be able to set these precisely at the time the
|
| - // request commits, avoiding the possibility of e.g. zooming the old content
|
| - // or of having to layout the new content twice.
|
| -
|
| - ResourceContext* resource_context = filter_->resource_context();
|
| - if (rdh_->delegate()) {
|
| - rdh_->delegate()->OnResponseStarted(request_, resource_context, response,
|
| - filter_);
|
| - }
|
| -
|
| - DevToolsNetLogObserver::PopulateResponseInfo(request_, response);
|
| -
|
| - HostZoomMap* host_zoom_map =
|
| - GetHostZoomMapForResourceContext(resource_context);
|
| -
|
| - const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
|
| - if (info->GetResourceType() == ResourceType::MAIN_FRAME && host_zoom_map) {
|
| - const GURL& request_url = request_->url();
|
| - filter_->Send(new ViewMsg_SetZoomLevelForLoadingURL(
|
| - info->GetRouteID(),
|
| - request_url, host_zoom_map->GetZoomLevel(net::GetHostOrSpecFromURL(
|
| - request_url))));
|
| - }
|
| -
|
| - response->head.request_start = request_->creation_time();
|
| - response->head.response_start = TimeTicks::Now();
|
| - filter_->Send(new ResourceMsg_ReceivedResponse(
|
| - routing_id_, request_id, response->head));
|
| - sent_received_response_msg_ = true;
|
| -
|
| - if (request_->response_info().metadata) {
|
| - std::vector<char> copy(request_->response_info().metadata->data(),
|
| - request_->response_info().metadata->data() +
|
| - request_->response_info().metadata->size());
|
| - filter_->Send(new ResourceMsg_ReceivedCachedMetadata(
|
| - routing_id_, request_id, copy));
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool AsyncResourceHandler::OnWillStart(int request_id,
|
| - const GURL& url,
|
| - bool* defer) {
|
| - return true;
|
| -}
|
| -
|
| -bool AsyncResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf,
|
| - int* buf_size, int min_size) {
|
| - DCHECK_EQ(-1, min_size);
|
| -
|
| - if (!EnsureResourceBufferIsInitialized())
|
| - return false;
|
| -
|
| - DCHECK(buffer_->CanAllocate());
|
| - char* memory = buffer_->Allocate(&allocation_size_);
|
| - CHECK(memory);
|
| -
|
| - *buf = new DependentIOBuffer(buffer_, memory);
|
| - *buf_size = allocation_size_;
|
| -
|
| - UMA_HISTOGRAM_CUSTOM_COUNTS(
|
| - "Net.AsyncResourceHandler_SharedIOBuffer_Alloc",
|
| - *buf_size, 0, kMaxAllocationSize, 100);
|
| - return true;
|
| -}
|
| -
|
| -bool AsyncResourceHandler::OnReadCompleted(int request_id, int bytes_read,
|
| - bool* defer) {
|
| - if (!bytes_read)
|
| - return true;
|
| -
|
| - buffer_->ShrinkLastAllocation(bytes_read);
|
| -
|
| - UMA_HISTOGRAM_CUSTOM_COUNTS(
|
| - "Net.AsyncResourceHandler_SharedIOBuffer_Used",
|
| - bytes_read, 0, kMaxAllocationSize, 100);
|
| - UMA_HISTOGRAM_PERCENTAGE(
|
| - "Net.AsyncResourceHandler_SharedIOBuffer_UsedPercentage",
|
| - CalcUsedPercentage(bytes_read, allocation_size_));
|
| -
|
| - if (!sent_first_data_msg_) {
|
| - base::SharedMemoryHandle handle;
|
| - int size;
|
| - if (!buffer_->ShareToProcess(filter_->peer_handle(), &handle, &size))
|
| - return false;
|
| - filter_->Send(
|
| - new ResourceMsg_SetDataBuffer(routing_id_, request_id, handle, size));
|
| - sent_first_data_msg_ = true;
|
| - }
|
| -
|
| - int data_offset = buffer_->GetLastAllocationOffset();
|
| - int encoded_data_length =
|
| - DevToolsNetLogObserver::GetAndResetEncodedDataLength(request_);
|
| -
|
| - filter_->Send(
|
| - new ResourceMsg_DataReceived(routing_id_, request_id, data_offset,
|
| - bytes_read, encoded_data_length));
|
| - ++pending_data_count_;
|
| - UMA_HISTOGRAM_CUSTOM_COUNTS(
|
| - "Net.AsyncResourceHandler_PendingDataCount",
|
| - pending_data_count_, 0, 100, 100);
|
| -
|
| - if (!buffer_->CanAllocate()) {
|
| - UMA_HISTOGRAM_CUSTOM_COUNTS(
|
| - "Net.AsyncResourceHandler_PendingDataCount_WhenFull",
|
| - pending_data_count_, 0, 100, 100);
|
| - *defer = did_defer_ = true;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -void AsyncResourceHandler::OnDataDownloaded(
|
| - int request_id, int bytes_downloaded) {
|
| - filter_->Send(new ResourceMsg_DataDownloaded(
|
| - routing_id_, request_id, bytes_downloaded));
|
| -}
|
| -
|
| -bool AsyncResourceHandler::OnResponseCompleted(
|
| - int request_id,
|
| - const net::URLRequestStatus& status,
|
| - const std::string& security_info) {
|
| - // If we crash here, figure out what URL the renderer was requesting.
|
| - // http://crbug.com/107692
|
| - char url_buf[128];
|
| - base::strlcpy(url_buf, request_->url().spec().c_str(), arraysize(url_buf));
|
| - base::debug::Alias(url_buf);
|
| -
|
| - // TODO(gavinp): Remove this CHECK when we figure out the cause of
|
| - // http://crbug.com/124680 . This check mirrors closely check in
|
| - // WebURLLoaderImpl::OnCompletedRequest that routes this message to a WebCore
|
| - // ResourceHandleInternal which asserts on its state and crashes. By crashing
|
| - // when the message is sent, we should get better crash reports.
|
| - CHECK(status.status() != net::URLRequestStatus::SUCCESS ||
|
| - sent_received_response_msg_);
|
| -
|
| - TimeTicks completion_time = TimeTicks::Now();
|
| -
|
| - int error_code = status.error();
|
| - bool was_ignored_by_handler =
|
| - ResourceRequestInfoImpl::ForRequest(request_)->WasIgnoredByHandler();
|
| -
|
| - DCHECK(status.status() != net::URLRequestStatus::IO_PENDING);
|
| - // If this check fails, then we're in an inconsistent state because all
|
| - // requests ignored by the handler should be canceled (which should result in
|
| - // the ERR_ABORTED error code).
|
| - DCHECK(!was_ignored_by_handler || error_code == net::ERR_ABORTED);
|
| -
|
| - // TODO(mkosiba): Fix up cases where we create a URLRequestStatus
|
| - // with a status() != SUCCESS and an error_code() == net::OK.
|
| - if (status.status() == net::URLRequestStatus::CANCELED &&
|
| - error_code == net::OK) {
|
| - error_code = net::ERR_ABORTED;
|
| - } else if (status.status() == net::URLRequestStatus::FAILED &&
|
| - error_code == net::OK) {
|
| - error_code = net::ERR_FAILED;
|
| - }
|
| -
|
| - filter_->Send(new ResourceMsg_RequestComplete(routing_id_,
|
| - request_id,
|
| - error_code,
|
| - was_ignored_by_handler,
|
| - security_info,
|
| - completion_time));
|
| - return true;
|
| -}
|
| -
|
| -bool AsyncResourceHandler::EnsureResourceBufferIsInitialized() {
|
| - if (buffer_ && buffer_->IsInitialized())
|
| - return true;
|
| -
|
| - buffer_ = new ResourceBuffer();
|
| - return buffer_->Initialize(kBufferSize,
|
| - kMinAllocationSize,
|
| - kMaxAllocationSize);
|
| -}
|
| -
|
| -void AsyncResourceHandler::ResumeIfDeferred() {
|
| - if (did_defer_) {
|
| - did_defer_ = false;
|
| - controller()->Resume();
|
| - }
|
| -}
|
| -
|
| -} // namespace content
|
|
|