diff options
author | darin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-05 08:02:44 +0000 |
---|---|---|
committer | darin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-05 08:02:44 +0000 |
commit | 678c036ef6be9f5e845f2e75a8b1bbd76985768d (patch) | |
tree | 2f012f324cc9a61c682fc730113e2834534ddb4e /content/browser/renderer_host | |
parent | 4eaa59bf61b134d79cedd565c0ab015dc18b75cd (diff) | |
download | chromium_src-678c036ef6be9f5e845f2e75a8b1bbd76985768d.zip chromium_src-678c036ef6be9f5e845f2e75a8b1bbd76985768d.tar.gz chromium_src-678c036ef6be9f5e845f2e75a8b1bbd76985768d.tar.bz2 |
Add content/browser/loader/ for resource loading related classes.
This infrastructure is shared by both renderer and worker processes, so having
it live in renderer_host/ was not quite right. This change also nicely reduces
the number of files in renderer_host/.
R=jam@chromium.org
Review URL: https://codereview.chromium.org/11414299
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@171194 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/renderer_host')
41 files changed, 7 insertions, 9155 deletions
diff --git a/content/browser/renderer_host/async_resource_handler.cc b/content/browser/renderer_host/async_resource_handler.cc deleted file mode 100644 index 8c77c27..0000000 --- a/content/browser/renderer_host/async_resource_handler.cc +++ /dev/null @@ -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 diff --git a/content/browser/renderer_host/async_resource_handler.h b/content/browser/renderer_host/async_resource_handler.h deleted file mode 100644 index 11c504f..0000000 --- a/content/browser/renderer_host/async_resource_handler.h +++ /dev/null @@ -1,91 +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. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_ASYNC_RESOURCE_HANDLER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_ASYNC_RESOURCE_HANDLER_H_ - -#include <string> - -#include "content/browser/renderer_host/resource_handler.h" -#include "googleurl/src/gurl.h" - -namespace net { -class URLRequest; -} - -namespace content { -class ResourceBuffer; -class ResourceDispatcherHostImpl; -class ResourceMessageFilter; -class SharedIOBuffer; - -// Used to complete an asynchronous resource request in response to resource -// load events from the resource dispatcher host. -class AsyncResourceHandler : public ResourceHandler { - public: - AsyncResourceHandler(ResourceMessageFilter* filter, - int routing_id, - net::URLRequest* request, - ResourceDispatcherHostImpl* rdh); - virtual ~AsyncResourceHandler(); - - // IPC message handlers: - void OnFollowRedirect(bool has_new_first_party_for_cookies, - const GURL& new_first_party_for_cookies); - void OnDataReceivedACK(); - - // ResourceHandler implementation: - virtual bool OnUploadProgress(int request_id, - uint64 position, - uint64 size) OVERRIDE; - virtual bool OnRequestRedirected(int request_id, - const GURL& new_url, - ResourceResponse* response, - bool* defer) OVERRIDE; - virtual bool OnResponseStarted(int request_id, - ResourceResponse* response, - bool* defer) OVERRIDE; - virtual bool OnWillStart(int request_id, - const GURL& url, - bool* defer) OVERRIDE; - virtual bool OnWillRead(int request_id, - net::IOBuffer** buf, - int* buf_size, - int min_size) OVERRIDE; - virtual bool OnReadCompleted(int request_id, - int bytes_read, - bool* defer) OVERRIDE; - virtual bool OnResponseCompleted(int request_id, - const net::URLRequestStatus& status, - const std::string& security_info) OVERRIDE; - virtual void OnDataDownloaded(int request_id, - int bytes_downloaded) OVERRIDE; - - private: - bool EnsureResourceBufferIsInitialized(); - void ResumeIfDeferred(); - - scoped_refptr<ResourceBuffer> buffer_; - scoped_refptr<ResourceMessageFilter> filter_; - int routing_id_; - net::URLRequest* request_; - ResourceDispatcherHostImpl* rdh_; - - // Number of messages we've sent to the renderer that we haven't gotten an - // ACK for. This allows us to avoid having too many messages in flight. - int pending_data_count_; - - int allocation_size_; - - bool did_defer_; - - bool sent_received_response_msg_; - bool sent_first_data_msg_; - - DISALLOW_COPY_AND_ASSIGN(AsyncResourceHandler); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_ASYNC_RESOURCE_HANDLER_H_ diff --git a/content/browser/renderer_host/buffered_resource_handler.cc b/content/browser/renderer_host/buffered_resource_handler.cc deleted file mode 100644 index f6d205b..0000000 --- a/content/browser/renderer_host/buffered_resource_handler.cc +++ /dev/null @@ -1,462 +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/buffered_resource_handler.h" - -#include <vector> - -#include "base/bind.h" -#include "base/logging.h" -#include "base/metrics/histogram.h" -#include "base/string_util.h" -#include "content/browser/download/download_resource_handler.h" -#include "content/browser/download/download_stats.h" -#include "content/browser/plugin_service_impl.h" -#include "content/browser/renderer_host/resource_dispatcher_host_impl.h" -#include "content/browser/renderer_host/resource_request_info_impl.h" -#include "content/browser/renderer_host/x509_user_cert_resource_handler.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/content_browser_client.h" -#include "content/public/browser/download_save_info.h" -#include "content/public/browser/resource_context.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/mime_sniffer.h" -#include "net/base/mime_util.h" -#include "net/base/net_errors.h" -#include "net/http/http_content_disposition.h" -#include "net/http/http_response_headers.h" -#include "webkit/plugins/webplugininfo.h" - -namespace content { - -namespace { - -void RecordSnifferMetrics(bool sniffing_blocked, - bool we_would_like_to_sniff, - const std::string& mime_type) { - static base::Histogram* nosniff_usage(NULL); - if (!nosniff_usage) - nosniff_usage = base::BooleanHistogram::FactoryGet( - "nosniff.usage", base::Histogram::kUmaTargetedHistogramFlag); - nosniff_usage->AddBoolean(sniffing_blocked); - - if (sniffing_blocked) { - static base::Histogram* nosniff_otherwise(NULL); - if (!nosniff_otherwise) - nosniff_otherwise = base::BooleanHistogram::FactoryGet( - "nosniff.otherwise", base::Histogram::kUmaTargetedHistogramFlag); - nosniff_otherwise->AddBoolean(we_would_like_to_sniff); - - static base::Histogram* nosniff_empty_mime_type(NULL); - if (!nosniff_empty_mime_type) - nosniff_empty_mime_type = base::BooleanHistogram::FactoryGet( - "nosniff.empty_mime_type", - base::Histogram::kUmaTargetedHistogramFlag); - nosniff_empty_mime_type->AddBoolean(mime_type.empty()); - } -} - -// Used to write into an existing IOBuffer at a given offset. -class DependentIOBuffer : public net::WrappedIOBuffer { - public: - DependentIOBuffer(net::IOBuffer* buf, int offset) - : net::WrappedIOBuffer(buf->data() + offset), - buf_(buf) { - } - - private: - ~DependentIOBuffer() {} - - scoped_refptr<net::IOBuffer> buf_; -}; - -} // namespace - -BufferedResourceHandler::BufferedResourceHandler( - scoped_ptr<ResourceHandler> next_handler, - ResourceDispatcherHostImpl* host, - net::URLRequest* request) - : LayeredResourceHandler(next_handler.Pass()), - state_(STATE_STARTING), - host_(host), - request_(request), - read_buffer_size_(0), - bytes_read_(0), - must_download_(false), - must_download_is_set_(false), - weak_ptr_factory_(this) { -} - -BufferedResourceHandler::~BufferedResourceHandler() { -} - -void BufferedResourceHandler::SetController(ResourceController* controller) { - ResourceHandler::SetController(controller); - - // Downstream handlers see us as their ResourceController, which allows us to - // consume part or all of the resource response, and then later replay it to - // downstream handler. - DCHECK(next_handler_.get()); - next_handler_->SetController(this); -} - -bool BufferedResourceHandler::OnResponseStarted( - int request_id, - ResourceResponse* response, - bool* defer) { - response_ = response; - - // TODO(darin): It is very odd to special-case 304 responses at this level. - // We do so only because the code always has, see r24977 and r29355. The - // fact that 204 is no longer special-cased this way suggests that 304 need - // not be special-cased either. - // - // The network stack only forwards 304 responses that were not received in - // response to a conditional request (i.e., If-Modified-Since). Other 304 - // responses end up being translated to 200 or whatever the cached response - // code happens to be. It should be very rare to see a 304 at this level. - - if (!(response_->head.headers && - response_->head.headers->response_code() == 304)) { - if (ShouldSniffContent()) { - state_ = STATE_BUFFERING; - return true; - } - - if (response_->head.mime_type.empty()) { - // Ugg. The server told us not to sniff the content but didn't give us - // a mime type. What's a browser to do? Turns out, we're supposed to - // treat the response as "text/plain". This is the most secure option. - response_->head.mime_type.assign("text/plain"); - } - - // Treat feed types as text/plain. - if (response_->head.mime_type == "application/rss+xml" || - response_->head.mime_type == "application/atom+xml") { - response_->head.mime_type.assign("text/plain"); - } - } - - state_ = STATE_PROCESSING; - return ProcessResponse(defer); -} - -// We'll let the original event handler provide a buffer, and reuse it for -// subsequent reads until we're done buffering. -bool BufferedResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf, - int* buf_size, int min_size) { - if (state_ == STATE_STREAMING) - return next_handler_->OnWillRead(request_id, buf, buf_size, min_size); - - DCHECK_EQ(-1, min_size); - - if (read_buffer_) { - CHECK_LT(bytes_read_, read_buffer_size_); - *buf = new DependentIOBuffer(read_buffer_, bytes_read_); - *buf_size = read_buffer_size_ - bytes_read_; - } else { - if (!next_handler_->OnWillRead(request_id, buf, buf_size, min_size)) - return false; - - read_buffer_ = *buf; - read_buffer_size_ = *buf_size; - DCHECK_GE(read_buffer_size_, net::kMaxBytesToSniff * 2); - } - return true; -} - -bool BufferedResourceHandler::OnReadCompleted(int request_id, int bytes_read, - bool* defer) { - if (state_ == STATE_STREAMING) - return next_handler_->OnReadCompleted(request_id, bytes_read, defer); - - DCHECK_EQ(state_, STATE_BUFFERING); - bytes_read_ += bytes_read; - - if (!DetermineMimeType() && (bytes_read > 0)) - return true; // Needs more data, so keep buffering. - - state_ = STATE_PROCESSING; - return ProcessResponse(defer); -} - -bool BufferedResourceHandler::OnResponseCompleted( - int request_id, - const net::URLRequestStatus& status, - const std::string& security_info) { - // Upon completion, act like a pass-through handler in case the downstream - // handler defers OnResponseCompleted. - state_ = STATE_STREAMING; - - return next_handler_->OnResponseCompleted(request_id, status, security_info); -} - -void BufferedResourceHandler::Resume() { - switch (state_) { - case STATE_BUFFERING: - case STATE_PROCESSING: - NOTREACHED(); - break; - case STATE_REPLAYING: - MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&BufferedResourceHandler::CallReplayReadCompleted, - weak_ptr_factory_.GetWeakPtr())); - break; - case STATE_STARTING: - case STATE_STREAMING: - controller()->Resume(); - break; - } -} - -void BufferedResourceHandler::Cancel() { - controller()->Cancel(); -} - -void BufferedResourceHandler::CancelAndIgnore() { - controller()->CancelAndIgnore(); -} - -void BufferedResourceHandler::CancelWithError(int error_code) { - controller()->CancelWithError(error_code); -} - -bool BufferedResourceHandler::ProcessResponse(bool* defer) { - DCHECK_EQ(STATE_PROCESSING, state_); - - // TODO(darin): Stop special-casing 304 responses. - if (!(response_->head.headers && - response_->head.headers->response_code() == 304)) { - if (!SelectNextHandler(defer)) - return false; - if (*defer) - return true; - } - - state_ = STATE_REPLAYING; - - int request_id = ResourceRequestInfo::ForRequest(request_)->GetRequestID(); - if (!next_handler_->OnResponseStarted(request_id, response_, defer)) - return false; - - if (!read_buffer_) { - state_ = STATE_STREAMING; - return true; - } - - if (!*defer) - return ReplayReadCompleted(defer); - - return true; -} - -bool BufferedResourceHandler::ShouldSniffContent() { - const std::string& mime_type = response_->head.mime_type; - - std::string content_type_options; - request_->GetResponseHeaderByName("x-content-type-options", - &content_type_options); - - bool sniffing_blocked = - LowerCaseEqualsASCII(content_type_options, "nosniff"); - bool we_would_like_to_sniff = - net::ShouldSniffMimeType(request_->url(), mime_type); - - RecordSnifferMetrics(sniffing_blocked, we_would_like_to_sniff, mime_type); - - if (!sniffing_blocked && we_would_like_to_sniff) { - // We're going to look at the data before deciding what the content type - // is. That means we need to delay sending the ResponseStarted message - // over the IPC channel. - VLOG(1) << "To buffer: " << request_->url().spec(); - return true; - } - - return false; -} - -bool BufferedResourceHandler::DetermineMimeType() { - DCHECK_EQ(STATE_BUFFERING, state_); - - const std::string& type_hint = response_->head.mime_type; - - std::string new_type; - bool made_final_decision = - net::SniffMimeType(read_buffer_->data(), bytes_read_, request_->url(), - type_hint, &new_type); - - // SniffMimeType() returns false if there is not enough data to determine - // the mime type. However, even if it returns false, it returns a new type - // that is probably better than the current one. - response_->head.mime_type.assign(new_type); - - return made_final_decision; -} - -bool BufferedResourceHandler::SelectNextHandler(bool* defer) { - DCHECK(!response_->head.mime_type.empty()); - - ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request_); - const std::string& mime_type = response_->head.mime_type; - - if (mime_type == "application/x-x509-user-cert") { - // Install X509 handler. - scoped_ptr<ResourceHandler> handler( - new X509UserCertResourceHandler(request_, - info->GetChildID(), - info->GetRouteID())); - return UseAlternateNextHandler(handler.Pass()); - } - - if (!info->allow_download()) - return true; - - if (!MustDownload()) { - if (net::IsSupportedMimeType(mime_type)) - return true; - - bool stale; - bool has_plugin = HasSupportingPlugin(&stale); - if (stale) { - // Refresh the plugins asynchronously. - PluginServiceImpl::GetInstance()->GetPlugins( - base::Bind(&BufferedResourceHandler::OnPluginsLoaded, - weak_ptr_factory_.GetWeakPtr())); - *defer = true; - return true; - } - if (has_plugin) - return true; - } - - // Install download handler - info->set_is_download(true); - scoped_ptr<ResourceHandler> handler( - host_->CreateResourceHandlerForDownload( - request_, - true, // is_content_initiated - scoped_ptr<DownloadSaveInfo>(new DownloadSaveInfo()), - DownloadResourceHandler::OnStartedCallback())); - return UseAlternateNextHandler(handler.Pass()); -} - -bool BufferedResourceHandler::UseAlternateNextHandler( - scoped_ptr<ResourceHandler> new_handler) { - if (response_->head.headers && // Can be NULL if FTP. - response_->head.headers->response_code() / 100 != 2) { - // The response code indicates that this is an error page, but we don't - // know how to display the content. We follow Firefox here and show our - // own error page instead of triggering a download. - // TODO(abarth): We should abstract the response_code test, but this kind - // of check is scattered throughout our codebase. - request_->CancelWithError(net::ERR_FILE_NOT_FOUND); - return false; - } - - int request_id = ResourceRequestInfo::ForRequest(request_)->GetRequestID(); - - // Inform the original ResourceHandler that this will be handled entirely by - // the new ResourceHandler. - // TODO(darin): We should probably check the return values of these. - bool defer_ignored = false; - next_handler_->OnResponseStarted(request_id, response_, &defer_ignored); - DCHECK(!defer_ignored); - net::URLRequestStatus status(net::URLRequestStatus::CANCELED, - net::ERR_ABORTED); - next_handler_->OnResponseCompleted(request_id, status, std::string()); - - // This is handled entirely within the new ResourceHandler, so just reset the - // original ResourceHandler. - next_handler_ = new_handler.Pass(); - next_handler_->SetController(this); - - return CopyReadBufferToNextHandler(request_id); -} - -bool BufferedResourceHandler::ReplayReadCompleted(bool* defer) { - DCHECK(read_buffer_); - - int request_id = ResourceRequestInfo::ForRequest(request_)->GetRequestID(); - bool result = next_handler_->OnReadCompleted(request_id, bytes_read_, defer); - - read_buffer_ = NULL; - read_buffer_size_ = 0; - bytes_read_ = 0; - - state_ = STATE_STREAMING; - - return result; -} - -void BufferedResourceHandler::CallReplayReadCompleted() { - bool defer = false; - if (!ReplayReadCompleted(&defer)) { - controller()->Cancel(); - } else if (!defer) { - state_ = STATE_STREAMING; - controller()->Resume(); - } -} - -bool BufferedResourceHandler::MustDownload() { - if (must_download_is_set_) - return must_download_; - - must_download_is_set_ = true; - - std::string disposition; - request_->GetResponseHeaderByName("content-disposition", &disposition); - if (!disposition.empty() && - net::HttpContentDisposition(disposition, std::string()).is_attachment()) { - must_download_ = true; - } else if (host_->delegate() && - host_->delegate()->ShouldForceDownloadResource( - request_->url(), response_->head.mime_type)) { - must_download_ = true; - } else { - must_download_ = false; - } - - return must_download_; -} - -bool BufferedResourceHandler::HasSupportingPlugin(bool* stale) { - ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request_); - - bool allow_wildcard = false; - webkit::WebPluginInfo plugin; - return PluginServiceImpl::GetInstance()->GetPluginInfo( - info->GetChildID(), info->GetRouteID(), info->GetContext(), - request_->url(), GURL(), response_->head.mime_type, allow_wildcard, - stale, &plugin, NULL); -} - -bool BufferedResourceHandler::CopyReadBufferToNextHandler(int request_id) { - if (!bytes_read_) - return true; - - net::IOBuffer* buf = NULL; - int buf_len = 0; - if (!next_handler_->OnWillRead(request_id, &buf, &buf_len, bytes_read_)) - return false; - - CHECK((buf_len >= bytes_read_) && (bytes_read_ >= 0)); - memcpy(buf->data(), read_buffer_->data(), bytes_read_); - return true; -} - -void BufferedResourceHandler::OnPluginsLoaded( - const std::vector<webkit::WebPluginInfo>& plugins) { - bool defer = false; - if (!ProcessResponse(&defer)) { - controller()->Cancel(); - } else if (!defer) { - controller()->Resume(); - } -} - -} // namespace content diff --git a/content/browser/renderer_host/buffered_resource_handler.h b/content/browser/renderer_host/buffered_resource_handler.h deleted file mode 100644 index 0d85c6d..0000000 --- a/content/browser/renderer_host/buffered_resource_handler.h +++ /dev/null @@ -1,116 +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. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_BUFFERED_RESOURCE_HANDLER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_BUFFERED_RESOURCE_HANDLER_H_ - -#include <string> -#include <vector> - -#include "base/memory/weak_ptr.h" -#include "content/browser/renderer_host/layered_resource_handler.h" -#include "content/public/browser/resource_controller.h" - -namespace net { -class URLRequest; -} - -namespace webkit { -struct WebPluginInfo; -} - -namespace content { -class ResourceDispatcherHostImpl; - -// Used to buffer a request until enough data has been received. -class BufferedResourceHandler - : public LayeredResourceHandler, - public ResourceController { - public: - BufferedResourceHandler(scoped_ptr<ResourceHandler> next_handler, - ResourceDispatcherHostImpl* host, - net::URLRequest* request); - virtual ~BufferedResourceHandler(); - - private: - // ResourceHandler implementation: - virtual void SetController(ResourceController* controller) OVERRIDE; - virtual bool OnResponseStarted(int request_id, - ResourceResponse* response, - bool* defer) OVERRIDE; - virtual bool OnWillRead(int request_id, - net::IOBuffer** buf, - int* buf_size, - int min_size) OVERRIDE; - virtual bool OnReadCompleted(int request_id, int bytes_read, - bool* defer) OVERRIDE; - virtual bool OnResponseCompleted(int request_id, - const net::URLRequestStatus& status, - const std::string& security_info) OVERRIDE; - - // ResourceController implementation: - virtual void Resume() OVERRIDE; - virtual void Cancel() OVERRIDE; - virtual void CancelAndIgnore() OVERRIDE; - virtual void CancelWithError(int error_code) OVERRIDE; - - bool ProcessResponse(bool* defer); - - bool ShouldSniffContent(); - bool DetermineMimeType(); - bool SelectNextHandler(bool* defer); - bool UseAlternateNextHandler(scoped_ptr<ResourceHandler> handler); - - bool ReplayReadCompleted(bool* defer); - void CallReplayReadCompleted(); - - bool MustDownload(); - bool HasSupportingPlugin(bool* is_stale); - - // Copies data from |read_buffer_| to |next_handler_|. - bool CopyReadBufferToNextHandler(int request_id); - - // Called on the IO thread once the list of plugins has been loaded. - void OnPluginsLoaded(const std::vector<webkit::WebPluginInfo>& plugins); - - enum State { - STATE_STARTING, - - // In this state, we are filling read_buffer_ with data for the purpose - // of sniffing the mime type of the response. - STATE_BUFFERING, - - // In this state, we are select an appropriate downstream ResourceHandler - // based on the mime type of the response. We are also potentially waiting - // for plugins to load so that we can determine if a plugin is available to - // handle the mime type. - STATE_PROCESSING, - - // In this state, we are replaying buffered events (OnResponseStarted and - // OnReadCompleted) to the downstream ResourceHandler. - STATE_REPLAYING, - - // In this state, we are just a blind pass-through ResourceHandler. - STATE_STREAMING - }; - State state_; - - scoped_refptr<ResourceResponse> response_; - ResourceDispatcherHostImpl* host_; - net::URLRequest* request_; - scoped_refptr<net::IOBuffer> read_buffer_; - int read_buffer_size_; - int bytes_read_; - - bool must_download_; - bool must_download_is_set_; - - base::WeakPtrFactory<BufferedResourceHandler> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(BufferedResourceHandler); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_BUFFERED_RESOURCE_HANDLER_H_ diff --git a/content/browser/renderer_host/cross_site_resource_handler.cc b/content/browser/renderer_host/cross_site_resource_handler.cc deleted file mode 100644 index 2416dcc..0000000 --- a/content/browser/renderer_host/cross_site_resource_handler.cc +++ /dev/null @@ -1,219 +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 <string> - -#include "content/browser/renderer_host/cross_site_resource_handler.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "content/browser/renderer_host/render_view_host_delegate.h" -#include "content/browser/renderer_host/render_view_host_impl.h" -#include "content/browser/renderer_host/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/http/http_response_headers.h" - -namespace content { - -namespace { - -void OnCrossSiteResponseHelper(int render_process_id, - int render_view_id, - int request_id) { - RenderViewHostImpl* rvh = RenderViewHostImpl::FromID(render_process_id, - render_view_id); - if (rvh && rvh->GetDelegate()->GetRendererManagementDelegate()) { - rvh->GetDelegate()->GetRendererManagementDelegate()->OnCrossSiteResponse( - render_process_id, request_id); - } -} - -} // namespace - -CrossSiteResourceHandler::CrossSiteResourceHandler( - scoped_ptr<ResourceHandler> next_handler, - int render_process_host_id, - int render_view_id, - net::URLRequest* request) - : LayeredResourceHandler(next_handler.Pass()), - render_process_host_id_(render_process_host_id), - render_view_id_(render_view_id), - request_(request), - has_started_response_(false), - in_cross_site_transition_(false), - request_id_(-1), - completed_during_transition_(false), - did_defer_(false), - completed_status_(), - response_(NULL) { -} - -CrossSiteResourceHandler::~CrossSiteResourceHandler() { - // Cleanup back-pointer stored on the request info. - ResourceRequestInfoImpl::ForRequest(request_)->set_cross_site_handler(NULL); -} - -bool CrossSiteResourceHandler::OnRequestRedirected( - int request_id, - const GURL& new_url, - ResourceResponse* response, - bool* defer) { - // We should not have started the transition before being redirected. - DCHECK(!in_cross_site_transition_); - return next_handler_->OnRequestRedirected( - request_id, new_url, response, defer); -} - -bool CrossSiteResourceHandler::OnResponseStarted( - int request_id, - ResourceResponse* response, - bool* defer) { - // At this point, we know that the response is safe to send back to the - // renderer: it is not a download, and it has passed the SSL and safe - // browsing checks. - // We should not have already started the transition before now. - DCHECK(!in_cross_site_transition_); - has_started_response_ = true; - - ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request_); - - // If this is a download, just pass the response through without doing a - // cross-site check. The renderer will see it is a download and abort the - // request. - // - // Similarly, HTTP 204 (No Content) responses leave us showing the previous - // page. We should allow the navigation to finish without running the unload - // handler or swapping in the pending RenderViewHost. - // - // In both cases, the pending RenderViewHost will stick around until the next - // cross-site navigation, since we are unable to tell when to destroy it. - // See RenderViewHostManager::RendererAbortedProvisionalLoad. - if (info->is_download() || - (response->head.headers && - response->head.headers->response_code() == 204)) { - return next_handler_->OnResponseStarted(request_id, response, defer); - } - - // Tell the renderer to run the onunload event handler. - StartCrossSiteTransition(request_id, response); - - // Defer loading until after the onunload event handler has run. - did_defer_ = *defer = true; - return true; -} - -bool CrossSiteResourceHandler::OnReadCompleted(int request_id, - int bytes_read, - bool* defer) { - CHECK(!in_cross_site_transition_); - return next_handler_->OnReadCompleted(request_id, bytes_read, defer); -} - -bool CrossSiteResourceHandler::OnResponseCompleted( - int request_id, - const net::URLRequestStatus& status, - const std::string& security_info) { - if (!in_cross_site_transition_) { - if (has_started_response_ || - status.status() != net::URLRequestStatus::FAILED) { - // We've already completed the transition or we're canceling the request, - // so just pass it through. - return next_handler_->OnResponseCompleted(request_id, status, - security_info); - } - - // An error occured, we should wait now for the cross-site transition, - // so that the error message (e.g., 404) can be displayed to the user. - // Also continue with the logic below to remember that we completed - // during the cross-site transition. - StartCrossSiteTransition(request_id, NULL); - } - - // We have to buffer the call until after the transition completes. - completed_during_transition_ = true; - completed_status_ = status; - completed_security_info_ = security_info; - - // Return false to tell RDH not to notify the world or clean up the - // pending request. We will do so in ResumeResponse. - did_defer_ = true; - return false; -} - -// We can now send the response to the new renderer, which will cause -// WebContentsImpl to swap in the new renderer and destroy the old one. -void CrossSiteResourceHandler::ResumeResponse() { - DCHECK(request_id_ != -1); - DCHECK(in_cross_site_transition_); - in_cross_site_transition_ = false; - - if (has_started_response_) { - // Send OnResponseStarted to the new renderer. - DCHECK(response_); - bool defer = false; - if (!next_handler_->OnResponseStarted(request_id_, response_, &defer)) { - controller()->Cancel(); - } else if (!defer) { - // Unpause the request to resume reading. Any further reads will be - // directed toward the new renderer. - ResumeIfDeferred(); - } - } - - // Remove ourselves from the ExtraRequestInfo. - ResourceRequestInfoImpl* info = - ResourceRequestInfoImpl::ForRequest(request_); - info->set_cross_site_handler(NULL); - - // If the response completed during the transition, notify the next - // event handler. - if (completed_during_transition_) { - if (next_handler_->OnResponseCompleted(request_id_, completed_status_, - completed_security_info_)) { - ResumeIfDeferred(); - } - } -} - -// Prepare to render the cross-site response in a new RenderViewHost, by -// telling the old RenderViewHost to run its onunload handler. -void CrossSiteResourceHandler::StartCrossSiteTransition( - int request_id, - ResourceResponse* response) { - in_cross_site_transition_ = true; - request_id_ = request_id; - response_ = response; - - // Store this handler on the ExtraRequestInfo, so that RDH can call our - // ResumeResponse method when the close ACK is received. - ResourceRequestInfoImpl* info = - ResourceRequestInfoImpl::ForRequest(request_); - info->set_cross_site_handler(this); - - // Tell the contents responsible for this request that a cross-site response - // is starting, so that it can tell its old renderer to run its onunload - // handler now. We will wait to hear the corresponding ClosePage_ACK. - BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind( - &OnCrossSiteResponseHelper, - render_process_host_id_, - render_view_id_, - request_id)); - - // TODO(creis): If the above call should fail, then we need to notify the IO - // thread to proceed anyway, using ResourceDispatcherHost::OnClosePageACK. -} - -void CrossSiteResourceHandler::ResumeIfDeferred() { - if (did_defer_) { - did_defer_ = false; - controller()->Resume(); - } -} - -} // namespace content diff --git a/content/browser/renderer_host/cross_site_resource_handler.h b/content/browser/renderer_host/cross_site_resource_handler.h deleted file mode 100644 index c17c6cd..0000000 --- a/content/browser/renderer_host/cross_site_resource_handler.h +++ /dev/null @@ -1,75 +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. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_CROSS_SITE_RESOURCE_HANDLER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_CROSS_SITE_RESOURCE_HANDLER_H_ - -#include "content/browser/renderer_host/layered_resource_handler.h" -#include "net/url_request/url_request_status.h" - -namespace net { -class URLRequest; -} - -namespace content { - -// Ensures that cross-site responses are delayed until the onunload handler of -// the previous page is allowed to run. This handler wraps an -// AsyncEventHandler, and it sits inside SafeBrowsing and Buffered event -// handlers. This is important, so that it can intercept OnResponseStarted -// after we determine that a response is safe and not a download. -class CrossSiteResourceHandler : public LayeredResourceHandler { - public: - CrossSiteResourceHandler(scoped_ptr<ResourceHandler> next_handler, - int render_process_host_id, - int render_view_id, - net::URLRequest* request); - virtual ~CrossSiteResourceHandler(); - - // ResourceHandler implementation: - virtual bool OnRequestRedirected(int request_id, - const GURL& new_url, - ResourceResponse* response, - bool* defer) OVERRIDE; - virtual bool OnResponseStarted(int request_id, - ResourceResponse* response, - bool* defer) OVERRIDE; - virtual bool OnReadCompleted(int request_id, - int bytes_read, - bool* defer) OVERRIDE; - virtual bool OnResponseCompleted(int request_id, - const net::URLRequestStatus& status, - const std::string& security_info) OVERRIDE; - - // We can now send the response to the new renderer, which will cause - // WebContentsImpl to swap in the new renderer and destroy the old one. - void ResumeResponse(); - - private: - // Prepare to render the cross-site response in a new RenderViewHost, by - // telling the old RenderViewHost to run its onunload handler. - void StartCrossSiteTransition( - int request_id, - ResourceResponse* response); - - void ResumeIfDeferred(); - - int render_process_host_id_; - int render_view_id_; - net::URLRequest* request_; - bool has_started_response_; - bool in_cross_site_transition_; - int request_id_; - bool completed_during_transition_; - bool did_defer_; - net::URLRequestStatus completed_status_; - std::string completed_security_info_; - ResourceResponse* response_; - - DISALLOW_COPY_AND_ASSIGN(CrossSiteResourceHandler); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_CROSS_SITE_RESOURCE_HANDLER_H_ diff --git a/content/browser/renderer_host/doomed_resource_handler.cc b/content/browser/renderer_host/doomed_resource_handler.cc deleted file mode 100644 index 3887373..0000000 --- a/content/browser/renderer_host/doomed_resource_handler.cc +++ /dev/null @@ -1,77 +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/doomed_resource_handler.h" - -#include "net/url_request/url_request_status.h" - -namespace content { - -DoomedResourceHandler::DoomedResourceHandler( - scoped_ptr<ResourceHandler> old_handler) - : old_handler_(old_handler.Pass()) { -} - -DoomedResourceHandler::~DoomedResourceHandler() { -} - -bool DoomedResourceHandler::OnUploadProgress(int request_id, - uint64 position, - uint64 size) { - NOTREACHED(); - return true; -} - -bool DoomedResourceHandler::OnRequestRedirected(int request_id, - const GURL& new_url, - ResourceResponse* response, - bool* defer) { - NOTREACHED(); - return true; -} - -bool DoomedResourceHandler::OnResponseStarted(int request_id, - ResourceResponse* response, - bool* defer) { - NOTREACHED(); - return true; -} - -bool DoomedResourceHandler::OnWillStart(int request_id, - const GURL& url, - bool* defer) { - NOTREACHED(); - return true; -} - -bool DoomedResourceHandler::OnWillRead(int request_id, - net::IOBuffer** buf, - int* buf_size, - int min_size) { - NOTREACHED(); - return true; -} - -bool DoomedResourceHandler::OnReadCompleted(int request_id, - int bytes_read, - bool* defer) { - NOTREACHED(); - return true; -} - -bool DoomedResourceHandler::OnResponseCompleted( - int request_id, - const net::URLRequestStatus& status, - const std::string& security_info) { - DCHECK(status.status() == net::URLRequestStatus::CANCELED || - status.status() == net::URLRequestStatus::FAILED); - return true; -} - -void DoomedResourceHandler::OnDataDownloaded(int request_id, - int bytes_downloaded) { - NOTREACHED(); -} - -} // namespace content diff --git a/content/browser/renderer_host/doomed_resource_handler.h b/content/browser/renderer_host/doomed_resource_handler.h deleted file mode 100644 index 0f37bb4..0000000 --- a/content/browser/renderer_host/doomed_resource_handler.h +++ /dev/null @@ -1,60 +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. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_DOOMED_RESOURCE_HANDLER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_DOOMED_RESOURCE_HANDLER_H_ - -#include "base/memory/scoped_ptr.h" -#include "content/browser/renderer_host/resource_handler.h" - -namespace content { - -// ResourceHandler that DCHECKs on all events but canceling and failing of -// requests while activated for a URLRequest. -class DoomedResourceHandler : public ResourceHandler { - public: - // As the DoomedResourceHandler is constructed and substituted from code - // of another ResourceHandler, we need to make sure that this other handler - // does not lose its last reference and gets destroyed by being substituted. - // Therefore, we retain a reference to |old_handler| that prevents the - // destruction. - explicit DoomedResourceHandler(scoped_ptr<ResourceHandler> old_handler); - virtual ~DoomedResourceHandler(); - - // ResourceHandler implementation: - virtual bool OnUploadProgress(int request_id, - uint64 position, - uint64 size) OVERRIDE; - virtual bool OnRequestRedirected(int request_id, - const GURL& new_url, - ResourceResponse* response, - bool* defer) OVERRIDE; - virtual bool OnResponseStarted(int request_id, - ResourceResponse* response, - bool* defer) OVERRIDE; - virtual bool OnWillStart(int request_id, - const GURL& url, - bool* defer) OVERRIDE; - virtual bool OnWillRead(int request_id, - net::IOBuffer** buf, - int* buf_size, - int min_size) OVERRIDE; - virtual bool OnReadCompleted(int request_id, - int bytes_read, - bool* defer) OVERRIDE; - virtual bool OnResponseCompleted(int request_id, - const net::URLRequestStatus& status, - const std::string& security_info) OVERRIDE; - virtual void OnDataDownloaded(int request_id, - int bytes_downloaded) OVERRIDE; - - private: - scoped_ptr<ResourceHandler> old_handler_; - - DISALLOW_COPY_AND_ASSIGN(DoomedResourceHandler); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_DOOMED_RESOURCE_HANDLER_H_ diff --git a/content/browser/renderer_host/layered_resource_handler.cc b/content/browser/renderer_host/layered_resource_handler.cc deleted file mode 100644 index 99323f6..0000000 --- a/content/browser/renderer_host/layered_resource_handler.cc +++ /dev/null @@ -1,83 +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/layered_resource_handler.h" - -#include "base/logging.h" - -namespace content { - -LayeredResourceHandler::LayeredResourceHandler( - scoped_ptr<ResourceHandler> next_handler) - : next_handler_(next_handler.Pass()) { -} - -LayeredResourceHandler::~LayeredResourceHandler() { -} - -void LayeredResourceHandler::SetController(ResourceController* controller) { - ResourceHandler::SetController(controller); - - // Pass the controller down to the next handler. This method is intended to - // be overriden by subclasses of LayeredResourceHandler that need to insert a - // different ResourceController. - - DCHECK(next_handler_.get()); - next_handler_->SetController(controller); -} - -bool LayeredResourceHandler::OnUploadProgress(int request_id, uint64 position, - uint64 size) { - DCHECK(next_handler_.get()); - return next_handler_->OnUploadProgress(request_id, position, size); -} - -bool LayeredResourceHandler::OnRequestRedirected(int request_id, - const GURL& url, - ResourceResponse* response, - bool* defer) { - DCHECK(next_handler_.get()); - return next_handler_->OnRequestRedirected(request_id, url, response, defer); -} - -bool LayeredResourceHandler::OnResponseStarted(int request_id, - ResourceResponse* response, - bool* defer) { - DCHECK(next_handler_.get()); - return next_handler_->OnResponseStarted(request_id, response, defer); -} - -bool LayeredResourceHandler::OnWillStart(int request_id, const GURL& url, - bool* defer) { - DCHECK(next_handler_.get()); - return next_handler_->OnWillStart(request_id, url, defer); -} - -bool LayeredResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf, - int* buf_size, int min_size) { - DCHECK(next_handler_.get()); - return next_handler_->OnWillRead(request_id, buf, buf_size, min_size); -} - -bool LayeredResourceHandler::OnReadCompleted(int request_id, int bytes_read, - bool* defer) { - DCHECK(next_handler_.get()); - return next_handler_->OnReadCompleted(request_id, bytes_read, defer); -} - -bool LayeredResourceHandler::OnResponseCompleted( - int request_id, - const net::URLRequestStatus& status, - const std::string& security_info) { - DCHECK(next_handler_.get()); - return next_handler_->OnResponseCompleted(request_id, status, security_info); -} - -void LayeredResourceHandler::OnDataDownloaded(int request_id, - int bytes_downloaded) { - DCHECK(next_handler_.get()); - next_handler_->OnDataDownloaded(request_id, bytes_downloaded); -} - -} // namespace content diff --git a/content/browser/renderer_host/layered_resource_handler.h b/content/browser/renderer_host/layered_resource_handler.h deleted file mode 100644 index d54abbe..0000000 --- a/content/browser/renderer_host/layered_resource_handler.h +++ /dev/null @@ -1,47 +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. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_LAYERED_RESOURCE_HANDLER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_LAYERED_RESOURCE_HANDLER_H_ - -#include "base/memory/scoped_ptr.h" -#include "content/browser/renderer_host/resource_handler.h" -#include "content/common/content_export.h" - -namespace content { - -// A ResourceHandler that simply delegates all calls to a next handler. This -// class is intended to be subclassed. -class CONTENT_EXPORT LayeredResourceHandler : public ResourceHandler { - public: - explicit LayeredResourceHandler(scoped_ptr<ResourceHandler> next_handler); - virtual ~LayeredResourceHandler(); - - // ResourceHandler implementation: - virtual void SetController(ResourceController* controller) OVERRIDE; - virtual bool OnUploadProgress(int request_id, uint64 position, - uint64 size) OVERRIDE; - virtual bool OnRequestRedirected(int request_id, const GURL& url, - ResourceResponse* response, - bool* defer) OVERRIDE; - virtual bool OnResponseStarted(int request_id, - ResourceResponse* response, - bool* defer) OVERRIDE; - virtual bool OnWillStart(int request_id, const GURL& url, - bool* defer) OVERRIDE; - virtual bool OnWillRead(int request_id, net::IOBuffer** buf, int* buf_size, - int min_size) OVERRIDE; - virtual bool OnReadCompleted(int request_id, int bytes_read, - bool* defer) OVERRIDE; - virtual bool OnResponseCompleted(int request_id, - const net::URLRequestStatus& status, - const std::string& security_info) OVERRIDE; - virtual void OnDataDownloaded(int request_id, int bytes_downloaded) OVERRIDE; - - scoped_ptr<ResourceHandler> next_handler_; -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_LAYERED_RESOURCE_HANDLER_H_ diff --git a/content/browser/renderer_host/redirect_to_file_resource_handler.cc b/content/browser/renderer_host/redirect_to_file_resource_handler.cc deleted file mode 100644 index 48c1c85..0000000 --- a/content/browser/renderer_host/redirect_to_file_resource_handler.cc +++ /dev/null @@ -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 diff --git a/content/browser/renderer_host/redirect_to_file_resource_handler.h b/content/browser/renderer_host/redirect_to_file_resource_handler.h deleted file mode 100644 index b33b212..0000000 --- a/content/browser/renderer_host/redirect_to_file_resource_handler.h +++ /dev/null @@ -1,107 +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. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_REDIRECT_TO_FILE_RESOURCE_HANDLER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_REDIRECT_TO_FILE_RESOURCE_HANDLER_H_ - -#include "base/file_path.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/platform_file.h" -#include "content/browser/renderer_host/layered_resource_handler.h" -#include "net/url_request/url_request_status.h" - -namespace net { -class FileStream; -class GrowableIOBuffer; -} - -namespace webkit_blob { -class ShareableFileReference; -} - -namespace content { -class ResourceDispatcherHostImpl; - -// Redirects network data to a file. This is intended to be layered in front -// of either the AsyncResourceHandler or the SyncResourceHandler. -class RedirectToFileResourceHandler : public LayeredResourceHandler { - public: - RedirectToFileResourceHandler( - scoped_ptr<ResourceHandler> next_handler, - int process_id, - ResourceDispatcherHostImpl* resource_dispatcher_host); - virtual ~RedirectToFileResourceHandler(); - - // ResourceHandler implementation: - virtual bool OnResponseStarted(int request_id, - ResourceResponse* response, - bool* defer) OVERRIDE; - virtual bool OnWillStart(int request_id, - const GURL& url, - bool* defer) OVERRIDE; - virtual bool OnWillRead(int request_id, - net::IOBuffer** buf, - int* buf_size, - int min_size) OVERRIDE; - virtual bool OnReadCompleted(int request_id, - int bytes_read, - bool* defer) OVERRIDE; - virtual bool OnResponseCompleted(int request_id, - const net::URLRequestStatus& status, - const std::string& security_info) OVERRIDE; - - private: - void DidCreateTemporaryFile(base::PlatformFileError error_code, - base::PassPlatformFile file_handle, - const FilePath& file_path); - void DidWriteToFile(int result); - bool WriteMore(); - bool BufIsFull() const; - void ResumeIfDeferred(); - - base::WeakPtrFactory<RedirectToFileResourceHandler> weak_factory_; - - ResourceDispatcherHostImpl* host_; - int process_id_; - int request_id_; - - // We allocate a single, fixed-size IO buffer (buf_) used to read from the - // network (buf_write_pending_ is true while the system is copying data into - // buf_), and then write this buffer out to disk (write_callback_pending_ is - // true while writing to disk). Reading from the network is suspended while - // the buffer is full (BufIsFull returns true). The write_cursor_ member - // tracks the offset into buf_ that we are writing to disk. - - scoped_refptr<net::GrowableIOBuffer> buf_; - bool buf_write_pending_; - int write_cursor_; - - scoped_ptr<net::FileStream> file_stream_; - bool write_callback_pending_; - - // |next_buffer_size_| is the size of the buffer to be allocated on the next - // OnWillRead() call. We exponentially grow the size of the buffer allocated - // when our owner fills our buffers. On the first OnWillRead() call, we - // allocate a buffer of 32k and double it in OnReadCompleted() if the buffer - // was filled, up to a maximum size of 512k. - int next_buffer_size_; - - // We create a ShareableFileReference that's deletable for the temp - // file created as a result of the download. - scoped_refptr<webkit_blob::ShareableFileReference> deletable_file_; - - bool did_defer_ ; - - bool completed_during_write_; - net::URLRequestStatus completed_status_; - std::string completed_security_info_; - - DISALLOW_COPY_AND_ASSIGN(RedirectToFileResourceHandler); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_REDIRECT_TO_FILE_RESOURCE_HANDLER_H_ diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc index 30c821c..9bcd74e 100644 --- a/content/browser/renderer_host/render_message_filter.cc +++ b/content/browser/renderer_host/render_message_filter.cc @@ -21,13 +21,13 @@ #include "content/browser/dom_storage/session_storage_namespace_impl.h" #include "content/browser/download/download_stats.h" #include "content/browser/gpu/gpu_data_manager_impl.h" +#include "content/browser/loader/resource_dispatcher_host_impl.h" #include "content/browser/plugin_process_host.h" #include "content/browser/plugin_service_impl.h" #include "content/browser/ppapi_plugin_process_host.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/renderer_host/render_view_host_delegate.h" #include "content/browser/renderer_host/render_widget_helper.h" -#include "content/browser/renderer_host/resource_dispatcher_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/common/child_process_host_impl.h" #include "content/common/child_process_messages.h" diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h index f52f86f..2494aa1 100644 --- a/content/browser/renderer_host/render_message_filter.h +++ b/content/browser/renderer_host/render_message_filter.h @@ -9,6 +9,7 @@ #include <windows.h> #endif +#include <set> #include <string> #include <vector> @@ -18,7 +19,6 @@ #include "base/shared_memory.h" #include "base/string16.h" #include "build/build_config.h" -#include "content/browser/renderer_host/resource_dispatcher_host_impl.h" #include "content/public/browser/browser_message_filter.h" #include "content/public/common/three_d_api_types.h" #include "media/base/channel_layout.h" @@ -53,6 +53,7 @@ struct MediaLogEvent; } namespace net { +class URLRequestContext; class URLRequestContextGetter; } diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 10c78e5..f5e455f 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc @@ -56,6 +56,7 @@ #include "content/browser/hyphenator/hyphenator_message_filter.h" #include "content/browser/in_process_webkit/indexed_db_context_impl.h" #include "content/browser/in_process_webkit/indexed_db_dispatcher_host.h" +#include "content/browser/loader/resource_message_filter.h" #include "content/browser/mime_registry_message_filter.h" #include "content/browser/plugin_service_impl.h" #include "content/browser/profiler_message_filter.h" @@ -75,7 +76,6 @@ #include "content/browser/renderer_host/render_view_host_delegate.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/renderer_host/render_widget_helper.h" -#include "content/browser/renderer_host/resource_message_filter.h" #include "content/browser/renderer_host/socket_stream_dispatcher_host.h" #include "content/browser/renderer_host/text_input_client_message_filter.h" #include "content/browser/resolve_proxy_msg_helper.h" @@ -93,6 +93,7 @@ #include "content/public/browser/browser_context.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/notification_service.h" +#include "content/public/browser/notification_types.h" #include "content/public/browser/render_process_host_factory.h" #include "content/public/browser/resource_context.h" #include "content/public/browser/user_metrics.h" diff --git a/content/browser/renderer_host/render_widget_helper.cc b/content/browser/renderer_host/render_widget_helper.cc index e198a31..14204a7 100644 --- a/content/browser/renderer_host/render_widget_helper.cc +++ b/content/browser/renderer_host/render_widget_helper.cc @@ -11,9 +11,9 @@ #include "base/threading/thread.h" #include "base/threading/thread_restrictions.h" #include "content/browser/gpu/gpu_surface_tracker.h" +#include "content/browser/loader/resource_dispatcher_host_impl.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/renderer_host/render_view_host_impl.h" -#include "content/browser/renderer_host/resource_dispatcher_host_impl.h" #include "content/browser/dom_storage/session_storage_namespace_impl.h" #include "content/common/view_messages.h" diff --git a/content/browser/renderer_host/resource_buffer.cc b/content/browser/renderer_host/resource_buffer.cc deleted file mode 100644 index 21c9451..0000000 --- a/content/browser/renderer_host/resource_buffer.cc +++ /dev/null @@ -1,181 +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/resource_buffer.h" - -#include <math.h> - -#include "base/logging.h" - -namespace content { - -// A circular buffer allocator. -// -// We keep track of the starting offset (alloc_start_) and the ending offset -// (alloc_end_). There are two layouts to keep in mind: -// -// #1: -// ------------[XXXXXXXXXXXXXXXXXXXXXXX]---- -// ^ ^ -// start end -// -// #2: -// XXXXXXXXXX]---------------------[XXXXXXXX -// ^ ^ -// end start -// -// If end <= start, then we have the buffer wraparound case (depicted second). -// If the buffer is empty, then start and end will be set to -1. -// -// Allocations are always contiguous. - -ResourceBuffer::ResourceBuffer() - : buf_size_(0), - min_alloc_size_(0), - max_alloc_size_(0), - alloc_start_(-1), - alloc_end_(-1) { -} - -ResourceBuffer::~ResourceBuffer() { -} - -bool ResourceBuffer::Initialize(int buffer_size, - int min_allocation_size, - int max_allocation_size) { - DCHECK(!IsInitialized()); - - // It would be wasteful if these are not multiples of min_allocation_size. - DCHECK_EQ(0, buffer_size % min_allocation_size); - DCHECK_EQ(0, max_allocation_size % min_allocation_size); - - buf_size_ = buffer_size; - min_alloc_size_ = min_allocation_size; - max_alloc_size_ = max_allocation_size; - - return shared_mem_.CreateAndMapAnonymous(buf_size_); -} - -bool ResourceBuffer::IsInitialized() const { - return shared_mem_.memory() != NULL; -} - -bool ResourceBuffer::ShareToProcess( - base::ProcessHandle process_handle, - base::SharedMemoryHandle* shared_memory_handle, - int* shared_memory_size) { - DCHECK(IsInitialized()); - - if (!shared_mem_.ShareToProcess(process_handle, shared_memory_handle)) - return false; - - *shared_memory_size = buf_size_; - return true; -} - -bool ResourceBuffer::CanAllocate() const { - DCHECK(IsInitialized()); - - if (alloc_start_ == -1) - return true; - - int diff = alloc_end_ - alloc_start_; - if (diff > 0) - return (buf_size_ - diff) >= min_alloc_size_; - - return -diff >= min_alloc_size_; -} - -char* ResourceBuffer::Allocate(int* size) { - DCHECK(CanAllocate()); - - int alloc_offset = 0; - int alloc_size; - - if (alloc_start_ == -1) { - // This is the first allocation. - alloc_start_ = 0; - alloc_end_ = buf_size_; - alloc_size = buf_size_; - } else if (alloc_start_ < alloc_end_) { - // Append the next allocation if it fits. Otherwise, wraparound. - // - // NOTE: We could look to see if a larger allocation is possible by - // wrapping around sooner, but instead we just look to fill the space at - // the end of the buffer provided that meets the min_alloc_size_ - // requirement. - // - if ((buf_size_ - alloc_end_) >= min_alloc_size_) { - alloc_offset = alloc_end_; - alloc_size = buf_size_ - alloc_end_; - alloc_end_ = buf_size_; - } else { - // It must be possible to allocate a least min_alloc_size_. - DCHECK(alloc_start_ >= min_alloc_size_); - alloc_size = alloc_start_; - alloc_end_ = alloc_start_; - } - } else { - // This is the wraparound case. - DCHECK(alloc_end_ < alloc_start_); - alloc_offset = alloc_end_; - alloc_size = alloc_start_ - alloc_end_; - alloc_end_ = alloc_start_; - } - - // Make sure alloc_size does not exceed max_alloc_size_. We store the - // current value of alloc_size, so that we can use ShrinkLastAllocation to - // trim it back. This allows us to reuse the alloc_end_ adjustment logic. - - alloc_sizes_.push(alloc_size); - - if (alloc_size > max_alloc_size_) { - alloc_size = max_alloc_size_; - ShrinkLastAllocation(alloc_size); - } - - *size = alloc_size; - return static_cast<char*>(shared_mem_.memory()) + alloc_offset; -} - -int ResourceBuffer::GetLastAllocationOffset() const { - DCHECK(!alloc_sizes_.empty()); - DCHECK(alloc_end_ >= alloc_sizes_.back()); - return alloc_end_ - alloc_sizes_.back(); -} - -void ResourceBuffer::ShrinkLastAllocation(int new_size) { - DCHECK(!alloc_sizes_.empty()); - - int aligned_size = (new_size / min_alloc_size_) * min_alloc_size_; - if (aligned_size < new_size) - aligned_size += min_alloc_size_; - - DCHECK_LE(new_size, aligned_size); - DCHECK_GE(alloc_sizes_.back(), aligned_size); - - int* last_allocation_size = &alloc_sizes_.back(); - alloc_end_ -= (*last_allocation_size - aligned_size); - *last_allocation_size = aligned_size; -} - -void ResourceBuffer::RecycleLeastRecentlyAllocated() { - DCHECK(!alloc_sizes_.empty()); - int allocation_size = alloc_sizes_.front(); - alloc_sizes_.pop(); - - alloc_start_ += allocation_size; - DCHECK(alloc_start_ <= buf_size_); - - if (alloc_start_ == alloc_end_) { - DCHECK(alloc_sizes_.empty()); - alloc_start_ = -1; - alloc_end_ = -1; - } else if (alloc_start_ == buf_size_) { - DCHECK(!alloc_sizes_.empty()); - alloc_start_ = 0; - } -} - -} // namespace content diff --git a/content/browser/renderer_host/resource_buffer.h b/content/browser/renderer_host/resource_buffer.h deleted file mode 100644 index ea805c3..0000000 --- a/content/browser/renderer_host/resource_buffer.h +++ /dev/null @@ -1,128 +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. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_RESOURCE_BUFFER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_RESOURCE_BUFFER_H_ - -#include <queue> - -#include "base/basictypes.h" -#include "base/memory/ref_counted.h" -#include "base/shared_memory.h" -#include "content/common/content_export.h" - -namespace content { - -// ResourceBuffer implements a simple "circular buffer" allocation strategy. -// Allocations are recycled in FIFO order. -// -// You can think of the ResourceBuffer as a FIFO. The Allocate method reserves -// space in the buffer. Allocate may be called multiple times until the buffer -// is fully reserved (at which point CanAllocate returns false). Allocations -// are freed in FIFO order via a call to RecycleLeastRecentlyAllocated. -// -// ResourceBuffer is reference-counted for the benefit of consumers, who need -// to ensure that ResourceBuffer stays alive while they are using its memory. -// -// EXAMPLE USAGE: -// -// // Writes data into the ResourceBuffer, and returns the location (byte -// // offset and count) of the bytes written into the ResourceBuffer's shared -// // memory buffer. -// void WriteToBuffer(ResourceBuffer* buf, int* offset, int* count) { -// DCHECK(buf->CanAllocate()); -// -// *offset = -1; -// *count = 0; -// -// int size; -// char* ptr = buf->Allocate(&size); -// if (!ptr) { /* handle error */ } -// -// int bytes_read = static_cast<int>(fread(ptr, 1, size, file_pointer_)); -// if (!bytes_read) { /* handle error */ } -// -// if (bytes_read < size) -// buf->ShrinkLastAllocation(bytes_read); -// -// *offset = buf->GetLastAllocationOffset(); -// *count = bytes_read; -// } -// -// NOTE: As the above example illustrates, the ResourceBuffer keeps track of -// the last allocation made. Calling ShrinkLastAllocation is optional, as it -// just helps the ResourceBuffer optimize storage and be more aggressive about -// returning larger allocations from the Allocate method. -// -class CONTENT_EXPORT ResourceBuffer - : public base::RefCountedThreadSafe<ResourceBuffer> { - public: - ResourceBuffer(); - - // Initialize the shared memory buffer. It will be buffer_size bytes in - // length. The min/max_allocation_size parameters control the behavior of - // the Allocate method. It will prefer to return segments that are - // max_allocation_size in length, but will return segments less than that if - // space is limited. It will not return allocations smaller than - // min_allocation_size. - bool Initialize(int buffer_size, - int min_allocation_size, - int max_allocation_size); - bool IsInitialized() const; - - // Returns a shared memory handle that can be passed to the given process. - // The shared memory handle is only intended to be interpretted by code - // running in the specified process. NOTE: The caller should ensure that - // this memory eventually be returned to the operating system. - bool ShareToProcess(base::ProcessHandle process_handle, - base::SharedMemoryHandle* shared_memory_handle, - int* shared_memory_size); - - // Returns true if Allocate will succeed. - bool CanAllocate() const; - - // Returns a pointer into the shared memory buffer or NULL if the buffer is - // already fully allocated. The returned size will be max_allocation_size - // unless the buffer is close to being full. - char* Allocate(int* size); - - // Returns the offset into the shared memory buffer where the last allocation - // returned by Allocate can be found. - int GetLastAllocationOffset() const; - - // Called to reduce the size of the last allocation returned by Allocate. It - // is OK for new_size to match the current size of the last allocation. - void ShrinkLastAllocation(int new_size); - - // Called to allow reuse of memory that was previously allocated. See notes - // above the class for more details about this method. - void RecycleLeastRecentlyAllocated(); - - private: - friend class base::RefCountedThreadSafe<ResourceBuffer>; - ~ResourceBuffer(); - - base::SharedMemory shared_mem_; - - int buf_size_; - int min_alloc_size_; - int max_alloc_size_; - - // These point to the range of the shared memory that is currently allocated. - // If alloc_start_ is -1, then the range is empty and nothing is allocated. - // Otherwise, alloc_start_ points to the start of the allocated range, and - // alloc_end_ points just beyond the end of the previous allocation. In the - // wraparound case, alloc_end_ <= alloc_start_. See resource_buffer.cc for - // more details about these members. - int alloc_start_; - int alloc_end_; - - std::queue<int> alloc_sizes_; - - DISALLOW_COPY_AND_ASSIGN(ResourceBuffer); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_RESOURCE_BUFFER_H_ diff --git a/content/browser/renderer_host/resource_buffer_unittest.cc b/content/browser/renderer_host/resource_buffer_unittest.cc deleted file mode 100644 index d613ebf..0000000 --- a/content/browser/renderer_host/resource_buffer_unittest.cc +++ /dev/null @@ -1,137 +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/resource_buffer.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace content { - -TEST(ResourceBufferTest, BasicAllocations) { - scoped_refptr<ResourceBuffer> buf = new ResourceBuffer(); - EXPECT_TRUE(buf->Initialize(100, 5, 10)); - EXPECT_TRUE(buf->CanAllocate()); - - // First allocation - { - int size; - char* ptr = buf->Allocate(&size); - EXPECT_TRUE(ptr); - EXPECT_EQ(10, size); - EXPECT_TRUE(buf->CanAllocate()); - - EXPECT_EQ(0, buf->GetLastAllocationOffset()); - - buf->ShrinkLastAllocation(2); // Less than our min allocation size. - EXPECT_EQ(0, buf->GetLastAllocationOffset()); - EXPECT_TRUE(buf->CanAllocate()); - } - - // Second allocation - { - int size; - char* ptr = buf->Allocate(&size); - EXPECT_TRUE(ptr); - EXPECT_EQ(10, size); - EXPECT_TRUE(buf->CanAllocate()); - - EXPECT_EQ(5, buf->GetLastAllocationOffset()); - - buf->ShrinkLastAllocation(4); - EXPECT_EQ(5, buf->GetLastAllocationOffset()); - - EXPECT_TRUE(buf->CanAllocate()); - } -} - -TEST(ResourceBufferTest, AllocateAndRecycle) { - scoped_refptr<ResourceBuffer> buf = new ResourceBuffer(); - EXPECT_TRUE(buf->Initialize(100, 5, 10)); - - int size; - - buf->Allocate(&size); - EXPECT_EQ(0, buf->GetLastAllocationOffset()); - - buf->RecycleLeastRecentlyAllocated(); - - // Offset should again be 0. - buf->Allocate(&size); - EXPECT_EQ(0, buf->GetLastAllocationOffset()); -} - -TEST(ResourceBufferTest, WrapAround) { - scoped_refptr<ResourceBuffer> buf = new ResourceBuffer(); - EXPECT_TRUE(buf->Initialize(20, 10, 10)); - - int size; - - buf->Allocate(&size); - EXPECT_EQ(10, size); - - buf->Allocate(&size); - EXPECT_EQ(10, size); - - // Create hole at the beginnning. Next allocation should go there. - buf->RecycleLeastRecentlyAllocated(); - - buf->Allocate(&size); - EXPECT_EQ(10, size); - - EXPECT_EQ(0, buf->GetLastAllocationOffset()); -} - -TEST(ResourceBufferTest, WrapAround2) { - scoped_refptr<ResourceBuffer> buf = new ResourceBuffer(); - EXPECT_TRUE(buf->Initialize(30, 10, 10)); - - int size; - - buf->Allocate(&size); - EXPECT_EQ(10, size); - - buf->Allocate(&size); - EXPECT_EQ(10, size); - - buf->Allocate(&size); - EXPECT_EQ(10, size); - - EXPECT_FALSE(buf->CanAllocate()); - - // Create holes at first and second slots. - buf->RecycleLeastRecentlyAllocated(); - buf->RecycleLeastRecentlyAllocated(); - - EXPECT_TRUE(buf->CanAllocate()); - - buf->Allocate(&size); - EXPECT_EQ(10, size); - EXPECT_EQ(0, buf->GetLastAllocationOffset()); - - buf->Allocate(&size); - EXPECT_EQ(10, size); - EXPECT_EQ(10, buf->GetLastAllocationOffset()); - - EXPECT_FALSE(buf->CanAllocate()); -} - -TEST(ResourceBufferTest, Full) { - scoped_refptr<ResourceBuffer> buf = new ResourceBuffer(); - EXPECT_TRUE(buf->Initialize(20, 10, 10)); - - int size; - buf->Allocate(&size); - EXPECT_EQ(10, size); - - buf->Allocate(&size); - EXPECT_EQ(10, size); - - // Full. - EXPECT_FALSE(buf->CanAllocate()); - - // Still full, even if there is a small hole at the end. - buf->ShrinkLastAllocation(5); - EXPECT_FALSE(buf->CanAllocate()); -} - -} // namespace content diff --git a/content/browser/renderer_host/resource_dispatcher_host_browsertest.cc b/content/browser/renderer_host/resource_dispatcher_host_browsertest.cc deleted file mode 100644 index eee7c39..0000000 --- a/content/browser/renderer_host/resource_dispatcher_host_browsertest.cc +++ /dev/null @@ -1,405 +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 "base/string_util.h" -#include "base/utf_string_conversions.h" -#include "content/browser/download/download_manager_impl.h" -#include "content/browser/web_contents/web_contents_impl.h" -#include "content/public/browser/browser_context.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/notification_types.h" -#include "content/public/browser/web_contents.h" -#include "content/public/common/url_constants.h" -#include "content/public/test/browser_test_utils.h" -#include "content/public/test/test_utils.h" -#include "content/shell/shell.h" -#include "content/test/content_browser_test.h" -#include "content/test/content_browser_test_utils.h" -#include "content/test/net/url_request_failed_job.h" -#include "content/test/net/url_request_mock_http_job.h" -#include "net/base/net_errors.h" -#include "net/test/test_server.h" - -namespace content { - -class ResourceDispatcherHostBrowserTest : public ContentBrowserTest, - public DownloadManager::Observer { - public: - ResourceDispatcherHostBrowserTest() : got_downloads_(false) {} - - protected: - virtual void SetUpOnMainThread() OVERRIDE { - FilePath path = GetTestFilePath("", ""); - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&URLRequestMockHTTPJob::AddUrlHandler, path)); - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&URLRequestFailedJob::AddUrlHandler)); - } - - virtual void OnDownloadCreated( - DownloadManager* manager, - DownloadItem* item) OVERRIDE { - if (!got_downloads_) - got_downloads_ = !!manager->InProgressCount(); - } - - RenderViewHost* render_view_host() { - return shell()->web_contents()->GetRenderViewHost(); - } - - GURL GetMockURL(const std::string& file) { - return URLRequestMockHTTPJob::GetMockUrl(FilePath().AppendASCII(file)); - } - - void CheckTitleTest(const GURL& url, - const std::string& expected_title) { - string16 expected_title16(ASCIIToUTF16(expected_title)); - TitleWatcher title_watcher(shell()->web_contents(), expected_title16); - NavigateToURL(shell(), url); - EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle()); - } - - bool GetPopupTitle(const GURL& url, string16* title) { - NavigateToURL(shell(), url); - - ShellAddedObserver new_shell_observer; - - // Create dynamic popup. - if (!ExecuteJavaScript(render_view_host(), L"", L"OpenPopup();")) - return false; - - Shell* new_shell = new_shell_observer.GetShell(); - *title = new_shell->web_contents()->GetTitle(); - return true; - } - - std::string GetCookies(const GURL& url) { - return content::GetCookies( - shell()->web_contents()->GetBrowserContext(), url); - } - - bool got_downloads() const { return got_downloads_; } - - private: - bool got_downloads_; -}; - -// Test title for content created by javascript window.open(). -// See http://crbug.com/5988 -IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, DynamicTitle1) { - ASSERT_TRUE(test_server()->Start()); - - GURL url(test_server()->GetURL("files/dynamic1.html")); - string16 title; - ASSERT_TRUE(GetPopupTitle(url, &title)); - EXPECT_TRUE(StartsWith(title, ASCIIToUTF16("My Popup Title"), true)) - << "Actual title: " << title; -} - -// Test title for content created by javascript window.open(). -// See http://crbug.com/5988 -IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, DynamicTitle2) { - ASSERT_TRUE(test_server()->Start()); - - GURL url(test_server()->GetURL("files/dynamic2.html")); - string16 title; - ASSERT_TRUE(GetPopupTitle(url, &title)); - EXPECT_TRUE(StartsWith(title, ASCIIToUTF16("My Dynamic Title"), true)) - << "Actual title: " << title; -} - -IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, - SniffHTMLWithNoContentType) { - CheckTitleTest(GetMockURL("content-sniffer-test0.html"), - "Content Sniffer Test 0"); -} - -IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, - RespectNoSniffDirective) { - CheckTitleTest(GetMockURL("nosniff-test.html"), - "mock.http/nosniff-test.html"); -} - -IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, - DoNotSniffHTMLFromTextPlain) { - CheckTitleTest(GetMockURL("content-sniffer-test1.html"), - "mock.http/content-sniffer-test1.html"); -} - -IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, - DoNotSniffHTMLFromImageGIF) { - CheckTitleTest(GetMockURL("content-sniffer-test2.html"), - "mock.http/content-sniffer-test2.html"); -} - -IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, - SniffNoContentTypeNoData) { - // Make sure no downloads start. - BrowserContext::GetDownloadManager( - shell()->web_contents()->GetBrowserContext())->AddObserver(this); - CheckTitleTest(GetMockURL("content-sniffer-test3.html"), - "Content Sniffer Test 3"); - EXPECT_EQ(1u, Shell::windows().size()); - ASSERT_FALSE(got_downloads()); -} - -IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, - ContentDispositionEmpty) { - CheckTitleTest(GetMockURL("content-disposition-empty.html"), "success"); -} - -IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, - ContentDispositionInline) { - CheckTitleTest(GetMockURL("content-disposition-inline.html"), "success"); -} - -// Test for bug #1091358. -IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, SyncXMLHttpRequest) { - ASSERT_TRUE(test_server()->Start()); - NavigateToURL( - shell(), test_server()->GetURL("files/sync_xmlhttprequest.html")); - - // Let's check the XMLHttpRequest ran successfully. - bool success = false; - EXPECT_TRUE(ExecuteJavaScriptAndExtractBool( - shell()->web_contents()->GetRenderViewHost(), - L"", - L"window.domAutomationController.send(DidSyncRequestSucceed());", - &success)); - EXPECT_TRUE(success); -} - -// If this flakes, use http://crbug.com/62776. -IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, - SyncXMLHttpRequest_Disallowed) { - ASSERT_TRUE(test_server()->Start()); - NavigateToURL( - shell(), - test_server()->GetURL("files/sync_xmlhttprequest_disallowed.html")); - - // Let's check the XMLHttpRequest ran successfully. - bool success = false; - EXPECT_TRUE(ExecuteJavaScriptAndExtractBool( - shell()->web_contents()->GetRenderViewHost(), - L"", - L"window.domAutomationController.send(DidSucceed());", - &success)); - EXPECT_TRUE(success); -} - -// Test for bug #1159553 -- A synchronous xhr (whose content-type is -// downloadable) would trigger download and hang the renderer process, -// if executed while navigating to a new page. -// If this flakes, use http://crbug.com/56264. -IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, - SyncXMLHttpRequest_DuringUnload) { - ASSERT_TRUE(test_server()->Start()); - BrowserContext::GetDownloadManager( - shell()->web_contents()->GetBrowserContext())->AddObserver(this); - - CheckTitleTest( - test_server()->GetURL("files/sync_xmlhttprequest_during_unload.html"), - "sync xhr on unload"); - - // Navigate to a new page, to dispatch unload event and trigger xhr. - // (the bug would make this step hang the renderer). - CheckTitleTest( - test_server()->GetURL("files/title2.html"), "Title Of Awesomeness"); - - ASSERT_FALSE(got_downloads()); -} - -// Tests that onunload is run for cross-site requests. (Bug 1114994) -IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, - CrossSiteOnunloadCookie) { - ASSERT_TRUE(test_server()->Start()); - - GURL url = test_server()->GetURL("files/onunload_cookie.html"); - CheckTitleTest(url, "set cookie on unload"); - - // Navigate to a new cross-site page, to dispatch unload event and set the - // cookie. - CheckTitleTest(GetMockURL("content-sniffer-test0.html"), - "Content Sniffer Test 0"); - - // Check that the cookie was set. - EXPECT_EQ("onunloadCookie=foo", GetCookies(url)); -} - -// If this flakes, use http://crbug.com/130404 -// Tests that onunload is run for cross-site requests to URLs that complete -// without network loads (e.g., about:blank, data URLs). -IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, - DISABLED_CrossSiteImmediateLoadOnunloadCookie) { - ASSERT_TRUE(test_server()->Start()); - - GURL url = test_server()->GetURL("files/onunload_cookie.html"); - CheckTitleTest(url, "set cookie on unload"); - - // Navigate to a cross-site page that loads immediately without making a - // network request. The unload event should still be run. - NavigateToURL(shell(), GURL("about:blank")); - - // Check that the cookie was set. - EXPECT_EQ("onunloadCookie=foo", GetCookies(url)); -} - -// Tests that the unload handler is not run for 204 responses. -// If this flakes use http://crbug.com/80596. -IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, - CrossSiteNoUnloadOn204) { - ASSERT_TRUE(test_server()->Start()); - - // Start with a URL that sets a cookie in its unload handler. - GURL url = test_server()->GetURL("files/onunload_cookie.html"); - CheckTitleTest(url, "set cookie on unload"); - - // Navigate to a cross-site URL that returns a 204 No Content response. - NavigateToURL(shell(), test_server()->GetURL("nocontent")); - - // Check that the unload cookie was not set. - EXPECT_EQ("", GetCookies(url)); -} - -#if !defined(OS_MACOSX) -// Tests that the onbeforeunload and onunload logic is short-circuited if the -// old renderer is gone. In that case, we don't want to wait for the old -// renderer to run the handlers. -// We need to disable this on Mac because the crash causes the OS CrashReporter -// process to kick in to analyze the poor dead renderer. Unfortunately, if the -// app isn't stripped of debug symbols, this takes about five minutes to -// complete and isn't conducive to quick turnarounds. As we don't currently -// strip the app on the build bots, this is bad times. -IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, CrossSiteAfterCrash) { - // Cause the renderer to crash. - WindowedNotificationObserver crash_observer( - NOTIFICATION_RENDERER_PROCESS_CLOSED, - NotificationService::AllSources()); - NavigateToURL(shell(), GURL(chrome::kChromeUICrashURL)); - // Wait for browser to notice the renderer crash. - crash_observer.Wait(); - - // Navigate to a new cross-site page. The browser should not wait around for - // the old renderer's on{before}unload handlers to run. - CheckTitleTest(GetMockURL("content-sniffer-test0.html"), - "Content Sniffer Test 0"); -} -#endif // !defined(OS_MACOSX) - -// Tests that cross-site navigations work when the new page does not go through -// the BufferedEventHandler (e.g., non-http{s} URLs). (Bug 1225872) -IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, - CrossSiteNavigationNonBuffered) { - // Start with an HTTP page. - CheckTitleTest(GetMockURL("content-sniffer-test0.html"), - "Content Sniffer Test 0"); - - // Now load a file:// page, which does not use the BufferedEventHandler. - // Make sure that the page loads and displays a title, and doesn't get stuck. - GURL url = GetTestUrl("", "title2.html"); - CheckTitleTest(url, "Title Of Awesomeness"); -} - -// Tests that a cross-site navigation to an error page (resulting in the link -// doctor page) still runs the onunload handler and can support navigations -// away from the link doctor page. (Bug 1235537) -// Flaky: http://crbug.com/100823 -IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, - CrossSiteNavigationErrorPage) { - ASSERT_TRUE(test_server()->Start()); - - GURL url(test_server()->GetURL("files/onunload_cookie.html")); - CheckTitleTest(url, "set cookie on unload"); - - // Navigate to a new cross-site URL that results in an error. - // TODO(creis): If this causes crashes or hangs, it might be for the same - // reason as ErrorPageTest::DNSError. See bug 1199491 and - // http://crbug.com/22877. - GURL failed_url = URLRequestFailedJob::GetMockHttpUrl( - net::ERR_NAME_NOT_RESOLVED); - NavigateToURL(shell(), failed_url); - - EXPECT_NE(ASCIIToUTF16("set cookie on unload"), - shell()->web_contents()->GetTitle()); - - // Check that the cookie was set, meaning that the onunload handler ran. - EXPECT_EQ("onunloadCookie=foo", GetCookies(url)); - - // Check that renderer-initiated navigations still work. In a previous bug, - // the ResourceDispatcherHost would think that such navigations were - // cross-site, because we didn't clean up from the previous request. Since - // WebContentsImpl was in the NORMAL state, it would ignore the attempt to run - // the onunload handler, and the navigation would fail. We can't test by - // redirecting to javascript:window.location='someURL', since javascript: - // URLs are prohibited by policy from interacting with sensitive chrome - // pages of which the error page is one. Instead, use automation to kick - // off the navigation, and wait to see that the tab loads. - string16 expected_title16(ASCIIToUTF16("Title Of Awesomeness")); - TitleWatcher title_watcher(shell()->web_contents(), expected_title16); - - bool success; - GURL test_url(test_server()->GetURL("files/title2.html")); - std::string redirect_script = "window.location='" + - test_url.possibly_invalid_spec() + "';" + - "window.domAutomationController.send(true);"; - EXPECT_TRUE(ExecuteJavaScriptAndExtractBool( - shell()->web_contents()->GetRenderViewHost(), - L"", ASCIIToWide(redirect_script), &success)); - EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle()); -} - -IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, - CrossSiteNavigationErrorPage2) { - ASSERT_TRUE(test_server()->Start()); - - GURL url(test_server()->GetURL("files/title2.html")); - CheckTitleTest(url, "Title Of Awesomeness"); - - // Navigate to a new cross-site URL that results in an error. - // TODO(creis): If this causes crashes or hangs, it might be for the same - // reason as ErrorPageTest::DNSError. See bug 1199491 and - // http://crbug.com/22877. - GURL failed_url = URLRequestFailedJob::GetMockHttpUrl( - net::ERR_NAME_NOT_RESOLVED); - - NavigateToURL(shell(), failed_url); - EXPECT_NE(ASCIIToUTF16("Title Of Awesomeness"), - shell()->web_contents()->GetTitle()); - - // Repeat navigation. We are testing that this completes. - NavigateToURL(shell(), failed_url); - EXPECT_NE(ASCIIToUTF16("Title Of Awesomeness"), - shell()->web_contents()->GetTitle()); -} - -IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, - CrossOriginRedirectBlocked) { - // We expect the following URL requests from this test: - // 1- http://mock.http/cross-origin-redirect-blocked.html - // 2- http://mock.http/redirect-to-title2.html - // 3- http://mock.http/title2.html - // - // If the redirect in #2 were not blocked, we'd also see a request - // for http://mock.http:4000/title2.html, and the title would be different. - CheckTitleTest(GetMockURL("cross-origin-redirect-blocked.html"), - "Title Of More Awesomeness"); -} - -// Tests that ResourceRequestInfoImpl is updated correctly on failed -// requests, to prevent calling Read on a request that has already failed. -// See bug 40250. -IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, - CrossSiteFailedRequest) { - // Visit another URL first to trigger a cross-site navigation. - NavigateToURL(shell(), GetTestUrl("", "simple_page.html")); - - // Visit a URL that fails without calling ResourceDispatcherHost::Read. - GURL broken_url("chrome://theme"); - NavigateToURL(shell(), broken_url); -} - -} // namespace content diff --git a/content/browser/renderer_host/resource_dispatcher_host_impl.cc b/content/browser/renderer_host/resource_dispatcher_host_impl.cc deleted file mode 100644 index 111edc5..0000000 --- a/content/browser/renderer_host/resource_dispatcher_host_impl.cc +++ /dev/null @@ -1,1729 +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. - -// See http://dev.chromium.org/developers/design-documents/multi-process-resource-loading - -#include "content/browser/renderer_host/resource_dispatcher_host_impl.h" - -#include <set> -#include <vector> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/command_line.h" -#include "base/compiler_specific.h" -#include "base/debug/alias.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop.h" -#include "base/metrics/histogram.h" -#include "base/shared_memory.h" -#include "base/stl_util.h" -#include "base/third_party/dynamic_annotations/dynamic_annotations.h" -#include "content/browser/appcache/chrome_appcache_service.h" -#include "content/browser/cert_store_impl.h" -#include "content/browser/child_process_security_policy_impl.h" -#include "content/browser/cross_site_request_manager.h" -#include "content/browser/download/download_resource_handler.h" -#include "content/browser/download/save_file_manager.h" -#include "content/browser/download/save_file_resource_handler.h" -#include "content/browser/fileapi/chrome_blob_storage_context.h" -#include "content/browser/plugin_service_impl.h" -#include "content/browser/renderer_host/async_resource_handler.h" -#include "content/browser/renderer_host/buffered_resource_handler.h" -#include "content/browser/renderer_host/cross_site_resource_handler.h" -#include "content/browser/renderer_host/redirect_to_file_resource_handler.h" -#include "content/browser/renderer_host/render_view_host_delegate.h" -#include "content/browser/renderer_host/render_view_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/renderer_host/sync_resource_handler.h" -#include "content/browser/renderer_host/throttling_resource_handler.h" -#include "content/browser/renderer_host/transfer_navigation_resource_throttle.h" -#include "content/browser/resource_context_impl.h" -#include "content/browser/worker_host/worker_service_impl.h" -#include "content/common/resource_messages.h" -#include "content/common/ssl_status_serialization.h" -#include "content/common/view_messages.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/content_browser_client.h" -#include "content/public/browser/download_manager.h" -#include "content/public/browser/global_request_id.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/resource_dispatcher_host_delegate.h" -#include "content/public/browser/resource_request_details.h" -#include "content/public/browser/resource_throttle.h" -#include "content/public/browser/user_metrics.h" -#include "content/public/common/content_switches.h" -#include "content/public/common/process_type.h" -#include "content/public/common/url_constants.h" -#include "net/base/auth.h" -#include "net/base/cert_status_flags.h" -#include "net/base/load_flags.h" -#include "net/base/mime_util.h" -#include "net/base/net_errors.h" -#include "net/base/registry_controlled_domains/registry_controlled_domain.h" -#include "net/base/request_priority.h" -#include "net/base/ssl_cert_request_info.h" -#include "net/base/upload_data.h" -#include "net/cookies/cookie_monster.h" -#include "net/http/http_cache.h" -#include "net/http/http_response_headers.h" -#include "net/http/http_response_info.h" -#include "net/http/http_transaction_factory.h" -#include "net/url_request/url_request.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_job_factory.h" -#include "webkit/appcache/appcache_interceptor.h" -#include "webkit/appcache/appcache_interfaces.h" -#include "webkit/blob/blob_storage_controller.h" -#include "webkit/blob/shareable_file_reference.h" -#include "webkit/glue/resource_request_body.h" -#include "webkit/glue/webkit_glue.h" - -using base::Time; -using base::TimeDelta; -using base::TimeTicks; -using webkit_blob::ShareableFileReference; -using webkit_glue::ResourceRequestBody; - -// ---------------------------------------------------------------------------- - -namespace content { - -namespace { - -static ResourceDispatcherHostImpl* g_resource_dispatcher_host; - -// The interval for calls to ResourceDispatcherHostImpl::UpdateLoadStates -const int kUpdateLoadStatesIntervalMsec = 100; - -// Maximum byte "cost" of all the outstanding requests for a renderer. -// See delcaration of |max_outstanding_requests_cost_per_process_| for details. -// This bound is 25MB, which allows for around 6000 outstanding requests. -const int kMaxOutstandingRequestsCostPerProcess = 26214400; - -// The number of milliseconds after noting a user gesture that we will -// tag newly-created URLRequest objects with the -// net::LOAD_MAYBE_USER_GESTURE load flag. This is a fairly arbitrary -// guess at how long to expect direct impact from a user gesture, but -// this should be OK as the load flag is a best-effort thing only, -// rather than being intended as fully accurate. -const int kUserGestureWindowMs = 3500; - -// All possible error codes from the network module. Note that the error codes -// are all positive (since histograms expect positive sample values). -const int kAllNetErrorCodes[] = { -#define NET_ERROR(label, value) -(value), -#include "net/base/net_error_list.h" -#undef NET_ERROR -}; - -// Aborts a request before an URLRequest has actually been created. -void AbortRequestBeforeItStarts(ResourceMessageFilter* filter, - IPC::Message* sync_result, - int route_id, - int request_id) { - if (sync_result) { - SyncLoadResult result; - result.error_code = net::ERR_ABORTED; - ResourceHostMsg_SyncLoad::WriteReplyParams(sync_result, result); - filter->Send(sync_result); - } else { - // Tell the renderer that this request was disallowed. - filter->Send(new ResourceMsg_RequestComplete( - route_id, - request_id, - net::ERR_ABORTED, - false, - std::string(), // No security info needed, connection not established. - base::TimeTicks())); - } -} - -GURL MaybeStripReferrer(const GURL& possible_referrer) { - if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoReferrers)) - return GURL(); - return possible_referrer; -} - -// Consults the RendererSecurity policy to determine whether the -// ResourceDispatcherHostImpl should service this request. A request might be -// disallowed if the renderer is not authorized to retrieve the request URL or -// if the renderer is attempting to upload an unauthorized file. -bool ShouldServiceRequest(ProcessType process_type, - int child_id, - const ResourceHostMsg_Request& request_data) { - if (process_type == PROCESS_TYPE_PLUGIN) - return true; - - ChildProcessSecurityPolicyImpl* policy = - ChildProcessSecurityPolicyImpl::GetInstance(); - - // Check if the renderer is permitted to request the requested URL. - if (!policy->CanRequestURL(child_id, request_data.url)) { - VLOG(1) << "Denied unauthorized request for " - << request_data.url.possibly_invalid_spec(); - return false; - } - - // Check if the renderer is permitted to upload the requested files. - if (request_data.request_body) { - const std::vector<ResourceRequestBody::Element>* uploads = - request_data.request_body->elements(); - std::vector<ResourceRequestBody::Element>::const_iterator iter; - for (iter = uploads->begin(); iter != uploads->end(); ++iter) { - if (iter->type() == ResourceRequestBody::Element::TYPE_FILE && - !policy->CanReadFile(child_id, iter->path())) { - NOTREACHED() << "Denied unauthorized upload of " - << iter->path().value(); - return false; - } - } - } - - return true; -} - -void RemoveDownloadFileFromChildSecurityPolicy(int child_id, - const FilePath& path) { - ChildProcessSecurityPolicyImpl::GetInstance()->RevokeAllPermissionsForFile( - child_id, path); -} - -#if defined(OS_WIN) -#pragma warning(disable: 4748) -#pragma optimize("", off) -#endif - -#if defined(OS_WIN) -#pragma optimize("", on) -#pragma warning(default: 4748) -#endif - -net::RequestPriority DetermineRequestPriority(ResourceType::Type type) { - // Determine request priority based on how critical this resource typically - // is to user-perceived page load performance. Important considerations are: - // * Can this resource block the download of other resources. - // * Can this resource block the rendering of the page. - // * How useful is the page to the user if this resource is not loaded yet. - - switch (type) { - // Main frames are the highest priority because they can block nearly every - // type of other resource and there is no useful display without them. - // Sub frames are a close second, however it is a common pattern to wrap - // ads in an iframe or even in multiple nested iframes. It is worth - // investigating if there is a better priority for them. - case ResourceType::MAIN_FRAME: - case ResourceType::SUB_FRAME: - return net::HIGHEST; - - // Stylesheets and scripts can block rendering and loading of other - // resources. Fonts can block text from rendering. - case ResourceType::STYLESHEET: - case ResourceType::SCRIPT: - case ResourceType::FONT_RESOURCE: - return net::MEDIUM; - - // Sub resources, objects and media are lower priority than potentially - // blocking stylesheets, scripts and fonts, but are higher priority than - // images because if they exist they are probably more central to the page - // focus than images on the page. - case ResourceType::SUB_RESOURCE: - case ResourceType::OBJECT: - case ResourceType::MEDIA: - case ResourceType::WORKER: - case ResourceType::SHARED_WORKER: - case ResourceType::XHR: - return net::LOW; - - // Images are the "lowest" priority because they typically do not block - // downloads or rendering and most pages have some useful content without - // them. - case ResourceType::IMAGE: - // Favicons aren't required for rendering the current page, but - // are user visible. - case ResourceType::FAVICON: - return net::LOWEST; - - // Prefetches are at a lower priority than even LOWEST, since they are not - // even required for rendering of the current page. - case ResourceType::PREFETCH: - return net::IDLE; - - default: - // When new resource types are added, their priority must be considered. - NOTREACHED(); - return net::LOW; - } -} - -void OnSwapOutACKHelper(int render_process_id, - int render_view_id, - bool timed_out) { - RenderViewHostImpl* rvh = RenderViewHostImpl::FromID(render_process_id, - render_view_id); - if (rvh) - rvh->OnSwapOutACK(timed_out); -} - -net::Error CallbackAndReturn( - const DownloadResourceHandler::OnStartedCallback& started_cb, - net::Error net_error) { - if (started_cb.is_null()) - return net_error; - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(started_cb, static_cast<DownloadItem*>(NULL), net_error)); - - return net_error; -} - -int BuildLoadFlagsForRequest(const ResourceHostMsg_Request& request_data, - int child_id, bool is_sync_load) { - int load_flags = request_data.load_flags; - - // Although EV status is irrelevant to sub-frames and sub-resources, we have - // to perform EV certificate verification on all resources because an HTTP - // keep-alive connection created to load a sub-frame or a sub-resource could - // be reused to load a main frame. - load_flags |= net::LOAD_VERIFY_EV_CERT; - if (request_data.resource_type == ResourceType::MAIN_FRAME) { - load_flags |= net::LOAD_MAIN_FRAME; - } else if (request_data.resource_type == ResourceType::SUB_FRAME) { - load_flags |= net::LOAD_SUB_FRAME; - } else if (request_data.resource_type == ResourceType::PREFETCH) { - load_flags |= (net::LOAD_PREFETCH | net::LOAD_DO_NOT_PROMPT_FOR_LOGIN); - } else if (request_data.resource_type == ResourceType::FAVICON) { - load_flags |= net::LOAD_DO_NOT_PROMPT_FOR_LOGIN; - } - - if (is_sync_load) - load_flags |= net::LOAD_IGNORE_LIMITS; - - ChildProcessSecurityPolicyImpl* policy = - ChildProcessSecurityPolicyImpl::GetInstance(); - if (!policy->CanSendCookiesForOrigin(child_id, request_data.url)) { - load_flags |= (net::LOAD_DO_NOT_SEND_COOKIES | - net::LOAD_DO_NOT_SEND_AUTH_DATA | - net::LOAD_DO_NOT_SAVE_COOKIES); - } - - // Raw headers are sensitive, as they include Cookie/Set-Cookie, so only - // allow requesting them if requester has ReadRawCookies permission. - if ((load_flags & net::LOAD_REPORT_RAW_HEADERS) - && !policy->CanReadRawCookies(child_id)) { - VLOG(1) << "Denied unauthorized request for raw headers"; - load_flags &= ~net::LOAD_REPORT_RAW_HEADERS; - } - - return load_flags; -} - -int GetCertID(net::URLRequest* request, int child_id) { - if (request->ssl_info().cert) { - return CertStore::GetInstance()->StoreCert(request->ssl_info().cert, - child_id); - } - return 0; -} - -template <class T> -void NotifyOnUI(int type, int render_process_id, int render_view_id, - scoped_ptr<T> detail) { - RenderViewHostImpl* host = - RenderViewHostImpl::FromID(render_process_id, render_view_id); - if (host) { - RenderViewHostDelegate* delegate = host->GetDelegate(); - NotificationService::current()->Notify( - type, Source<WebContents>(delegate->GetAsWebContents()), - Details<T>(detail.get())); - } -} - -} // namespace - -// static -ResourceDispatcherHost* ResourceDispatcherHost::Get() { - return g_resource_dispatcher_host; -} - -ResourceDispatcherHostImpl::ResourceDispatcherHostImpl() - : save_file_manager_(new SaveFileManager()), - request_id_(-1), - is_shutdown_(false), - max_outstanding_requests_cost_per_process_( - kMaxOutstandingRequestsCostPerProcess), - filter_(NULL), - delegate_(NULL), - allow_cross_origin_auth_prompt_(false) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - DCHECK(!g_resource_dispatcher_host); - g_resource_dispatcher_host = this; - - GetContentClient()->browser()->ResourceDispatcherHostCreated(); - - ANNOTATE_BENIGN_RACE( - &last_user_gesture_time_, - "We don't care about the precise value, see http://crbug.com/92889"); - - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&appcache::AppCacheInterceptor::EnsureRegistered)); - - update_load_states_timer_.reset( - new base::RepeatingTimer<ResourceDispatcherHostImpl>()); -} - -ResourceDispatcherHostImpl::~ResourceDispatcherHostImpl() { - DCHECK(g_resource_dispatcher_host); - g_resource_dispatcher_host = NULL; -} - -// static -ResourceDispatcherHostImpl* ResourceDispatcherHostImpl::Get() { - return g_resource_dispatcher_host; -} - -void ResourceDispatcherHostImpl::SetDelegate( - ResourceDispatcherHostDelegate* delegate) { - delegate_ = delegate; -} - -void ResourceDispatcherHostImpl::SetAllowCrossOriginAuthPrompt(bool value) { - allow_cross_origin_auth_prompt_ = value; -} - -void ResourceDispatcherHostImpl::AddResourceContext(ResourceContext* context) { - active_resource_contexts_.insert(context); -} - -void ResourceDispatcherHostImpl::RemoveResourceContext( - ResourceContext* context) { - CHECK(ContainsKey(active_resource_contexts_, context)); - active_resource_contexts_.erase(context); -} - -void ResourceDispatcherHostImpl::CancelRequestsForContext( - ResourceContext* context) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - DCHECK(context); - - CHECK(ContainsKey(active_resource_contexts_, context)); - - // Note that request cancellation has side effects. Therefore, we gather all - // the requests to cancel first, and then we start cancelling. We assert at - // the end that there are no more to cancel since the context is about to go - // away. - typedef std::vector<linked_ptr<ResourceLoader> > LoaderList; - LoaderList loaders_to_cancel; - - for (LoaderMap::iterator i = pending_loaders_.begin(); - i != pending_loaders_.end();) { - if (i->second->GetRequestInfo()->GetContext() == context) { - loaders_to_cancel.push_back(i->second); - pending_loaders_.erase(i++); - } else { - ++i; - } - } - - for (BlockedLoadersMap::iterator i = blocked_loaders_map_.begin(); - i != blocked_loaders_map_.end();) { - BlockedLoadersList* loaders = i->second; - if (loaders->empty()) { - // This can happen if BlockRequestsForRoute() has been called for a route, - // but we haven't blocked any matching requests yet. - ++i; - continue; - } - ResourceRequestInfoImpl* info = loaders->front()->GetRequestInfo(); - if (info->GetContext() == context) { - blocked_loaders_map_.erase(i++); - for (BlockedLoadersList::const_iterator it = loaders->begin(); - it != loaders->end(); ++it) { - linked_ptr<ResourceLoader> loader = *it; - info = loader->GetRequestInfo(); - // We make the assumption that all requests on the list have the same - // ResourceContext. - DCHECK_EQ(context, info->GetContext()); - IncrementOutstandingRequestsMemoryCost(-1 * info->memory_cost(), - info->GetChildID()); - loaders_to_cancel.push_back(loader); - } - delete loaders; - } else { - ++i; - } - } - -#ifndef NDEBUG - for (LoaderList::iterator i = loaders_to_cancel.begin(); - i != loaders_to_cancel.end(); ++i) { - // There is no strict requirement that this be the case, but currently - // downloads and transferred requests are the only requests that aren't - // cancelled when the associated processes go away. It may be OK for this - // invariant to change in the future, but if this assertion fires without - // the invariant changing, then it's indicative of a leak. - DCHECK((*i)->GetRequestInfo()->is_download() || (*i)->is_transferring()); - } -#endif - - loaders_to_cancel.clear(); - - // Validate that no more requests for this context were added. - for (LoaderMap::const_iterator i = pending_loaders_.begin(); - i != pending_loaders_.end(); ++i) { - // http://crbug.com/90971 - CHECK_NE(i->second->GetRequestInfo()->GetContext(), context); - } - - for (BlockedLoadersMap::const_iterator i = blocked_loaders_map_.begin(); - i != blocked_loaders_map_.end(); ++i) { - BlockedLoadersList* loaders = i->second; - if (!loaders->empty()) { - ResourceRequestInfoImpl* info = loaders->front()->GetRequestInfo(); - // http://crbug.com/90971 - CHECK_NE(info->GetContext(), context); - } - } -} - -net::Error ResourceDispatcherHostImpl::BeginDownload( - scoped_ptr<net::URLRequest> request, - bool is_content_initiated, - ResourceContext* context, - int child_id, - int route_id, - bool prefer_cache, - scoped_ptr<DownloadSaveInfo> save_info, - const DownloadStartedCallback& started_callback) { - if (is_shutdown_) - return CallbackAndReturn(started_callback, net::ERR_INSUFFICIENT_RESOURCES); - - const GURL& url = request->original_url(); - - // http://crbug.com/90971 - char url_buf[128]; - base::strlcpy(url_buf, url.spec().c_str(), arraysize(url_buf)); - base::debug::Alias(url_buf); - CHECK(ContainsKey(active_resource_contexts_, context)); - - request->set_referrer(MaybeStripReferrer(GURL(request->referrer())).spec()); - int extra_load_flags = net::LOAD_IS_DOWNLOAD; - if (prefer_cache) { - // If there is upload data attached, only retrieve from cache because there - // is no current mechanism to prompt the user for their consent for a - // re-post. For GETs, try to retrieve data from the cache and skip - // validating the entry if present. - if (request->get_upload() != NULL) - extra_load_flags |= net::LOAD_ONLY_FROM_CACHE; - else - extra_load_flags |= net::LOAD_PREFERRING_CACHE; - } else { - extra_load_flags |= net::LOAD_DISABLE_CACHE; - } - request->set_load_flags(request->load_flags() | extra_load_flags); - // Check if the renderer is permitted to request the requested URL. - if (!ChildProcessSecurityPolicyImpl::GetInstance()-> - CanRequestURL(child_id, url)) { - VLOG(1) << "Denied unauthorized download request for " - << url.possibly_invalid_spec(); - return CallbackAndReturn(started_callback, net::ERR_ACCESS_DENIED); - } - - request_id_--; - - const net::URLRequestContext* request_context = context->GetRequestContext(); - if (!request_context->job_factory()->IsHandledURL(url)) { - VLOG(1) << "Download request for unsupported protocol: " - << url.possibly_invalid_spec(); - return CallbackAndReturn(started_callback, net::ERR_ACCESS_DENIED); - } - - ResourceRequestInfoImpl* extra_info = - CreateRequestInfo(child_id, route_id, true, context); - extra_info->AssociateWithRequest(request.get()); // Request takes ownership. - - // From this point forward, the |DownloadResourceHandler| is responsible for - // |started_callback|. - scoped_ptr<ResourceHandler> handler( - CreateResourceHandlerForDownload(request.get(), is_content_initiated, - save_info.Pass(), started_callback)); - - BeginRequestInternal(request.Pass(), handler.Pass()); - - return net::OK; -} - -void ResourceDispatcherHostImpl::ClearLoginDelegateForRequest( - net::URLRequest* request) { - ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); - if (info) { - ResourceLoader* loader = GetLoader(info->GetGlobalRequestID()); - if (loader) - loader->ClearLoginDelegate(); - } -} - -void ResourceDispatcherHostImpl::Shutdown() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - BrowserThread::PostTask(BrowserThread::IO, - FROM_HERE, - base::Bind(&ResourceDispatcherHostImpl::OnShutdown, - base::Unretained(this))); -} - -scoped_ptr<ResourceHandler> -ResourceDispatcherHostImpl::CreateResourceHandlerForDownload( - net::URLRequest* request, - bool is_content_initiated, - scoped_ptr<DownloadSaveInfo> save_info, - const DownloadResourceHandler::OnStartedCallback& started_cb) { - scoped_ptr<ResourceHandler> handler( - new DownloadResourceHandler(request, started_cb, save_info.Pass())); - if (delegate_) { - const ResourceRequestInfo* request_info( - ResourceRequestInfo::ForRequest(request)); - - ScopedVector<ResourceThrottle> throttles; - delegate_->DownloadStarting( - request, request_info->GetContext(), request_info->GetChildID(), - request_info->GetRouteID(), request_info->GetRequestID(), - is_content_initiated, &throttles); - if (!throttles.empty()) { - handler.reset( - new ThrottlingResourceHandler( - handler.Pass(), request_info->GetChildID(), - request_info->GetRequestID(), throttles.Pass())); - } - } - return handler.Pass(); -} - -void ResourceDispatcherHostImpl::ClearSSLClientAuthHandlerForRequest( - net::URLRequest* request) { - ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); - if (info) { - ResourceLoader* loader = GetLoader(info->GetGlobalRequestID()); - if (loader) - loader->ClearSSLClientAuthHandler(); - } -} - -ResourceDispatcherHostLoginDelegate* -ResourceDispatcherHostImpl::CreateLoginDelegate( - ResourceLoader* loader, - net::AuthChallengeInfo* auth_info) { - if (!delegate_) - return NULL; - - return delegate_->CreateLoginDelegate(auth_info, loader->request()); -} - -bool ResourceDispatcherHostImpl::AcceptAuthRequest( - ResourceLoader* loader, - net::AuthChallengeInfo* auth_info) { - if (delegate_ && !delegate_->AcceptAuthRequest(loader->request(), auth_info)) - return false; - - // Prevent third-party content from prompting for login, unless it is - // a proxy that is trying to authenticate. This is often the foundation - // of a scam to extract credentials for another domain from the user. - if (!auth_info->is_proxy) { - HttpAuthResourceType resource_type = - HttpAuthResourceTypeOf(loader->request()); - UMA_HISTOGRAM_ENUMERATION("Net.HttpAuthResource", - resource_type, - HTTP_AUTH_RESOURCE_LAST); - - if (resource_type == HTTP_AUTH_RESOURCE_BLOCKED_CROSS) - return false; - } - - return true; -} - -bool ResourceDispatcherHostImpl::AcceptSSLClientCertificateRequest( - ResourceLoader* loader, - net::SSLCertRequestInfo* cert_info) { - if (delegate_ && !delegate_->AcceptSSLClientCertificateRequest( - loader->request(), cert_info)) { - return false; - } - - return true; -} - -bool ResourceDispatcherHostImpl::HandleExternalProtocol(ResourceLoader* loader, - const GURL& url) { - if (!delegate_) - return false; - - ResourceRequestInfoImpl* info = loader->GetRequestInfo(); - - if (!ResourceType::IsFrame(info->GetResourceType())) - return false; - - const net::URLRequestJobFactory* job_factory = - info->GetContext()->GetRequestContext()->job_factory(); - if (job_factory->IsHandledURL(url)) - return false; - - return delegate_->HandleExternalProtocol(url, info->GetChildID(), - info->GetRouteID()); -} - -void ResourceDispatcherHostImpl::DidStartRequest(ResourceLoader* loader) { - // Make sure we have the load state monitor running - if (!update_load_states_timer_->IsRunning()) { - update_load_states_timer_->Start(FROM_HERE, - TimeDelta::FromMilliseconds(kUpdateLoadStatesIntervalMsec), - this, &ResourceDispatcherHostImpl::UpdateLoadStates); - } -} - -void ResourceDispatcherHostImpl::DidReceiveRedirect(ResourceLoader* loader, - const GURL& new_url) { - ResourceRequestInfoImpl* info = loader->GetRequestInfo(); - - int render_process_id, render_view_id; - if (!info->GetAssociatedRenderView(&render_process_id, &render_view_id)) - return; - - // Notify the observers on the UI thread. - scoped_ptr<ResourceRedirectDetails> detail(new ResourceRedirectDetails( - loader->request(), - GetCertID(loader->request(), info->GetChildID()), - new_url)); - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind( - &NotifyOnUI<ResourceRedirectDetails>, - static_cast<int>(NOTIFICATION_RESOURCE_RECEIVED_REDIRECT), - render_process_id, render_view_id, base::Passed(&detail))); -} - -void ResourceDispatcherHostImpl::DidReceiveResponse(ResourceLoader* loader) { - ResourceRequestInfoImpl* info = loader->GetRequestInfo(); - - int render_process_id, render_view_id; - if (!info->GetAssociatedRenderView(&render_process_id, &render_view_id)) - return; - - // Notify the observers on the UI thread. - scoped_ptr<ResourceRequestDetails> detail(new ResourceRequestDetails( - loader->request(), - GetCertID(loader->request(), info->GetChildID()))); - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind( - &NotifyOnUI<ResourceRequestDetails>, - static_cast<int>(NOTIFICATION_RESOURCE_RESPONSE_STARTED), - render_process_id, render_view_id, base::Passed(&detail))); -} - -void ResourceDispatcherHostImpl::DidFinishLoading(ResourceLoader* loader) { - ResourceRequestInfo* info = loader->GetRequestInfo(); - - // Record final result of all resource loads. - if (info->GetResourceType() == ResourceType::MAIN_FRAME) { - // This enumeration has "3" appended to its name to distinguish it from - // older versions. - UMA_HISTOGRAM_CUSTOM_ENUMERATION( - "Net.ErrorCodesForMainFrame3", - -loader->request()->status().error(), - base::CustomHistogram::ArrayToCustomRanges( - kAllNetErrorCodes, arraysize(kAllNetErrorCodes))); - - if (loader->request()->url().SchemeIsSecure() && - loader->request()->url().host() == "www.google.com") { - UMA_HISTOGRAM_CUSTOM_ENUMERATION( - "Net.ErrorCodesForHTTPSGoogleMainFrame2", - -loader->request()->status().error(), - base::CustomHistogram::ArrayToCustomRanges( - kAllNetErrorCodes, arraysize(kAllNetErrorCodes))); - } - } else { - // This enumeration has "2" appended to distinguish it from older versions. - UMA_HISTOGRAM_CUSTOM_ENUMERATION( - "Net.ErrorCodesForSubresources2", - -loader->request()->status().error(), - base::CustomHistogram::ArrayToCustomRanges( - kAllNetErrorCodes, arraysize(kAllNetErrorCodes))); - } - - // Destroy the ResourceLoader. - RemovePendingRequest(info->GetChildID(), info->GetRequestID()); -} - -// static -bool ResourceDispatcherHostImpl::RenderViewForRequest( - const net::URLRequest* request, - int* render_process_id, - int* render_view_id) { - const ResourceRequestInfoImpl* info = - ResourceRequestInfoImpl::ForRequest(request); - if (!info) { - *render_process_id = -1; - *render_view_id = -1; - return false; - } - - return info->GetAssociatedRenderView(render_process_id, render_view_id); -} - -void ResourceDispatcherHostImpl::OnShutdown() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - - is_shutdown_ = true; - pending_loaders_.clear(); - - // Make sure we shutdown the timer now, otherwise by the time our destructor - // runs if the timer is still running the Task is deleted twice (once by - // the MessageLoop and the second time by RepeatingTimer). - update_load_states_timer_.reset(); - - // Clear blocked requests if any left. - // Note that we have to do this in 2 passes as we cannot call - // CancelBlockedRequestsForRoute while iterating over - // blocked_loaders_map_, as it modifies it. - std::set<ProcessRouteIDs> ids; - for (BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.begin(); - iter != blocked_loaders_map_.end(); ++iter) { - std::pair<std::set<ProcessRouteIDs>::iterator, bool> result = - ids.insert(iter->first); - // We should not have duplicates. - DCHECK(result.second); - } - for (std::set<ProcessRouteIDs>::const_iterator iter = ids.begin(); - iter != ids.end(); ++iter) { - CancelBlockedRequestsForRoute(iter->first, iter->second); - } -} - -bool ResourceDispatcherHostImpl::OnMessageReceived( - const IPC::Message& message, - ResourceMessageFilter* filter, - bool* message_was_ok) { - filter_ = filter; - bool handled = true; - IPC_BEGIN_MESSAGE_MAP_EX(ResourceDispatcherHostImpl, message, *message_was_ok) - IPC_MESSAGE_HANDLER(ResourceHostMsg_RequestResource, OnRequestResource) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ResourceHostMsg_SyncLoad, OnSyncLoad) - IPC_MESSAGE_HANDLER(ResourceHostMsg_ReleaseDownloadedFile, - OnReleaseDownloadedFile) - IPC_MESSAGE_HANDLER(ResourceHostMsg_DataReceived_ACK, OnDataReceivedACK) - IPC_MESSAGE_HANDLER(ResourceHostMsg_DataDownloaded_ACK, OnDataDownloadedACK) - IPC_MESSAGE_HANDLER(ResourceHostMsg_UploadProgress_ACK, OnUploadProgressACK) - IPC_MESSAGE_HANDLER(ResourceHostMsg_CancelRequest, OnCancelRequest) - IPC_MESSAGE_HANDLER(ResourceHostMsg_FollowRedirect, OnFollowRedirect) - IPC_MESSAGE_HANDLER(ViewHostMsg_SwapOut_ACK, OnSwapOutACK) - IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache, - OnDidLoadResourceFromMemoryCache) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP_EX() - - if (message.type() == ViewHostMsg_DidLoadResourceFromMemoryCache::ID) { - // We just needed to peek at this message. We still want it to reach its - // normal destination. - handled = false; - } - - filter_ = NULL; - return handled; -} - -void ResourceDispatcherHostImpl::OnRequestResource( - const IPC::Message& message, - int request_id, - const ResourceHostMsg_Request& request_data) { - BeginRequest(request_id, request_data, NULL, message.routing_id()); -} - -// Begins a resource request with the given params on behalf of the specified -// child process. Responses will be dispatched through the given receiver. The -// process ID is used to lookup WebContentsImpl from routing_id's in the case of -// a request from a renderer. request_context is the cookie/cache context to be -// used for this request. -// -// If sync_result is non-null, then a SyncLoad reply will be generated, else -// a normal asynchronous set of response messages will be generated. -void ResourceDispatcherHostImpl::OnSyncLoad( - int request_id, - const ResourceHostMsg_Request& request_data, - IPC::Message* sync_result) { - BeginRequest(request_id, request_data, sync_result, - sync_result->routing_id()); -} - -void ResourceDispatcherHostImpl::BeginRequest( - int request_id, - const ResourceHostMsg_Request& request_data, - IPC::Message* sync_result, // only valid for sync - int route_id) { - ProcessType process_type = filter_->process_type(); - int child_id = filter_->child_id(); - - // If we crash here, figure out what URL the renderer was requesting. - // http://crbug.com/91398 - char url_buf[128]; - base::strlcpy(url_buf, request_data.url.spec().c_str(), arraysize(url_buf)); - base::debug::Alias(url_buf); - - // If the request that's coming in is being transferred from another process, - // we want to reuse and resume the old loader rather than start a new one. - linked_ptr<ResourceLoader> deferred_loader; - { - LoaderMap::iterator it = pending_loaders_.find( - GlobalRequestID(request_data.transferred_request_child_id, - request_data.transferred_request_request_id)); - if (it != pending_loaders_.end()) { - if (it->second->is_transferring()) { - deferred_loader = it->second; - pending_loaders_.erase(it); - } else { - RecordAction(UserMetricsAction("BadMessageTerminate_RDH")); - filter_->BadMessageReceived(); - return; - } - } - } - - ResourceContext* resource_context = filter_->resource_context(); - // http://crbug.com/90971 - CHECK(ContainsKey(active_resource_contexts_, resource_context)); - - if (is_shutdown_ || - !ShouldServiceRequest(process_type, child_id, request_data)) { - AbortRequestBeforeItStarts(filter_, sync_result, route_id, request_id); - return; - } - - const Referrer referrer(MaybeStripReferrer(request_data.referrer), - request_data.referrer_policy); - - // Allow the observer to block/handle the request. - if (delegate_ && !delegate_->ShouldBeginRequest(child_id, - route_id, - request_data.method, - request_data.url, - request_data.resource_type, - resource_context, - referrer)) { - AbortRequestBeforeItStarts(filter_, sync_result, route_id, request_id); - return; - } - - int load_flags = - BuildLoadFlagsForRequest(request_data, child_id, sync_result != NULL); - - // Construct the request. - scoped_ptr<net::URLRequest> new_request; - net::URLRequest* request; - if (deferred_loader.get()) { - request = deferred_loader->request(); - - // Give the ResourceLoader (or any of the ResourceHandlers held by it) a - // chance to reset some state before we complete the transfer. - deferred_loader->WillCompleteTransfer(); - } else { - net::URLRequestContext* context = - filter_->GetURLRequestContext(request_data.resource_type); - new_request.reset(context->CreateRequest(request_data.url, NULL)); - request = new_request.get(); - - request->set_method(request_data.method); - request->set_first_party_for_cookies(request_data.first_party_for_cookies); - request->set_referrer(referrer.url.spec()); - webkit_glue::ConfigureURLRequestForReferrerPolicy(request, - referrer.policy); - net::HttpRequestHeaders headers; - headers.AddHeadersFromString(request_data.headers); - request->SetExtraRequestHeaders(headers); - } - - // TODO(darin): Do we really need all of these URLRequest setters in the - // transferred navigation case? - - request->set_load_flags(load_flags); - - request->set_priority(DetermineRequestPriority(request_data.resource_type)); - - // Resolve elements from request_body and prepare upload data. - if (request_data.request_body) { - request->set_upload( - request_data.request_body->ResolveElementsAndCreateUploadData( - filter_->blob_storage_context()->controller())); - } - - bool allow_download = request_data.allow_download && - ResourceType::IsFrame(request_data.resource_type); - - // Make extra info and read footer (contains request ID). - ResourceRequestInfoImpl* extra_info = - new ResourceRequestInfoImpl( - process_type, - child_id, - route_id, - request_data.origin_pid, - request_id, - request_data.is_main_frame, - request_data.frame_id, - request_data.parent_is_main_frame, - request_data.parent_frame_id, - request_data.resource_type, - request_data.transition_type, - false, // is download - allow_download, - request_data.has_user_gesture, - request_data.referrer_policy, - resource_context); - extra_info->AssociateWithRequest(request); // Request takes ownership. - - if (request->url().SchemeIs(chrome::kBlobScheme)) { - // Hang on to a reference to ensure the blob is not released prior - // to the job being started. - extra_info->set_requested_blob_data( - filter_->blob_storage_context()->controller()-> - GetBlobDataFromUrl(request->url())); - } - - // Have the appcache associate its extra info with the request. - appcache::AppCacheInterceptor::SetExtraRequestInfo( - request, filter_->appcache_service(), child_id, - request_data.appcache_host_id, request_data.resource_type); - - // Construct the IPC resource handler. - scoped_ptr<ResourceHandler> handler; - if (sync_result) { - handler.reset(new SyncResourceHandler( - filter_, request, sync_result, this)); - } else { - handler.reset(new AsyncResourceHandler( - filter_, route_id, request, this)); - } - - // The RedirectToFileResourceHandler depends on being next in the chain. - if (request_data.download_to_file) { - handler.reset( - new RedirectToFileResourceHandler(handler.Pass(), child_id, this)); - } - - // Install a CrossSiteResourceHandler if this request is coming from a - // RenderViewHost with a pending cross-site request. We only check this for - // MAIN_FRAME requests. Unblock requests only come from a blocked page, do - // not count as cross-site, otherwise it gets blocked indefinitely. - if (request_data.resource_type == ResourceType::MAIN_FRAME && - process_type == PROCESS_TYPE_RENDERER && - CrossSiteRequestManager::GetInstance()-> - HasPendingCrossSiteRequest(child_id, route_id)) { - // Wrap the event handler to be sure the current page's onunload handler - // has a chance to run before we render the new page. - handler.reset(new CrossSiteResourceHandler(handler.Pass(), child_id, - route_id, request)); - } - - // Insert a buffered event handler before the actual one. - handler.reset( - new BufferedResourceHandler(handler.Pass(), this, request)); - - ScopedVector<ResourceThrottle> throttles; - if (delegate_) { - bool is_continuation_of_transferred_request = - (deferred_loader.get() != NULL); - - delegate_->RequestBeginning(request, - resource_context, - filter_->appcache_service(), - request_data.resource_type, - child_id, - route_id, - is_continuation_of_transferred_request, - &throttles); - } - - if (request_data.resource_type == ResourceType::MAIN_FRAME) { - throttles.insert( - throttles.begin(), - new TransferNavigationResourceThrottle(request)); - } - - if (!throttles.empty()) { - handler.reset( - new ThrottlingResourceHandler(handler.Pass(), child_id, request_id, - throttles.Pass())); - } - - if (deferred_loader.get()) { - pending_loaders_[extra_info->GetGlobalRequestID()] = deferred_loader; - deferred_loader->CompleteTransfer(handler.Pass()); - } else { - BeginRequestInternal(new_request.Pass(), handler.Pass()); - } -} - -void ResourceDispatcherHostImpl::OnReleaseDownloadedFile(int request_id) { - UnregisterDownloadedTempFile(filter_->child_id(), request_id); -} - -void ResourceDispatcherHostImpl::OnDataReceivedACK(int request_id) { - ResourceLoader* loader = GetLoader(filter_->child_id(), request_id); - if (!loader) - return; - - ResourceRequestInfoImpl* info = loader->GetRequestInfo(); - if (info->async_handler()) - info->async_handler()->OnDataReceivedACK(); -} - -void ResourceDispatcherHostImpl::OnDataDownloadedACK(int request_id) { - // TODO(michaeln): maybe throttle DataDownloaded messages -} - -void ResourceDispatcherHostImpl::RegisterDownloadedTempFile( - int child_id, int request_id, ShareableFileReference* reference) { - registered_temp_files_[child_id][request_id] = reference; - ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile( - child_id, reference->path()); - - // When the temp file is deleted, revoke permissions that the renderer has - // to that file. This covers an edge case where the file is deleted and then - // the same name is re-used for some other purpose, we don't want the old - // renderer to still have access to it. - // - // We do this when the file is deleted because the renderer can take a blob - // reference to the temp file that outlives the url loaded that it was - // loaded with to keep the file (and permissions) alive. - reference->AddFinalReleaseCallback( - base::Bind(&RemoveDownloadFileFromChildSecurityPolicy, - child_id)); -} - -void ResourceDispatcherHostImpl::UnregisterDownloadedTempFile( - int child_id, int request_id) { - DeletableFilesMap& map = registered_temp_files_[child_id]; - DeletableFilesMap::iterator found = map.find(request_id); - if (found == map.end()) - return; - - map.erase(found); - - // Note that we don't remove the security bits here. This will be done - // when all file refs are deleted (see RegisterDownloadedTempFile). -} - -bool ResourceDispatcherHostImpl::Send(IPC::Message* message) { - delete message; - return false; -} - -void ResourceDispatcherHostImpl::OnUploadProgressACK(int request_id) { - ResourceLoader* loader = GetLoader(filter_->child_id(), request_id); - if (loader) - loader->OnUploadProgressACK(); -} - -void ResourceDispatcherHostImpl::OnCancelRequest(int request_id) { - CancelRequest(filter_->child_id(), request_id, true); -} - -void ResourceDispatcherHostImpl::OnFollowRedirect( - int request_id, - bool has_new_first_party_for_cookies, - const GURL& new_first_party_for_cookies) { - ResourceLoader* loader = GetLoader(filter_->child_id(), request_id); - if (!loader) { - DVLOG(1) << "OnFollowRedirect for invalid request"; - return; - } - - ResourceRequestInfoImpl* info = loader->GetRequestInfo(); - if (info->async_handler()) { - info->async_handler()->OnFollowRedirect( - has_new_first_party_for_cookies, - new_first_party_for_cookies); - } -} - -ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo( - int child_id, - int route_id, - bool download, - ResourceContext* context) { - return new ResourceRequestInfoImpl( - PROCESS_TYPE_RENDERER, - child_id, - route_id, - 0, - request_id_, - false, // is_main_frame - -1, // frame_id - false, // parent_is_main_frame - -1, // parent_frame_id - ResourceType::SUB_RESOURCE, - PAGE_TRANSITION_LINK, - download, // is_download - download, // allow_download - false, // has_user_gesture - WebKit::WebReferrerPolicyDefault, - context); -} - - -void ResourceDispatcherHostImpl::OnSwapOutACK( - const ViewMsg_SwapOut_Params& params) { - HandleSwapOutACK(params, false); -} - -void ResourceDispatcherHostImpl::OnSimulateSwapOutACK( - const ViewMsg_SwapOut_Params& params) { - // Call the real implementation with true, which means that we timed out. - HandleSwapOutACK(params, true); -} - -void ResourceDispatcherHostImpl::HandleSwapOutACK( - const ViewMsg_SwapOut_Params& params, bool timed_out) { - // Closes for cross-site transitions are handled such that the cross-site - // transition continues. - ResourceLoader* loader = GetLoader(params.new_render_process_host_id, - params.new_request_id); - if (loader) { - // The response we were meant to resume could have already been canceled. - ResourceRequestInfoImpl* info = loader->GetRequestInfo(); - if (info->cross_site_handler()) - info->cross_site_handler()->ResumeResponse(); - } - - // Update the RenderViewHost's internal state after the ACK. - BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(&OnSwapOutACKHelper, - params.closing_process_id, - params.closing_route_id, - timed_out)); -} - -void ResourceDispatcherHostImpl::OnDidLoadResourceFromMemoryCache( - const GURL& url, - const std::string& security_info, - const std::string& http_method, - const std::string& mime_type, - ResourceType::Type resource_type) { - if (!url.is_valid() || !(url.SchemeIs("http") || url.SchemeIs("https"))) - return; - - filter_->GetURLRequestContext(resource_type)->http_transaction_factory()-> - GetCache()->OnExternalCacheHit(url, http_method); -} - -// This function is only used for saving feature. -void ResourceDispatcherHostImpl::BeginSaveFile( - const GURL& url, - const Referrer& referrer, - int child_id, - int route_id, - ResourceContext* context) { - if (is_shutdown_) - return; - - // http://crbug.com/90971 - char url_buf[128]; - base::strlcpy(url_buf, url.spec().c_str(), arraysize(url_buf)); - base::debug::Alias(url_buf); - CHECK(ContainsKey(active_resource_contexts_, context)); - - scoped_ptr<ResourceHandler> handler( - new SaveFileResourceHandler(child_id, - route_id, - url, - save_file_manager_.get())); - request_id_--; - - const net::URLRequestContext* request_context = context->GetRequestContext(); - bool known_proto = - request_context->job_factory()->IsHandledURL(url); - if (!known_proto) { - // Since any URLs which have non-standard scheme have been filtered - // by save manager(see GURL::SchemeIsStandard). This situation - // should not happen. - NOTREACHED(); - return; - } - - scoped_ptr<net::URLRequest> request( - request_context->CreateRequest(url, NULL)); - request->set_method("GET"); - request->set_referrer(MaybeStripReferrer(referrer.url).spec()); - webkit_glue::ConfigureURLRequestForReferrerPolicy(request.get(), - referrer.policy); - // So far, for saving page, we need fetch content from cache, in the - // future, maybe we can use a configuration to configure this behavior. - request->set_load_flags(net::LOAD_PREFERRING_CACHE); - - // Since we're just saving some resources we need, disallow downloading. - ResourceRequestInfoImpl* extra_info = - CreateRequestInfo(child_id, route_id, false, context); - extra_info->AssociateWithRequest(request.get()); // Request takes ownership. - - BeginRequestInternal(request.Pass(), handler.Pass()); -} - -void ResourceDispatcherHostImpl::MarkAsTransferredNavigation( - const GlobalRequestID& id) { - GetLoader(id)->MarkAsTransferring(); -} - -int ResourceDispatcherHostImpl::GetOutstandingRequestsMemoryCost( - int child_id) const { - OutstandingRequestsMemoryCostMap::const_iterator entry = - outstanding_requests_memory_cost_map_.find(child_id); - return (entry == outstanding_requests_memory_cost_map_.end()) ? - 0 : entry->second; -} - -// The object died, so cancel and detach all requests associated with it except -// for downloads, which belong to the browser process even if initiated via a -// renderer. -void ResourceDispatcherHostImpl::CancelRequestsForProcess(int child_id) { - CancelRequestsForRoute(child_id, -1 /* cancel all */); - registered_temp_files_.erase(child_id); -} - -void ResourceDispatcherHostImpl::CancelRequestsForRoute(int child_id, - int route_id) { - // Since pending_requests_ is a map, we first build up a list of all of the - // matching requests to be cancelled, and then we cancel them. Since there - // may be more than one request to cancel, we cannot simply hold onto the map - // iterators found in the first loop. - - // Find the global ID of all matching elements. - std::vector<GlobalRequestID> matching_requests; - for (LoaderMap::const_iterator i = pending_loaders_.begin(); - i != pending_loaders_.end(); ++i) { - if (i->first.child_id != child_id) - continue; - - ResourceRequestInfoImpl* info = i->second->GetRequestInfo(); - - GlobalRequestID id(child_id, i->first.request_id); - DCHECK(id == i->first); - - // Don't cancel navigations that are transferring to another process, - // since they belong to another process now. - if (!info->is_download() && !IsTransferredNavigation(id) && - (route_id == -1 || route_id == info->GetRouteID())) { - matching_requests.push_back(id); - } - } - - // Remove matches. - for (size_t i = 0; i < matching_requests.size(); ++i) { - LoaderMap::iterator iter = pending_loaders_.find(matching_requests[i]); - // Although every matching request was in pending_requests_ when we built - // matching_requests, it is normal for a matching request to be not found - // in pending_requests_ after we have removed some matching requests from - // pending_requests_. For example, deleting a net::URLRequest that has - // exclusive (write) access to an HTTP cache entry may unblock another - // net::URLRequest that needs exclusive access to the same cache entry, and - // that net::URLRequest may complete and remove itself from - // pending_requests_. So we need to check that iter is not equal to - // pending_requests_.end(). - if (iter != pending_loaders_.end()) - RemovePendingLoader(iter); - } - - // Now deal with blocked requests if any. - if (route_id != -1) { - if (blocked_loaders_map_.find(ProcessRouteIDs(child_id, route_id)) != - blocked_loaders_map_.end()) { - CancelBlockedRequestsForRoute(child_id, route_id); - } - } else { - // We have to do all render views for the process |child_id|. - // Note that we have to do this in 2 passes as we cannot call - // CancelBlockedRequestsForRoute while iterating over - // blocked_loaders_map_, as it modifies it. - std::set<int> route_ids; - for (BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.begin(); - iter != blocked_loaders_map_.end(); ++iter) { - if (iter->first.first == child_id) - route_ids.insert(iter->first.second); - } - for (std::set<int>::const_iterator iter = route_ids.begin(); - iter != route_ids.end(); ++iter) { - CancelBlockedRequestsForRoute(child_id, *iter); - } - } -} - -// Cancels the request and removes it from the list. -void ResourceDispatcherHostImpl::RemovePendingRequest(int child_id, - int request_id) { - LoaderMap::iterator i = pending_loaders_.find( - GlobalRequestID(child_id, request_id)); - if (i == pending_loaders_.end()) { - NOTREACHED() << "Trying to remove a request that's not here"; - return; - } - RemovePendingLoader(i); -} - -void ResourceDispatcherHostImpl::RemovePendingLoader( - const LoaderMap::iterator& iter) { - ResourceRequestInfoImpl* info = iter->second->GetRequestInfo(); - - // Remove the memory credit that we added when pushing the request onto - // the pending list. - IncrementOutstandingRequestsMemoryCost(-1 * info->memory_cost(), - info->GetChildID()); - - pending_loaders_.erase(iter); - - // If we have no more pending requests, then stop the load state monitor - if (pending_loaders_.empty() && update_load_states_timer_.get()) - update_load_states_timer_->Stop(); -} - -void ResourceDispatcherHostImpl::CancelRequest(int child_id, - int request_id, - bool from_renderer) { - if (from_renderer) { - // When the old renderer dies, it sends a message to us to cancel its - // requests. - if (IsTransferredNavigation(GlobalRequestID(child_id, request_id))) - return; - } - - ResourceLoader* loader = GetLoader(child_id, request_id); - if (!loader) { - // We probably want to remove this warning eventually, but I wanted to be - // able to notice when this happens during initial development since it - // should be rare and may indicate a bug. - DVLOG(1) << "Canceling a request that wasn't found"; - return; - } - - loader->CancelRequest(from_renderer); -} - -int ResourceDispatcherHostImpl::IncrementOutstandingRequestsMemoryCost( - int cost, - int child_id) { - // Retrieve the previous value (defaulting to 0 if not found). - OutstandingRequestsMemoryCostMap::iterator prev_entry = - outstanding_requests_memory_cost_map_.find(child_id); - int new_cost = 0; - if (prev_entry != outstanding_requests_memory_cost_map_.end()) - new_cost = prev_entry->second; - - // Insert/update the total; delete entries when their value reaches 0. - new_cost += cost; - CHECK(new_cost >= 0); - if (new_cost == 0) - outstanding_requests_memory_cost_map_.erase(child_id); - else - outstanding_requests_memory_cost_map_[child_id] = new_cost; - - return new_cost; -} - -// static -int ResourceDispatcherHostImpl::CalculateApproximateMemoryCost( - net::URLRequest* request) { - // The following fields should be a minor size contribution (experimentally - // on the order of 100). However since they are variable length, it could - // in theory be a sizeable contribution. - int strings_cost = request->extra_request_headers().ToString().size() + - request->original_url().spec().size() + - request->referrer().size() + - request->method().size(); - - // Note that this expression will typically be dominated by: - // |kAvgBytesPerOutstandingRequest|. - return kAvgBytesPerOutstandingRequest + strings_cost; -} - -void ResourceDispatcherHostImpl::BeginRequestInternal( - scoped_ptr<net::URLRequest> request, - scoped_ptr<ResourceHandler> handler) { - DCHECK(!request->is_pending()); - ResourceRequestInfoImpl* info = - ResourceRequestInfoImpl::ForRequest(request.get()); - - if ((TimeTicks::Now() - last_user_gesture_time_) < - TimeDelta::FromMilliseconds(kUserGestureWindowMs)) { - request->set_load_flags( - request->load_flags() | net::LOAD_MAYBE_USER_GESTURE); - } - - // Add the memory estimate that starting this request will consume. - info->set_memory_cost(CalculateApproximateMemoryCost(request.get())); - int memory_cost = IncrementOutstandingRequestsMemoryCost(info->memory_cost(), - info->GetChildID()); - - // If enqueing/starting this request will exceed our per-process memory - // bound, abort it right away. - if (memory_cost > max_outstanding_requests_cost_per_process_) { - // We call "CancelWithError()" as a way of setting the net::URLRequest's - // status -- it has no effect beyond this, since the request hasn't started. - request->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES); - - if (!handler->OnResponseCompleted(info->GetRequestID(), request->status(), - std::string())) { - // TODO(darin): The handler is not ready for us to kill the request. Oops! - NOTREACHED(); - } - - IncrementOutstandingRequestsMemoryCost(-1 * info->memory_cost(), - info->GetChildID()); - - // A ResourceHandler must not outlive its associated URLRequest. - handler.reset(); - return; - } - - linked_ptr<ResourceLoader> loader( - new ResourceLoader(request.Pass(), handler.Pass(), this)); - - ProcessRouteIDs pair_id(info->GetChildID(), info->GetRouteID()); - BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.find(pair_id); - if (iter != blocked_loaders_map_.end()) { - // The request should be blocked. - iter->second->push_back(loader); - return; - } - - StartLoading(info, loader); -} - -void ResourceDispatcherHostImpl::StartLoading( - ResourceRequestInfoImpl* info, - const linked_ptr<ResourceLoader>& loader) { - pending_loaders_[info->GetGlobalRequestID()] = loader; - - loader->StartRequest(); -} - -void ResourceDispatcherHostImpl::OnUserGesture(WebContentsImpl* contents) { - last_user_gesture_time_ = TimeTicks::Now(); -} - -net::URLRequest* ResourceDispatcherHostImpl::GetURLRequest( - const GlobalRequestID& id) { - ResourceLoader* loader = GetLoader(id); - if (!loader) - return NULL; - - return loader->request(); -} - -namespace { - -// This function attempts to return the "more interesting" load state of |a| -// and |b|. We don't have temporal information about these load states -// (meaning we don't know when we transitioned into these states), so we just -// rank them according to how "interesting" the states are. -// -// We take advantage of the fact that the load states are an enumeration listed -// in the order in which they occur during the lifetime of a request, so we can -// regard states with larger numeric values as being further along toward -// completion. We regard those states as more interesting to report since they -// represent progress. -// -// For example, by this measure "tranferring data" is a more interesting state -// than "resolving host" because when we are transferring data we are actually -// doing something that corresponds to changes that the user might observe, -// whereas waiting for a host name to resolve implies being stuck. -// -const net::LoadStateWithParam& MoreInterestingLoadState( - const net::LoadStateWithParam& a, const net::LoadStateWithParam& b) { - return (a.state < b.state) ? b : a; -} - -// Carries information about a load state change. -struct LoadInfo { - GURL url; - net::LoadStateWithParam load_state; - uint64 upload_position; - uint64 upload_size; -}; - -// Map from ProcessID+ViewID pair to LoadState -typedef std::map<std::pair<int, int>, LoadInfo> LoadInfoMap; - -// Used to marshal calls to LoadStateChanged from the IO to UI threads. We do -// them all as a single callback to avoid spamming the UI thread. -void LoadInfoUpdateCallback(const LoadInfoMap& info_map) { - LoadInfoMap::const_iterator i; - for (i = info_map.begin(); i != info_map.end(); ++i) { - RenderViewHostImpl* view = - RenderViewHostImpl::FromID(i->first.first, i->first.second); - if (view) // The view could be gone at this point. - view->LoadStateChanged(i->second.url, i->second.load_state, - i->second.upload_position, - i->second.upload_size); - } -} - -} // namespace - -void ResourceDispatcherHostImpl::UpdateLoadStates() { - // Populate this map with load state changes, and then send them on to the UI - // thread where they can be passed along to the respective RVHs. - LoadInfoMap info_map; - - LoaderMap::const_iterator i; - - // Determine the largest upload size of all requests - // in each View (good chance it's zero). - std::map<std::pair<int, int>, uint64> largest_upload_size; - for (i = pending_loaders_.begin(); i != pending_loaders_.end(); ++i) { - net::URLRequest* request = i->second->request(); - ResourceRequestInfoImpl* info = i->second->GetRequestInfo(); - uint64 upload_size = request->GetUploadProgress().size(); - if (request->GetLoadState().state != net::LOAD_STATE_SENDING_REQUEST) - upload_size = 0; - std::pair<int, int> key(info->GetChildID(), info->GetRouteID()); - if (upload_size && largest_upload_size[key] < upload_size) - largest_upload_size[key] = upload_size; - } - - for (i = pending_loaders_.begin(); i != pending_loaders_.end(); ++i) { - net::URLRequest* request = i->second->request(); - ResourceRequestInfoImpl* info = i->second->GetRequestInfo(); - net::LoadStateWithParam load_state = request->GetLoadState(); - net::UploadProgress progress = request->GetUploadProgress(); - - // We also poll for upload progress on this timer and send upload - // progress ipc messages to the plugin process. - i->second->ReportUploadProgress(); - - std::pair<int, int> key(info->GetChildID(), info->GetRouteID()); - - // If a request is uploading data, ignore all other requests so that the - // upload progress takes priority for being shown in the status bar. - if (largest_upload_size.find(key) != largest_upload_size.end() && - progress.size() < largest_upload_size[key]) - continue; - - net::LoadStateWithParam to_insert = load_state; - LoadInfoMap::iterator existing = info_map.find(key); - if (existing != info_map.end()) { - to_insert = - MoreInterestingLoadState(existing->second.load_state, load_state); - if (to_insert.state == existing->second.load_state.state) - continue; - } - LoadInfo& load_info = info_map[key]; - load_info.url = request->url(); - load_info.load_state = to_insert; - load_info.upload_size = progress.size(); - load_info.upload_position = progress.position(); - } - - if (info_map.empty()) - return; - - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&LoadInfoUpdateCallback, info_map)); -} - -void ResourceDispatcherHostImpl::BlockRequestsForRoute(int child_id, - int route_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - ProcessRouteIDs key(child_id, route_id); - DCHECK(blocked_loaders_map_.find(key) == blocked_loaders_map_.end()) << - "BlockRequestsForRoute called multiple time for the same RVH"; - blocked_loaders_map_[key] = new BlockedLoadersList(); -} - -void ResourceDispatcherHostImpl::ResumeBlockedRequestsForRoute(int child_id, - int route_id) { - ProcessBlockedRequestsForRoute(child_id, route_id, false); -} - -void ResourceDispatcherHostImpl::CancelBlockedRequestsForRoute(int child_id, - int route_id) { - ProcessBlockedRequestsForRoute(child_id, route_id, true); -} - -void ResourceDispatcherHostImpl::ProcessBlockedRequestsForRoute( - int child_id, - int route_id, - bool cancel_requests) { - BlockedLoadersMap::iterator iter = blocked_loaders_map_.find( - std::pair<int, int>(child_id, route_id)); - if (iter == blocked_loaders_map_.end()) { - // It's possible to reach here if the renderer crashed while an interstitial - // page was showing. - return; - } - - BlockedLoadersList* loaders = iter->second; - - // Removing the vector from the map unblocks any subsequent requests. - blocked_loaders_map_.erase(iter); - - for (BlockedLoadersList::iterator loaders_iter = loaders->begin(); - loaders_iter != loaders->end(); ++loaders_iter) { - linked_ptr<ResourceLoader> loader = *loaders_iter; - ResourceRequestInfoImpl* info = loader->GetRequestInfo(); - if (cancel_requests) { - IncrementOutstandingRequestsMemoryCost(-1 * info->memory_cost(), - info->GetChildID()); - } else { - StartLoading(info, loader); - } - } - - delete loaders; -} - -ResourceDispatcherHostImpl::HttpAuthResourceType -ResourceDispatcherHostImpl::HttpAuthResourceTypeOf(net::URLRequest* request) { - // Use the same critera as for cookies to determine the sub-resource type - // that is requesting to be authenticated. - if (!request->first_party_for_cookies().is_valid()) - return HTTP_AUTH_RESOURCE_TOP; - - if (net::RegistryControlledDomainService::SameDomainOrHost( - request->first_party_for_cookies(), request->url())) - return HTTP_AUTH_RESOURCE_SAME_DOMAIN; - - if (allow_cross_origin_auth_prompt()) - return HTTP_AUTH_RESOURCE_ALLOWED_CROSS; - - return HTTP_AUTH_RESOURCE_BLOCKED_CROSS; -} - -bool ResourceDispatcherHostImpl::allow_cross_origin_auth_prompt() { - return allow_cross_origin_auth_prompt_; -} - -bool ResourceDispatcherHostImpl::IsTransferredNavigation( - const GlobalRequestID& id) const { - ResourceLoader* loader = GetLoader(id); - return loader ? loader->is_transferring() : false; -} - -ResourceLoader* ResourceDispatcherHostImpl::GetLoader( - const GlobalRequestID& id) const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - - LoaderMap::const_iterator i = pending_loaders_.find(id); - if (i == pending_loaders_.end()) - return NULL; - - return i->second.get(); -} - -ResourceLoader* ResourceDispatcherHostImpl::GetLoader(int child_id, - int request_id) const { - return GetLoader(GlobalRequestID(child_id, request_id)); -} - -} // namespace content diff --git a/content/browser/renderer_host/resource_dispatcher_host_impl.h b/content/browser/renderer_host/resource_dispatcher_host_impl.h deleted file mode 100644 index a3c134f..0000000 --- a/content/browser/renderer_host/resource_dispatcher_host_impl.h +++ /dev/null @@ -1,421 +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. - -// This is the browser side of the resource dispatcher, it receives requests -// from the child process (i.e. [Renderer, Plugin, Worker]ProcessHost), and -// dispatches them to URLRequests. It then forwards the messages from the -// URLRequests back to the correct process for handling. -// -// See http://dev.chromium.org/developers/design-documents/multi-process-resource-loading - -#ifndef CONTENT_BROWSER_RENDERER_HOST_RESOURCE_DISPATCHER_HOST_IMPL_H_ -#define CONTENT_BROWSER_RENDERER_HOST_RESOURCE_DISPATCHER_HOST_IMPL_H_ - -#include <map> -#include <set> -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/gtest_prod_util.h" -#include "base/memory/linked_ptr.h" -#include "base/memory/scoped_ptr.h" -#include "base/time.h" -#include "base/timer.h" -#include "content/browser/download/download_resource_handler.h" -#include "content/browser/renderer_host/resource_loader.h" -#include "content/browser/renderer_host/resource_loader_delegate.h" -#include "content/common/content_export.h" -#include "content/public/browser/child_process_data.h" -#include "content/public/browser/notification_types.h" -#include "content/public/browser/resource_dispatcher_host.h" -#include "ipc/ipc_message.h" -#include "net/cookies/canonical_cookie.h" -#include "net/url_request/url_request.h" -#include "webkit/glue/resource_type.h" - -class ResourceHandler; -struct ResourceHostMsg_Request; -struct ViewMsg_SwapOut_Params; - -namespace net { -class URLRequestJobFactory; -} - -namespace webkit_blob { -class ShareableFileReference; -} - -namespace content { -class ResourceContext; -class ResourceDispatcherHostDelegate; -class ResourceMessageFilter; -class ResourceRequestInfoImpl; -class SaveFileManager; -class WebContentsImpl; -struct DownloadSaveInfo; -struct GlobalRequestID; -struct Referrer; - -class CONTENT_EXPORT ResourceDispatcherHostImpl - : public ResourceDispatcherHost, - public ResourceLoaderDelegate { - public: - ResourceDispatcherHostImpl(); - virtual ~ResourceDispatcherHostImpl(); - - // Returns the current ResourceDispatcherHostImpl. May return NULL if it - // hasn't been created yet. - static ResourceDispatcherHostImpl* Get(); - - // ResourceDispatcherHost implementation: - virtual void SetDelegate(ResourceDispatcherHostDelegate* delegate) OVERRIDE; - virtual void SetAllowCrossOriginAuthPrompt(bool value) OVERRIDE; - virtual net::Error BeginDownload( - scoped_ptr<net::URLRequest> request, - bool is_content_initiated, - ResourceContext* context, - int child_id, - int route_id, - bool prefer_cache, - scoped_ptr<DownloadSaveInfo> save_info, - const DownloadStartedCallback& started_callback) OVERRIDE; - virtual void ClearLoginDelegateForRequest(net::URLRequest* request) OVERRIDE; - virtual void BlockRequestsForRoute(int child_id, int route_id) OVERRIDE; - virtual void ResumeBlockedRequestsForRoute( - int child_id, int route_id) OVERRIDE; - - // Puts the resource dispatcher host in an inactive state (unable to begin - // new requests). Cancels all pending requests. - void Shutdown(); - - // Notify the ResourceDispatcherHostImpl of a new resource context. - void AddResourceContext(ResourceContext* context); - - // Notify the ResourceDispatcherHostImpl of a resource context destruction. - void RemoveResourceContext(ResourceContext* context); - - // Force cancels any pending requests for the given |context|. This is - // necessary to ensure that before |context| goes away, all requests - // for it are dead. - void CancelRequestsForContext(ResourceContext* context); - - // Returns true if the message was a resource message that was processed. - // If it was, message_was_ok will be false iff the message was corrupt. - bool OnMessageReceived(const IPC::Message& message, - ResourceMessageFilter* filter, - bool* message_was_ok); - - // Initiates a save file from the browser process (as opposed to a resource - // request from the renderer or another child process). - void BeginSaveFile(const GURL& url, - const Referrer& referrer, - int child_id, - int route_id, - ResourceContext* context); - - // Cancels the given request if it still exists. We ignore cancels from the - // renderer in the event of a download. - void CancelRequest(int child_id, - int request_id, - bool from_renderer); - - // Marks the request as "parked". This happens if a request is - // redirected cross-site and needs to be resumed by a new render view. - void MarkAsTransferredNavigation(const GlobalRequestID& id); - - // Returns the number of pending requests. This is designed for the unittests - int pending_requests() const { - return static_cast<int>(pending_loaders_.size()); - } - - // Intended for unit-tests only. Returns the memory cost of all the - // outstanding requests (pending and blocked) for |child_id|. - int GetOutstandingRequestsMemoryCost(int child_id) const; - - // Intended for unit-tests only. Overrides the outstanding requests bound. - void set_max_outstanding_requests_cost_per_process(int limit) { - max_outstanding_requests_cost_per_process_ = limit; - } - - // The average private bytes increase of the browser for each new pending - // request. Experimentally obtained. - static const int kAvgBytesPerOutstandingRequest = 4400; - - SaveFileManager* save_file_manager() const { - return save_file_manager_; - } - - // Called when the unload handler for a cross-site request has finished. - void OnSwapOutACK(const ViewMsg_SwapOut_Params& params); - - // Called when we want to simulate the renderer process sending - // ViewHostMsg_SwapOut_ACK in cases where the renderer has died or is - // unresponsive. - void OnSimulateSwapOutACK(const ViewMsg_SwapOut_Params& params); - - // Called when the renderer loads a resource from its internal cache. - void OnDidLoadResourceFromMemoryCache(const GURL& url, - const std::string& security_info, - const std::string& http_method, - const std::string& mime_type, - ResourceType::Type resource_type); - - // Force cancels any pending requests for the given process. - void CancelRequestsForProcess(int child_id); - - // Force cancels any pending requests for the given route id. This method - // acts like CancelRequestsForProcess when route_id is -1. - void CancelRequestsForRoute(int child_id, int route_id); - - void OnUserGesture(WebContentsImpl* contents); - - // Retrieves a net::URLRequest. Must be called from the IO thread. - net::URLRequest* GetURLRequest(const GlobalRequestID& request_id); - - void RemovePendingRequest(int child_id, int request_id); - - // Cancels any blocked request for the specified route id. - void CancelBlockedRequestsForRoute(int child_id, int route_id); - - // Maintains a collection of temp files created in support of - // the download_to_file capability. Used to grant access to the - // child process and to defer deletion of the file until it's - // no longer needed. - void RegisterDownloadedTempFile( - int child_id, int request_id, - webkit_blob::ShareableFileReference* reference); - void UnregisterDownloadedTempFile(int child_id, int request_id); - - // Needed for the sync IPC message dispatcher macros. - bool Send(IPC::Message* message); - - // Indicates whether third-party sub-content can pop-up HTTP basic auth - // dialog boxes. - bool allow_cross_origin_auth_prompt(); - - ResourceDispatcherHostDelegate* delegate() { - return delegate_; - } - - // Must be called after the ResourceRequestInfo has been created - // and associated with the request. - scoped_ptr<ResourceHandler> CreateResourceHandlerForDownload( - net::URLRequest* request, - bool is_content_initiated, - scoped_ptr<DownloadSaveInfo> save_info, - const DownloadResourceHandler::OnStartedCallback& started_cb); - - void ClearSSLClientAuthHandlerForRequest(net::URLRequest* request); - - private: - FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest, - TestBlockedRequestsProcessDies); - FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest, - IncrementOutstandingRequestsMemoryCost); - FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest, - CalculateApproximateMemoryCost); - - class ShutdownTask; - - friend class ShutdownTask; - - // ResourceLoaderDelegate implementation: - virtual ResourceDispatcherHostLoginDelegate* CreateLoginDelegate( - ResourceLoader* loader, - net::AuthChallengeInfo* auth_info) OVERRIDE; - virtual bool AcceptAuthRequest( - ResourceLoader* loader, - net::AuthChallengeInfo* auth_info) OVERRIDE; - virtual bool AcceptSSLClientCertificateRequest( - ResourceLoader* loader, - net::SSLCertRequestInfo* cert_info) OVERRIDE; - virtual bool HandleExternalProtocol(ResourceLoader* loader, - const GURL& url) OVERRIDE; - virtual void DidStartRequest(ResourceLoader* loader) OVERRIDE; - virtual void DidReceiveRedirect(ResourceLoader* loader, - const GURL& new_url) OVERRIDE; - virtual void DidReceiveResponse(ResourceLoader* loader) OVERRIDE; - virtual void DidFinishLoading(ResourceLoader* loader) OVERRIDE; - - // Extracts the render view/process host's identifiers from the given request - // and places them in the given out params (both required). If there are no - // such IDs associated with the request (such as non-page-related requests), - // this function will return false and both out params will be -1. - static bool RenderViewForRequest(const net::URLRequest* request, - int* render_process_host_id, - int* render_view_host_id); - - // A shutdown helper that runs on the IO thread. - void OnShutdown(); - - // The real implementation of the OnSwapOutACK logic. OnSwapOutACK and - // OnSimulateSwapOutACK just call this method, supplying the |timed_out| - // parameter, which indicates whether the call is due to a timeout while - // waiting for SwapOut acknowledgement from the renderer process. - void HandleSwapOutACK(const ViewMsg_SwapOut_Params& params, bool timed_out); - - // Helper function for regular and download requests. - void BeginRequestInternal(scoped_ptr<net::URLRequest> request, - scoped_ptr<ResourceHandler> handler); - - void StartLoading(ResourceRequestInfoImpl* info, - const linked_ptr<ResourceLoader>& loader); - - // Updates the "cost" of outstanding requests for |child_id|. - // The "cost" approximates how many bytes are consumed by all the in-memory - // data structures supporting this request (net::URLRequest object, - // HttpNetworkTransaction, etc...). - // The value of |cost| is added to the running total, and the resulting - // sum is returned. - int IncrementOutstandingRequestsMemoryCost(int cost, - int child_id); - - // Estimate how much heap space |request| will consume to run. - static int CalculateApproximateMemoryCost(net::URLRequest* request); - - // The list of all requests that we have pending. This list is not really - // optimized, and assumes that we have relatively few requests pending at once - // since some operations require brute-force searching of the list. - // - // It may be enhanced in the future to provide some kind of prioritization - // mechanism. We should also consider a hashtable or binary tree if it turns - // out we have a lot of things here. - typedef std::map<GlobalRequestID, linked_ptr<ResourceLoader> > LoaderMap; - - // Deletes the pending request identified by the iterator passed in. - // This function will invalidate the iterator passed in. Callers should - // not rely on this iterator being valid on return. - void RemovePendingLoader(const LoaderMap::iterator& iter); - - // Checks all pending requests and updates the load states and upload - // progress if necessary. - void UpdateLoadStates(); - - // Resumes or cancels (if |cancel_requests| is true) any blocked requests. - void ProcessBlockedRequestsForRoute(int child_id, - int route_id, - bool cancel_requests); - - void OnRequestResource(const IPC::Message& msg, - int request_id, - const ResourceHostMsg_Request& request_data); - void OnSyncLoad(int request_id, - const ResourceHostMsg_Request& request_data, - IPC::Message* sync_result); - void BeginRequest(int request_id, - const ResourceHostMsg_Request& request_data, - IPC::Message* sync_result, // only valid for sync - int route_id); // only valid for async - void OnDataReceivedACK(int request_id); - void OnDataDownloadedACK(int request_id); - void OnUploadProgressACK(int request_id); - void OnCancelRequest(int request_id); - void OnFollowRedirect(int request_id, - bool has_new_first_party_for_cookies, - const GURL& new_first_party_for_cookies); - void OnReleaseDownloadedFile(int request_id); - - // Creates ResourceRequestInfoImpl for a download or page save. - // |download| should be true if the request is a file download. - ResourceRequestInfoImpl* CreateRequestInfo( - int child_id, - int route_id, - bool download, - ResourceContext* context); - - // Relationship of resource being authenticated with the top level page. - enum HttpAuthResourceType { - HTTP_AUTH_RESOURCE_TOP, // Top-level page itself - HTTP_AUTH_RESOURCE_SAME_DOMAIN, // Sub-content from same domain - HTTP_AUTH_RESOURCE_BLOCKED_CROSS, // Blocked Sub-content from cross domain - HTTP_AUTH_RESOURCE_ALLOWED_CROSS, // Allowed Sub-content per command line - HTTP_AUTH_RESOURCE_LAST - }; - - HttpAuthResourceType HttpAuthResourceTypeOf(net::URLRequest* request); - - // Returns whether the URLRequest identified by |transferred_request_id| is - // currently in the process of being transferred to a different renderer. - // This happens if a request is redirected cross-site and needs to be resumed - // by a new render view. - bool IsTransferredNavigation( - const GlobalRequestID& transferred_request_id) const; - - ResourceLoader* GetLoader(const GlobalRequestID& id) const; - ResourceLoader* GetLoader(int child_id, int request_id) const; - - LoaderMap pending_loaders_; - - // Collection of temp files downloaded for child processes via - // the download_to_file mechanism. We avoid deleting them until - // the client no longer needs them. - typedef std::map<int, scoped_refptr<webkit_blob::ShareableFileReference> > - DeletableFilesMap; // key is request id - typedef std::map<int, DeletableFilesMap> - RegisteredTempFiles; // key is child process id - RegisteredTempFiles registered_temp_files_; - - // A timer that periodically calls UpdateLoadStates while pending_requests_ - // is not empty. - scoped_ptr<base::RepeatingTimer<ResourceDispatcherHostImpl> > - update_load_states_timer_; - - // We own the save file manager. - scoped_refptr<SaveFileManager> save_file_manager_; - - // Request ID for browser initiated requests. request_ids generated by - // child processes are counted up from 0, while browser created requests - // start at -2 and go down from there. (We need to start at -2 because -1 is - // used as a special value all over the resource_dispatcher_host for - // uninitialized variables.) This way, we no longer have the unlikely (but - // observed in the real world!) event where we have two requests with the same - // request_id_. - int request_id_; - - // True if the resource dispatcher host has been shut down. - bool is_shutdown_; - - typedef std::vector<linked_ptr<ResourceLoader> > BlockedLoadersList; - typedef std::pair<int, int> ProcessRouteIDs; - typedef std::map<ProcessRouteIDs, BlockedLoadersList*> BlockedLoadersMap; - BlockedLoadersMap blocked_loaders_map_; - - // Maps the child_ids to the approximate number of bytes - // being used to service its resource requests. No entry implies 0 cost. - typedef std::map<int, int> OutstandingRequestsMemoryCostMap; - OutstandingRequestsMemoryCostMap outstanding_requests_memory_cost_map_; - - // |max_outstanding_requests_cost_per_process_| is the upper bound on how - // many outstanding requests can be issued per child process host. - // The constraint is expressed in terms of bytes (where the cost of - // individual requests is given by CalculateApproximateMemoryCost). - // The total number of outstanding requests is roughly: - // (max_outstanding_requests_cost_per_process_ / - // kAvgBytesPerOutstandingRequest) - int max_outstanding_requests_cost_per_process_; - - // Time of the last user gesture. Stored so that we can add a load - // flag to requests occurring soon after a gesture to indicate they - // may be because of explicit user action. - base::TimeTicks last_user_gesture_time_; - - // Used during IPC message dispatching so that the handlers can get a pointer - // to the source of the message. - ResourceMessageFilter* filter_; - - ResourceDispatcherHostDelegate* delegate_; - - bool allow_cross_origin_auth_prompt_; - - // http://crbug.com/90971 - Assists in tracking down use-after-frees on - // shutdown. - std::set<const ResourceContext*> active_resource_contexts_; - - DISALLOW_COPY_AND_ASSIGN(ResourceDispatcherHostImpl); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_RESOURCE_DISPATCHER_HOST_IMPL_H_ diff --git a/content/browser/renderer_host/resource_dispatcher_host_unittest.cc b/content/browser/renderer_host/resource_dispatcher_host_unittest.cc deleted file mode 100644 index 437b611..0000000 --- a/content/browser/renderer_host/resource_dispatcher_host_unittest.cc +++ /dev/null @@ -1,1958 +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/resource_dispatcher_host_impl.h" - -#include <vector> - -#include "base/bind.h" -#include "base/file_path.h" -#include "base/memory/scoped_vector.h" -#include "base/message_loop.h" -#include "base/process_util.h" -#include "base/string_number_conversions.h" -#include "base/string_split.h" -#include "content/browser/browser_thread_impl.h" -#include "content/browser/child_process_security_policy_impl.h" -#include "content/browser/renderer_host/resource_dispatcher_host_impl.h" -#include "content/browser/renderer_host/resource_message_filter.h" -#include "content/common/child_process_host_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_context.h" -#include "content/public/browser/resource_dispatcher_host_delegate.h" -#include "content/public/browser/resource_throttle.h" -#include "content/public/common/resource_response.h" -#include "content/public/test/test_browser_context.h" -#include "content/test/test_content_browser_client.h" -#include "net/base/net_errors.h" -#include "net/base/upload_data.h" -#include "net/http/http_util.h" -#include "net/url_request/url_request.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_job.h" -#include "net/url_request/url_request_simple_job.h" -#include "net/url_request/url_request_test_job.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "webkit/appcache/appcache_interfaces.h" - -// TODO(eroman): Write unit tests for SafeBrowsing that exercise -// SafeBrowsingResourceHandler. - -namespace content { - -namespace { - -// Returns the resource response header structure for this request. -void GetResponseHead(const std::vector<IPC::Message>& messages, - ResourceResponseHead* response_head) { - ASSERT_GE(messages.size(), 2U); - - // The first messages should be received response. - ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, messages[0].type()); - - PickleIterator iter(messages[0]); - int request_id; - ASSERT_TRUE(IPC::ReadParam(&messages[0], &iter, &request_id)); - ASSERT_TRUE(IPC::ReadParam(&messages[0], &iter, response_head)); -} - -void GenerateIPCMessage( - scoped_refptr<ResourceMessageFilter> filter, - scoped_ptr<IPC::Message> message) { - bool msg_is_ok; - ResourceDispatcherHostImpl::Get()->OnMessageReceived( - *message, filter.get(), &msg_is_ok); -} - -} // namespace - -static int RequestIDForMessage(const IPC::Message& msg) { - int request_id = -1; - switch (msg.type()) { - case ResourceMsg_UploadProgress::ID: - case ResourceMsg_ReceivedResponse::ID: - case ResourceMsg_ReceivedRedirect::ID: - case ResourceMsg_SetDataBuffer::ID: - case ResourceMsg_DataReceived::ID: - case ResourceMsg_RequestComplete::ID: - request_id = IPC::MessageIterator(msg).NextInt(); - break; - } - return request_id; -} - -static ResourceHostMsg_Request CreateResourceRequest( - const char* method, - ResourceType::Type type, - const GURL& url) { - ResourceHostMsg_Request request; - request.method = std::string(method); - request.url = url; - request.first_party_for_cookies = url; // bypass third-party cookie blocking - request.referrer_policy = WebKit::WebReferrerPolicyDefault; - request.load_flags = 0; - request.origin_pid = 0; - request.resource_type = type; - request.request_context = 0; - request.appcache_host_id = appcache::kNoHostId; - request.download_to_file = false; - request.is_main_frame = true; - request.frame_id = 0; - request.parent_is_main_frame = false; - request.parent_frame_id = -1; - request.transition_type = PAGE_TRANSITION_LINK; - request.allow_download = true; - return request; -} - -// Spin up the message loop to kick off the request. -static void KickOffRequest() { - MessageLoop::current()->RunUntilIdle(); -} - -// We may want to move this to a shared space if it is useful for something else -class ResourceIPCAccumulator { - public: - void AddMessage(const IPC::Message& msg) { - messages_.push_back(msg); - } - - // This groups the messages by their request ID. The groups will be in order - // that the first message for each request ID was received, and the messages - // within the groups will be in the order that they appeared. - // Note that this clears messages_. - typedef std::vector< std::vector<IPC::Message> > ClassifiedMessages; - void GetClassifiedMessages(ClassifiedMessages* msgs); - - private: - std::vector<IPC::Message> messages_; -}; - -// This is very inefficient as a result of repeatedly extracting the ID, use -// only for tests! -void ResourceIPCAccumulator::GetClassifiedMessages(ClassifiedMessages* msgs) { - while (!messages_.empty()) { - // Ignore unknown message types as it is valid for code to generated other - // IPCs as side-effects that we are not testing here. - int cur_id = RequestIDForMessage(messages_[0]); - if (cur_id != -1) { - std::vector<IPC::Message> cur_requests; - cur_requests.push_back(messages_[0]); - // find all other messages with this ID - for (int i = 1; i < static_cast<int>(messages_.size()); i++) { - int id = RequestIDForMessage(messages_[i]); - if (id == cur_id) { - cur_requests.push_back(messages_[i]); - messages_.erase(messages_.begin() + i); - i--; - } - } - msgs->push_back(cur_requests); - } - messages_.erase(messages_.begin()); - } -} - -class MockURLRequestContextSelector - : public ResourceMessageFilter::URLRequestContextSelector { - public: - explicit MockURLRequestContextSelector( - net::URLRequestContext* request_context) - : request_context_(request_context) {} - - virtual net::URLRequestContext* GetRequestContext( - ResourceType::Type request_type) { - return request_context_; - } - - private: - net::URLRequestContext* const request_context_; -}; - -// This class forwards the incoming messages to the ResourceDispatcherHostTest. -// This is used to emulate different sub-processes, since this filter will -// have a different ID than the original. For the test, we want all the incoming -// messages to go to the same place, which is why this forwards. -class ForwardingFilter : public ResourceMessageFilter { - public: - explicit ForwardingFilter(IPC::Sender* dest, - ResourceContext* resource_context) - : ResourceMessageFilter( - ChildProcessHostImpl::GenerateChildProcessUniqueId(), - PROCESS_TYPE_RENDERER, - resource_context, NULL, NULL, - new MockURLRequestContextSelector( - resource_context->GetRequestContext())), - dest_(dest) { - OnChannelConnected(base::GetCurrentProcId()); - } - - // ResourceMessageFilter override - virtual bool Send(IPC::Message* msg) { - if (!dest_) - return false; - return dest_->Send(msg); - } - - protected: - virtual ~ForwardingFilter() {} - - private: - IPC::Sender* dest_; - - DISALLOW_COPY_AND_ASSIGN(ForwardingFilter); -}; - -// This class is a variation on URLRequestTestJob in that it does -// not complete start upon entry, only when specifically told to. -class URLRequestTestDelayedStartJob : public net::URLRequestTestJob { - public: - URLRequestTestDelayedStartJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate) - : net::URLRequestTestJob(request, network_delegate) { - Init(); - } - URLRequestTestDelayedStartJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate, - bool auto_advance) - : net::URLRequestTestJob(request, network_delegate, auto_advance) { - Init(); - } - URLRequestTestDelayedStartJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate, - const std::string& response_headers, - const std::string& response_data, - bool auto_advance) - : net::URLRequestTestJob(request, - network_delegate, - response_headers, - response_data, - auto_advance) { - Init(); - } - - // Do nothing until you're told to. - virtual void Start() {} - - // Finish starting a URL request whose job is an instance of - // URLRequestTestDelayedStartJob. It is illegal to call this routine - // with a URLRequest that does not use URLRequestTestDelayedStartJob. - static void CompleteStart(net::URLRequest* request) { - for (URLRequestTestDelayedStartJob* job = list_head_; - job; - job = job->next_) { - if (job->request() == request) { - job->net::URLRequestTestJob::Start(); - return; - } - } - NOTREACHED(); - } - - static bool DelayedStartQueueEmpty() { - return !list_head_; - } - - static void ClearQueue() { - if (list_head_) { - LOG(ERROR) - << "Unreleased entries on URLRequestTestDelayedStartJob delay queue" - << "; may result in leaks."; - list_head_ = NULL; - } - } - - protected: - virtual ~URLRequestTestDelayedStartJob() { - for (URLRequestTestDelayedStartJob** job = &list_head_; *job; - job = &(*job)->next_) { - if (*job == this) { - *job = (*job)->next_; - return; - } - } - NOTREACHED(); - } - - private: - void Init() { - next_ = list_head_; - list_head_ = this; - } - - static URLRequestTestDelayedStartJob* list_head_; - URLRequestTestDelayedStartJob* next_; -}; - -URLRequestTestDelayedStartJob* -URLRequestTestDelayedStartJob::list_head_ = NULL; - -// This class is a variation on URLRequestTestJob in that it -// returns IO_pending errors before every read, not just the first one. -class URLRequestTestDelayedCompletionJob : public net::URLRequestTestJob { - public: - URLRequestTestDelayedCompletionJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate) - : net::URLRequestTestJob(request, network_delegate) {} - URLRequestTestDelayedCompletionJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate, - bool auto_advance) - : net::URLRequestTestJob(request, network_delegate, auto_advance) {} - URLRequestTestDelayedCompletionJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate, - const std::string& response_headers, - const std::string& response_data, - bool auto_advance) - : net::URLRequestTestJob(request, - network_delegate, - response_headers, - response_data, - auto_advance) {} - - protected: - ~URLRequestTestDelayedCompletionJob() {} - - private: - virtual bool NextReadAsync() OVERRIDE { return true; } -}; - -class URLRequestBigJob : public net::URLRequestSimpleJob { - public: - URLRequestBigJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate) - : net::URLRequestSimpleJob(request, network_delegate) { - } - - virtual int GetData(std::string* mime_type, - std::string* charset, - std::string* data, - const net::CompletionCallback& callback) const OVERRIDE { - *mime_type = "text/plain"; - *charset = "UTF-8"; - - std::string text; - int count; - if (!ParseURL(request_->url(), &text, &count)) - return net::ERR_INVALID_URL; - - data->reserve(text.size() * count); - for (int i = 0; i < count; ++i) - data->append(text); - - return net::OK; - } - - private: - virtual ~URLRequestBigJob() {} - - // big-job:substring,N - static bool ParseURL(const GURL& url, std::string* text, int* count) { - std::vector<std::string> parts; - base::SplitString(url.path(), ',', &parts); - - if (parts.size() != 2) - return false; - - *text = parts[0]; - return base::StringToInt(parts[1], count); - } -}; - -// Associated with an URLRequest to determine if the URLRequest gets deleted. -class TestUserData : public base::SupportsUserData::Data { - public: - explicit TestUserData(bool* was_deleted) - : was_deleted_(was_deleted) { - } - - ~TestUserData() { - *was_deleted_ = true; - } - - private: - bool* was_deleted_; -}; - -class TransfersAllNavigationsContentBrowserClient - : public TestContentBrowserClient { - public: - virtual bool ShouldSwapProcessesForRedirect(ResourceContext* resource_context, - const GURL& current_url, - const GURL& new_url) { - return true; - } -}; - -enum GenericResourceThrottleFlags { - NONE = 0, - DEFER_STARTING_REQUEST = 1 << 0, - DEFER_PROCESSING_RESPONSE = 1 << 1, - CANCEL_BEFORE_START = 1 << 2 -}; - -// Throttle that tracks the current throttle blocking a request. Only one -// can throttle any request at a time. -class GenericResourceThrottle : public ResourceThrottle { - public: - // The value is used to indicate that the throttle should not provide - // a error code when cancelling a request. net::OK is used, because this - // is not an error code. - static const int USE_DEFAULT_CANCEL_ERROR_CODE = net::OK; - - GenericResourceThrottle(int flags, int code) - : flags_(flags), - error_code_for_cancellation_(code) { - } - - virtual ~GenericResourceThrottle() { - if (active_throttle_ == this) - active_throttle_ = NULL; - } - - // ResourceThrottle implementation: - virtual void WillStartRequest(bool* defer) OVERRIDE { - ASSERT_EQ(NULL, active_throttle_); - if (flags_ & DEFER_STARTING_REQUEST) { - active_throttle_ = this; - *defer = true; - } - - if (flags_ & CANCEL_BEFORE_START) { - if (error_code_for_cancellation_ == USE_DEFAULT_CANCEL_ERROR_CODE) { - controller()->Cancel(); - } else { - controller()->CancelWithError(error_code_for_cancellation_); - } - } - } - - virtual void WillProcessResponse(bool* defer) OVERRIDE { - ASSERT_EQ(NULL, active_throttle_); - if (flags_ & DEFER_PROCESSING_RESPONSE) { - active_throttle_ = this; - *defer = true; - } - } - - void Resume() { - ASSERT_TRUE(this == active_throttle_); - active_throttle_ = NULL; - controller()->Resume(); - } - - static GenericResourceThrottle* active_throttle() { - return active_throttle_; - } - - private: - int flags_; // bit-wise union of GenericResourceThrottleFlags. - int error_code_for_cancellation_; - - // The currently active throttle, if any. - static GenericResourceThrottle* active_throttle_; -}; -// static -GenericResourceThrottle* GenericResourceThrottle::active_throttle_ = NULL; - -class TestResourceDispatcherHostDelegate - : public ResourceDispatcherHostDelegate { - public: - TestResourceDispatcherHostDelegate() - : create_two_throttles_(false), - flags_(NONE), - error_code_for_cancellation_( - GenericResourceThrottle::USE_DEFAULT_CANCEL_ERROR_CODE) { - } - - void set_url_request_user_data(base::SupportsUserData::Data* user_data) { - user_data_.reset(user_data); - } - - void set_flags(int value) { - flags_ = value; - } - - void set_error_code_for_cancellation(int code) { - error_code_for_cancellation_ = code; - } - - void set_create_two_throttles(bool create_two_throttles) { - create_two_throttles_ = create_two_throttles; - } - - // ResourceDispatcherHostDelegate implementation: - - virtual void RequestBeginning( - net::URLRequest* request, - ResourceContext* resource_context, - appcache::AppCacheService* appcache_service, - ResourceType::Type resource_type, - int child_id, - int route_id, - bool is_continuation_of_transferred_request, - ScopedVector<ResourceThrottle>* throttles) OVERRIDE { - if (user_data_.get()) { - const void* key = user_data_.get(); - request->SetUserData(key, user_data_.release()); - } - - if (flags_ != NONE) { - throttles->push_back(new GenericResourceThrottle( - flags_, error_code_for_cancellation_)); - if (create_two_throttles_) - throttles->push_back(new GenericResourceThrottle( - flags_, error_code_for_cancellation_)); - } - } - - private: - bool create_two_throttles_; - int flags_; - int error_code_for_cancellation_; - scoped_ptr<base::SupportsUserData::Data> user_data_; -}; - -class ResourceDispatcherHostTest : public testing::Test, - public IPC::Sender { - public: - ResourceDispatcherHostTest() - : ui_thread_(BrowserThread::UI, &message_loop_), - file_thread_(BrowserThread::FILE_USER_BLOCKING, &message_loop_), - cache_thread_(BrowserThread::CACHE, &message_loop_), - io_thread_(BrowserThread::IO, &message_loop_), - old_factory_(NULL), - resource_type_(ResourceType::SUB_RESOURCE), - send_data_received_acks_(false) { - browser_context_.reset(new TestBrowserContext()); - BrowserContext::EnsureResourceContextInitialized(browser_context_.get()); - message_loop_.RunUntilIdle(); - filter_ = new ForwardingFilter( - this, browser_context_->GetResourceContext()); - } - // IPC::Sender implementation - virtual bool Send(IPC::Message* msg) { - accum_.AddMessage(*msg); - - if (send_data_received_acks_ && - msg->type() == ResourceMsg_DataReceived::ID) { - GenerateDataReceivedACK(*msg); - } - - delete msg; - return true; - } - - protected: - // testing::Test - virtual void SetUp() { - DCHECK(!test_fixture_); - test_fixture_ = this; - ChildProcessSecurityPolicyImpl::GetInstance()->Add(0); - net::URLRequest::Deprecated::RegisterProtocolFactory( - "test", - &ResourceDispatcherHostTest::Factory); - EnsureTestSchemeIsAllowed(); - delay_start_ = false; - delay_complete_ = false; - url_request_jobs_created_count_ = 0; - } - - virtual void TearDown() { - net::URLRequest::Deprecated::RegisterProtocolFactory("test", NULL); - if (!scheme_.empty()) - net::URLRequest::Deprecated::RegisterProtocolFactory( - scheme_, old_factory_); - - EXPECT_TRUE(URLRequestTestDelayedStartJob::DelayedStartQueueEmpty()); - URLRequestTestDelayedStartJob::ClearQueue(); - - DCHECK(test_fixture_ == this); - test_fixture_ = NULL; - - host_.Shutdown(); - - ChildProcessSecurityPolicyImpl::GetInstance()->Remove(0); - - // Flush the message loop to make application verifiers happy. - if (ResourceDispatcherHostImpl::Get()) - ResourceDispatcherHostImpl::Get()->CancelRequestsForContext( - browser_context_->GetResourceContext()); - browser_context_.reset(); - message_loop_.RunUntilIdle(); - } - - // Creates a request using the current test object as the filter. - void MakeTestRequest(int render_view_id, - int request_id, - const GURL& url); - - // Generates a request using the given filter. This will probably be a - // ForwardingFilter. - void MakeTestRequest(ResourceMessageFilter* filter, - int render_view_id, - int request_id, - const GURL& url); - - void CancelRequest(int request_id); - - void CompleteStartRequest(int request_id); - void CompleteStartRequest(ResourceMessageFilter* filter, int request_id); - - void EnsureSchemeIsAllowed(const std::string& scheme) { - ChildProcessSecurityPolicyImpl* policy = - ChildProcessSecurityPolicyImpl::GetInstance(); - if (!policy->IsWebSafeScheme(scheme)) - policy->RegisterWebSafeScheme(scheme); - } - - void EnsureTestSchemeIsAllowed() { - EnsureSchemeIsAllowed("test"); - } - - // Sets a particular response for any request from now on. To switch back to - // the default bahavior, pass an empty |headers|. |headers| should be raw- - // formatted (NULLs instead of EOLs). - void SetResponse(const std::string& headers, const std::string& data) { - response_headers_ = net::HttpUtil::AssembleRawHeaders(headers.data(), - headers.size()); - response_data_ = data; - } - void SetResponse(const std::string& headers) { - SetResponse(headers, std::string()); - } - - // Sets a particular resource type for any request from now on. - void SetResourceType(ResourceType::Type type) { - resource_type_ = type; - } - - void SendDataReceivedACKs(bool send_acks) { - send_data_received_acks_ = send_acks; - } - - // Intercepts requests for the given protocol. - void HandleScheme(const std::string& scheme) { - DCHECK(scheme_.empty()); - DCHECK(!old_factory_); - scheme_ = scheme; - old_factory_ = net::URLRequest::Deprecated::RegisterProtocolFactory( - scheme_, &ResourceDispatcherHostTest::Factory); - EnsureSchemeIsAllowed(scheme); - } - - // Our own net::URLRequestJob factory. - static net::URLRequestJob* Factory(net::URLRequest* request, - net::NetworkDelegate* network_delegate, - const std::string& scheme) { - url_request_jobs_created_count_++; - if (test_fixture_->response_headers_.empty()) { - if (delay_start_) { - return new URLRequestTestDelayedStartJob(request, network_delegate); - } else if (delay_complete_) { - return new URLRequestTestDelayedCompletionJob(request, - network_delegate); - } else if (scheme == "big-job") { - return new URLRequestBigJob(request, network_delegate); - } else { - return new net::URLRequestTestJob(request, network_delegate); - } - } else { - if (delay_start_) { - return new URLRequestTestDelayedStartJob( - request, network_delegate, - test_fixture_->response_headers_, test_fixture_->response_data_, - false); - } else if (delay_complete_) { - return new URLRequestTestDelayedCompletionJob( - request, network_delegate, - test_fixture_->response_headers_, test_fixture_->response_data_, - false); - } else { - return new net::URLRequestTestJob( - request, network_delegate, - test_fixture_->response_headers_, test_fixture_->response_data_, - false); - } - } - } - - void SetDelayedStartJobGeneration(bool delay_job_start) { - delay_start_ = delay_job_start; - } - - void SetDelayedCompleteJobGeneration(bool delay_job_complete) { - delay_complete_ = delay_job_complete; - } - - void GenerateDataReceivedACK(const IPC::Message& msg) { - EXPECT_EQ(ResourceMsg_DataReceived::ID, msg.type()); - - int request_id = IPC::MessageIterator(msg).NextInt(); - scoped_ptr<IPC::Message> ack( - new ResourceHostMsg_DataReceived_ACK(msg.routing_id(), request_id)); - - MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&GenerateIPCMessage, filter_, base::Passed(&ack))); - } - - MessageLoopForIO message_loop_; - BrowserThreadImpl ui_thread_; - BrowserThreadImpl file_thread_; - BrowserThreadImpl cache_thread_; - BrowserThreadImpl io_thread_; - scoped_ptr<TestBrowserContext> browser_context_; - scoped_refptr<ForwardingFilter> filter_; - ResourceDispatcherHostImpl host_; - ResourceIPCAccumulator accum_; - std::string response_headers_; - std::string response_data_; - std::string scheme_; - net::URLRequest::ProtocolFactory* old_factory_; - ResourceType::Type resource_type_; - bool send_data_received_acks_; - static ResourceDispatcherHostTest* test_fixture_; - static bool delay_start_; - static bool delay_complete_; - static int url_request_jobs_created_count_; -}; -// Static. -ResourceDispatcherHostTest* ResourceDispatcherHostTest::test_fixture_ = NULL; -bool ResourceDispatcherHostTest::delay_start_ = false; -bool ResourceDispatcherHostTest::delay_complete_ = false; -int ResourceDispatcherHostTest::url_request_jobs_created_count_ = 0; - -void ResourceDispatcherHostTest::MakeTestRequest(int render_view_id, - int request_id, - const GURL& url) { - MakeTestRequest(filter_.get(), render_view_id, request_id, url); -} - -void ResourceDispatcherHostTest::MakeTestRequest( - ResourceMessageFilter* filter, - int render_view_id, - int request_id, - const GURL& url) { - ResourceHostMsg_Request request = - CreateResourceRequest("GET", resource_type_, url); - ResourceHostMsg_RequestResource msg(render_view_id, request_id, request); - bool msg_was_ok; - host_.OnMessageReceived(msg, filter, &msg_was_ok); - KickOffRequest(); -} - -void ResourceDispatcherHostTest::CancelRequest(int request_id) { - host_.CancelRequest(filter_->child_id(), request_id, false); -} - -void ResourceDispatcherHostTest::CompleteStartRequest(int request_id) { - CompleteStartRequest(filter_, request_id); -} - -void ResourceDispatcherHostTest::CompleteStartRequest( - ResourceMessageFilter* filter, - int request_id) { - GlobalRequestID gid(filter->child_id(), request_id); - net::URLRequest* req = host_.GetURLRequest(gid); - EXPECT_TRUE(req); - if (req) - URLRequestTestDelayedStartJob::CompleteStart(req); -} - -void CheckSuccessfulRequest(const std::vector<IPC::Message>& messages, - const std::string& reference_data) { - // A successful request will have received 4 messages: - // ReceivedResponse (indicates headers received) - // SetDataBuffer (contains shared memory handle) - // DataReceived (data offset and length into shared memory) - // RequestComplete (request is done) - // - // This function verifies that we received 4 messages and that they - // are appropriate. - ASSERT_EQ(4U, messages.size()); - - // The first messages should be received response - ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, messages[0].type()); - - ASSERT_EQ(ResourceMsg_SetDataBuffer::ID, messages[1].type()); - - PickleIterator iter(messages[1]); - int request_id; - ASSERT_TRUE(IPC::ReadParam(&messages[1], &iter, &request_id)); - base::SharedMemoryHandle shm_handle; - ASSERT_TRUE(IPC::ReadParam(&messages[1], &iter, &shm_handle)); - int shm_size; - ASSERT_TRUE(IPC::ReadParam(&messages[1], &iter, &shm_size)); - - // Followed by the data, currently we only do the data in one chunk, but - // should probably test multiple chunks later - ASSERT_EQ(ResourceMsg_DataReceived::ID, messages[2].type()); - - PickleIterator iter2(messages[2]); - ASSERT_TRUE(IPC::ReadParam(&messages[2], &iter2, &request_id)); - int data_offset; - ASSERT_TRUE(IPC::ReadParam(&messages[2], &iter2, &data_offset)); - int data_length; - ASSERT_TRUE(IPC::ReadParam(&messages[2], &iter2, &data_length)); - - ASSERT_EQ(reference_data.size(), static_cast<size_t>(data_length)); - ASSERT_GE(shm_size, data_length); - - base::SharedMemory shared_mem(shm_handle, true); // read only - shared_mem.Map(data_length); - const char* data = static_cast<char*>(shared_mem.memory()) + data_offset; - ASSERT_EQ(0, memcmp(reference_data.c_str(), data, data_length)); - - // The last message should be all data received. - ASSERT_EQ(ResourceMsg_RequestComplete::ID, messages[3].type()); -} - -// Tests whether many messages get dispatched properly. -TEST_F(ResourceDispatcherHostTest, TestMany) { - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1()); - MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2()); - MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3()); - - // flush all the pending requests - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - // sorts out all the messages we saw by request - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - - // there are three requests, so we should have gotten them classified as such - ASSERT_EQ(3U, msgs.size()); - - CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1()); - CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_2()); - CheckSuccessfulRequest(msgs[2], net::URLRequestTestJob::test_data_3()); -} - -void CheckCancelledRequestCompleteMessage(const IPC::Message& message) { - ASSERT_EQ(ResourceMsg_RequestComplete::ID, message.type()); - - int request_id; - int error_code; - - PickleIterator iter(message); - ASSERT_TRUE(IPC::ReadParam(&message, &iter, &request_id)); - ASSERT_TRUE(IPC::ReadParam(&message, &iter, &error_code)); - - EXPECT_EQ(net::ERR_ABORTED, error_code); -} - -// Tests whether messages get canceled properly. We issue three requests, -// cancel one of them, and make sure that each sent the proper notifications. -TEST_F(ResourceDispatcherHostTest, Cancel) { - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1()); - MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2()); - MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3()); - CancelRequest(2); - - // flush all the pending requests - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - MessageLoop::current()->RunUntilIdle(); - - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - - // there are three requests, so we should have gotten them classified as such - ASSERT_EQ(3U, msgs.size()); - - CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1()); - CheckSuccessfulRequest(msgs[2], net::URLRequestTestJob::test_data_3()); - - // Check that request 2 got canceled. - ASSERT_EQ(2U, msgs[1].size()); - ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[1][0].type()); - CheckCancelledRequestCompleteMessage(msgs[1][1]); -} - -TEST_F(ResourceDispatcherHostTest, CancelWhileStartIsDeferred) { - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - bool was_deleted = false; - - // Arrange to have requests deferred before starting. - TestResourceDispatcherHostDelegate delegate; - delegate.set_flags(DEFER_STARTING_REQUEST); - delegate.set_url_request_user_data(new TestUserData(&was_deleted)); - host_.SetDelegate(&delegate); - - MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1()); - CancelRequest(1); - - // Our TestResourceThrottle should not have been deleted yet. This is to - // ensure that destruction of the URLRequest happens asynchronously to - // calling CancelRequest. - EXPECT_FALSE(was_deleted); - - // flush all the pending requests - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - MessageLoop::current()->RunUntilIdle(); - - EXPECT_TRUE(was_deleted); - - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); -} - -// Tests if cancel is called in ResourceThrottle::WillStartRequest, then the -// URLRequest will not be started. -TEST_F(ResourceDispatcherHostTest, CancelInResourceThrottleWillStartRequest) { - TestResourceDispatcherHostDelegate delegate; - delegate.set_flags(CANCEL_BEFORE_START); - host_.SetDelegate(&delegate); - - MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1()); - - // flush all the pending requests - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - MessageLoop::current()->RunUntilIdle(); - - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - - // Check that request got canceled. - ASSERT_EQ(1U, msgs[0].size()); - CheckCancelledRequestCompleteMessage(msgs[0][0]); - - // Make sure URLRequest is never started. - EXPECT_EQ(0, url_request_jobs_created_count_); -} - -TEST_F(ResourceDispatcherHostTest, PausedStartError) { - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - // Arrange to have requests deferred before processing response headers. - TestResourceDispatcherHostDelegate delegate; - delegate.set_flags(DEFER_PROCESSING_RESPONSE); - host_.SetDelegate(&delegate); - - SetDelayedStartJobGeneration(true); - MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_error()); - CompleteStartRequest(1); - - // flush all the pending requests - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - MessageLoop::current()->RunUntilIdle(); - - EXPECT_EQ(0, host_.pending_requests()); -} - -TEST_F(ResourceDispatcherHostTest, ThrottleAndResumeTwice) { - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - // Arrange to have requests deferred before starting. - TestResourceDispatcherHostDelegate delegate; - delegate.set_flags(DEFER_STARTING_REQUEST); - delegate.set_create_two_throttles(true); - host_.SetDelegate(&delegate); - - // Make sure the first throttle blocked the request, and then resume. - MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1()); - GenericResourceThrottle* first_throttle = - GenericResourceThrottle::active_throttle(); - ASSERT_TRUE(first_throttle); - first_throttle->Resume(); - - // Make sure the second throttle blocked the request, and then resume. - ASSERT_TRUE(GenericResourceThrottle::active_throttle()); - ASSERT_NE(first_throttle, GenericResourceThrottle::active_throttle()); - GenericResourceThrottle::active_throttle()->Resume(); - - ASSERT_FALSE(GenericResourceThrottle::active_throttle()); - - // The request is started asynchronously. - MessageLoop::current()->RunUntilIdle(); - - // Flush all the pending requests. - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - - EXPECT_EQ(0, host_.pending_requests()); - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id())); - - // Make sure the request completed successfully. - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - ASSERT_EQ(1U, msgs.size()); - CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1()); -} - - -// Tests that the delegate can cancel a request and provide a error code. -TEST_F(ResourceDispatcherHostTest, CancelInDelegate) { - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - TestResourceDispatcherHostDelegate delegate; - delegate.set_flags(CANCEL_BEFORE_START); - delegate.set_error_code_for_cancellation(net::ERR_ACCESS_DENIED); - host_.SetDelegate(&delegate); - - MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1()); - // The request will get cancelled by the throttle. - - // flush all the pending requests - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - MessageLoop::current()->RunUntilIdle(); - - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - - // Check the cancellation - ASSERT_EQ(1U, msgs.size()); - ASSERT_EQ(1U, msgs[0].size()); - ASSERT_EQ(ResourceMsg_RequestComplete::ID, msgs[0][0].type()); - - int request_id; - int error_code; - - PickleIterator iter(msgs[0][0]); - ASSERT_TRUE(IPC::ReadParam(&msgs[0][0], &iter, &request_id)); - ASSERT_TRUE(IPC::ReadParam(&msgs[0][0], &iter, &error_code)); - - EXPECT_EQ(net::ERR_ACCESS_DENIED, error_code); -} - -// The host delegate acts as a second one so we can have some requests -// pending and some canceled. -class TestFilter : public ForwardingFilter { - public: - explicit TestFilter(ResourceContext* resource_context) - : ForwardingFilter(NULL, resource_context), - has_canceled_(false), - received_after_canceled_(0) { - } - - // ForwardingFilter override - virtual bool Send(IPC::Message* msg) OVERRIDE { - // no messages should be received when the process has been canceled - if (has_canceled_) - received_after_canceled_++; - delete msg; - return true; - } - - bool has_canceled_; - int received_after_canceled_; - - private: - virtual ~TestFilter() {} -}; - -// Tests CancelRequestsForProcess -TEST_F(ResourceDispatcherHostTest, TestProcessCancel) { - scoped_refptr<TestFilter> test_filter = new TestFilter( - browser_context_->GetResourceContext()); - - // request 1 goes to the test delegate - ResourceHostMsg_Request request = CreateResourceRequest( - "GET", ResourceType::SUB_RESOURCE, net::URLRequestTestJob::test_url_1()); - - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - MakeTestRequest(test_filter.get(), 0, 1, - net::URLRequestTestJob::test_url_1()); - - // request 2 goes to us - MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2()); - - // request 3 goes to the test delegate - MakeTestRequest(test_filter.get(), 0, 3, - net::URLRequestTestJob::test_url_3()); - - // Make sure all requests have finished stage one. test_url_1 will have - // finished. - MessageLoop::current()->RunUntilIdle(); - - // TODO(mbelshe): - // Now that the async IO path is in place, the IO always completes on the - // initial call; so the requests have already completed. This basically - // breaks the whole test. - //EXPECT_EQ(3, host_.pending_requests()); - - // Process each request for one level so one callback is called. - for (int i = 0; i < 2; i++) - EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage()); - - // Cancel the requests to the test process. - host_.CancelRequestsForProcess(filter_->child_id()); - test_filter->has_canceled_ = true; - - // Flush all the pending requests. - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - - EXPECT_EQ(0, host_.pending_requests()); - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id())); - - // The test delegate should not have gotten any messages after being canceled. - ASSERT_EQ(0, test_filter->received_after_canceled_); - - // We should have gotten exactly one result. - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - ASSERT_EQ(1U, msgs.size()); - CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_2()); -} - -// Tests blocking and resuming requests. -TEST_F(ResourceDispatcherHostTest, TestBlockingResumingRequests) { - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id())); - - host_.BlockRequestsForRoute(filter_->child_id(), 1); - host_.BlockRequestsForRoute(filter_->child_id(), 2); - host_.BlockRequestsForRoute(filter_->child_id(), 3); - - MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1()); - MakeTestRequest(1, 2, net::URLRequestTestJob::test_url_2()); - MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3()); - MakeTestRequest(1, 4, net::URLRequestTestJob::test_url_1()); - MakeTestRequest(2, 5, net::URLRequestTestJob::test_url_2()); - MakeTestRequest(3, 6, net::URLRequestTestJob::test_url_3()); - - // Flush all the pending requests - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - - // Sort out all the messages we saw by request - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - - // All requests but the 2 for the RVH 0 should have been blocked. - ASSERT_EQ(2U, msgs.size()); - - CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1()); - CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_3()); - - // Resume requests for RVH 1 and flush pending requests. - host_.ResumeBlockedRequestsForRoute(filter_->child_id(), 1); - KickOffRequest(); - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - - msgs.clear(); - accum_.GetClassifiedMessages(&msgs); - ASSERT_EQ(2U, msgs.size()); - CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_2()); - CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_1()); - - // Test that new requests are not blocked for RVH 1. - MakeTestRequest(1, 7, net::URLRequestTestJob::test_url_1()); - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - msgs.clear(); - accum_.GetClassifiedMessages(&msgs); - ASSERT_EQ(1U, msgs.size()); - CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1()); - - // Now resumes requests for all RVH (2 and 3). - host_.ResumeBlockedRequestsForRoute(filter_->child_id(), 2); - host_.ResumeBlockedRequestsForRoute(filter_->child_id(), 3); - KickOffRequest(); - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id())); - - msgs.clear(); - accum_.GetClassifiedMessages(&msgs); - ASSERT_EQ(2U, msgs.size()); - CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_2()); - CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_3()); -} - -// Tests blocking and canceling requests. -TEST_F(ResourceDispatcherHostTest, TestBlockingCancelingRequests) { - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id())); - - host_.BlockRequestsForRoute(filter_->child_id(), 1); - - MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1()); - MakeTestRequest(1, 2, net::URLRequestTestJob::test_url_2()); - MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3()); - MakeTestRequest(1, 4, net::URLRequestTestJob::test_url_1()); - - // Flush all the pending requests. - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - - // Sort out all the messages we saw by request. - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - - // The 2 requests for the RVH 0 should have been processed. - ASSERT_EQ(2U, msgs.size()); - - CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1()); - CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_3()); - - // Cancel requests for RVH 1. - host_.CancelBlockedRequestsForRoute(filter_->child_id(), 1); - KickOffRequest(); - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id())); - - msgs.clear(); - accum_.GetClassifiedMessages(&msgs); - ASSERT_EQ(0U, msgs.size()); -} - -// Tests that blocked requests are canceled if their associated process dies. -TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsProcessDies) { - // This second filter is used to emulate a second process. - scoped_refptr<ForwardingFilter> second_filter = new ForwardingFilter( - this, browser_context_->GetResourceContext()); - - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id())); - EXPECT_EQ(0, - host_.GetOutstandingRequestsMemoryCost(second_filter->child_id())); - - host_.BlockRequestsForRoute(second_filter->child_id(), 0); - - MakeTestRequest(filter_.get(), 0, 1, net::URLRequestTestJob::test_url_1()); - MakeTestRequest(second_filter.get(), 0, 2, - net::URLRequestTestJob::test_url_2()); - MakeTestRequest(filter_.get(), 0, 3, net::URLRequestTestJob::test_url_3()); - MakeTestRequest(second_filter.get(), 0, 4, - net::URLRequestTestJob::test_url_1()); - - // Simulate process death. - host_.CancelRequestsForProcess(second_filter->child_id()); - - // Flush all the pending requests. - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id())); - EXPECT_EQ(0, - host_.GetOutstandingRequestsMemoryCost(second_filter->child_id())); - - // Sort out all the messages we saw by request. - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - - // The 2 requests for the RVH 0 should have been processed. - ASSERT_EQ(2U, msgs.size()); - - CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1()); - CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_3()); - - EXPECT_TRUE(host_.blocked_loaders_map_.empty()); -} - -// Tests that blocked requests don't leak when the ResourceDispatcherHost goes -// away. Note that we rely on Purify for finding the leaks if any. -// If this test turns the Purify bot red, check the ResourceDispatcherHost -// destructor to make sure the blocked requests are deleted. -TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsDontLeak) { - // This second filter is used to emulate a second process. - scoped_refptr<ForwardingFilter> second_filter = new ForwardingFilter( - this, browser_context_->GetResourceContext()); - - host_.BlockRequestsForRoute(filter_->child_id(), 1); - host_.BlockRequestsForRoute(filter_->child_id(), 2); - host_.BlockRequestsForRoute(second_filter->child_id(), 1); - - MakeTestRequest(filter_.get(), 0, 1, net::URLRequestTestJob::test_url_1()); - MakeTestRequest(filter_.get(), 1, 2, net::URLRequestTestJob::test_url_2()); - MakeTestRequest(filter_.get(), 0, 3, net::URLRequestTestJob::test_url_3()); - MakeTestRequest(second_filter.get(), 1, 4, - net::URLRequestTestJob::test_url_1()); - MakeTestRequest(filter_.get(), 2, 5, net::URLRequestTestJob::test_url_2()); - MakeTestRequest(filter_.get(), 2, 6, net::URLRequestTestJob::test_url_3()); - - host_.CancelRequestsForProcess(filter_->child_id()); - host_.CancelRequestsForProcess(second_filter->child_id()); - - // Flush all the pending requests. - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} -} - -// Test the private helper method "CalculateApproximateMemoryCost()". -TEST_F(ResourceDispatcherHostTest, CalculateApproximateMemoryCost) { - net::URLRequestContext context; - net::URLRequest req(GURL("http://www.google.com"), NULL, &context); - EXPECT_EQ(4427, - ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(&req)); - - // Add 9 bytes of referrer. - req.set_referrer("123456789"); - EXPECT_EQ(4436, - ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(&req)); - - // Add 33 bytes of upload content. - std::string upload_content; - upload_content.resize(33); - std::fill(upload_content.begin(), upload_content.end(), 'x'); - scoped_refptr<net::UploadData> upload_data(new net::UploadData()); - upload_data->AppendBytes(upload_content.data(), upload_content.size()); - req.set_upload(upload_data); - - // Since the upload throttling is disabled, this has no effect on the cost. - EXPECT_EQ(4436, - ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(&req)); -} - -// Test the private helper method "IncrementOutstandingRequestsMemoryCost()". -TEST_F(ResourceDispatcherHostTest, IncrementOutstandingRequestsMemoryCost) { - // Add some counts for render_process_host=7 - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(7)); - EXPECT_EQ(1, host_.IncrementOutstandingRequestsMemoryCost(1, 7)); - EXPECT_EQ(2, host_.IncrementOutstandingRequestsMemoryCost(1, 7)); - EXPECT_EQ(3, host_.IncrementOutstandingRequestsMemoryCost(1, 7)); - - // Add some counts for render_process_host=3 - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(3)); - EXPECT_EQ(1, host_.IncrementOutstandingRequestsMemoryCost(1, 3)); - EXPECT_EQ(2, host_.IncrementOutstandingRequestsMemoryCost(1, 3)); - - // Remove all the counts for render_process_host=7 - EXPECT_EQ(3, host_.GetOutstandingRequestsMemoryCost(7)); - EXPECT_EQ(2, host_.IncrementOutstandingRequestsMemoryCost(-1, 7)); - EXPECT_EQ(1, host_.IncrementOutstandingRequestsMemoryCost(-1, 7)); - EXPECT_EQ(0, host_.IncrementOutstandingRequestsMemoryCost(-1, 7)); - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(7)); - - // Remove all the counts for render_process_host=3 - EXPECT_EQ(2, host_.GetOutstandingRequestsMemoryCost(3)); - EXPECT_EQ(1, host_.IncrementOutstandingRequestsMemoryCost(-1, 3)); - EXPECT_EQ(0, host_.IncrementOutstandingRequestsMemoryCost(-1, 3)); - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(3)); - - // When an entry reaches 0, it should be deleted. - EXPECT_TRUE(host_.outstanding_requests_memory_cost_map_.end() == - host_.outstanding_requests_memory_cost_map_.find(7)); - EXPECT_TRUE(host_.outstanding_requests_memory_cost_map_.end() == - host_.outstanding_requests_memory_cost_map_.find(3)); -} - -// Test that when too many requests are outstanding for a particular -// render_process_host_id, any subsequent request from it fails. -TEST_F(ResourceDispatcherHostTest, TooManyOutstandingRequests) { - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id())); - - // Expected cost of each request as measured by - // ResourceDispatcherHost::CalculateApproximateMemoryCost(). - int kMemoryCostOfTest2Req = - ResourceDispatcherHostImpl::kAvgBytesPerOutstandingRequest + - std::string("GET").size() + - net::URLRequestTestJob::test_url_2().spec().size(); - - // Tighten the bound on the ResourceDispatcherHost, to speed things up. - int kMaxCostPerProcess = 440000; - host_.set_max_outstanding_requests_cost_per_process(kMaxCostPerProcess); - - // Determine how many instance of test_url_2() we can request before - // throttling kicks in. - size_t kMaxRequests = kMaxCostPerProcess / kMemoryCostOfTest2Req; - - // This second filter is used to emulate a second process. - scoped_refptr<ForwardingFilter> second_filter = new ForwardingFilter( - this, browser_context_->GetResourceContext()); - - // Saturate the number of outstanding requests for our process. - for (size_t i = 0; i < kMaxRequests; ++i) { - MakeTestRequest(filter_.get(), 0, i + 1, - net::URLRequestTestJob::test_url_2()); - } - - // Issue two more requests for our process -- these should fail immediately. - MakeTestRequest(filter_.get(), 0, kMaxRequests + 1, - net::URLRequestTestJob::test_url_2()); - MakeTestRequest(filter_.get(), 0, kMaxRequests + 2, - net::URLRequestTestJob::test_url_2()); - - // Issue two requests for the second process -- these should succeed since - // it is just process 0 that is saturated. - MakeTestRequest(second_filter.get(), 0, kMaxRequests + 3, - net::URLRequestTestJob::test_url_2()); - MakeTestRequest(second_filter.get(), 0, kMaxRequests + 4, - net::URLRequestTestJob::test_url_2()); - - // Flush all the pending requests. - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - MessageLoop::current()->RunUntilIdle(); - - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id())); - - // Sorts out all the messages we saw by request. - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - - // We issued (kMaxRequests + 4) total requests. - ASSERT_EQ(kMaxRequests + 4, msgs.size()); - - // Check that the first kMaxRequests succeeded. - for (size_t i = 0; i < kMaxRequests; ++i) - CheckSuccessfulRequest(msgs[i], net::URLRequestTestJob::test_data_2()); - - // Check that the subsequent two requests (kMaxRequests + 1) and - // (kMaxRequests + 2) were failed, since the per-process bound was reached. - for (int i = 0; i < 2; ++i) { - // Should have sent a single RequestComplete message. - int index = kMaxRequests + i; - EXPECT_EQ(1U, msgs[index].size()); - EXPECT_EQ(ResourceMsg_RequestComplete::ID, msgs[index][0].type()); - - // The RequestComplete message should have the error code of - // ERR_INSUFFICIENT_RESOURCES. - int request_id; - int error_code; - - PickleIterator iter(msgs[index][0]); - EXPECT_TRUE(IPC::ReadParam(&msgs[index][0], &iter, &request_id)); - EXPECT_TRUE(IPC::ReadParam(&msgs[index][0], &iter, &error_code)); - - EXPECT_EQ(index + 1, request_id); - EXPECT_EQ(net::ERR_INSUFFICIENT_RESOURCES, error_code); - } - - // The final 2 requests should have succeeded. - CheckSuccessfulRequest(msgs[kMaxRequests + 2], - net::URLRequestTestJob::test_data_2()); - CheckSuccessfulRequest(msgs[kMaxRequests + 3], - net::URLRequestTestJob::test_data_2()); -} - -// Tests that we sniff the mime type for a simple request. -TEST_F(ResourceDispatcherHostTest, MimeSniffed) { - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - std::string raw_headers("HTTP/1.1 200 OK\n\n"); - std::string response_data("<html><title>Test One</title></html>"); - SetResponse(raw_headers, response_data); - - HandleScheme("http"); - MakeTestRequest(0, 1, GURL("http:bla")); - - // Flush all pending requests. - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - // Sorts out all the messages we saw by request. - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - ASSERT_EQ(1U, msgs.size()); - - ResourceResponseHead response_head; - GetResponseHead(msgs[0], &response_head); - ASSERT_EQ("text/html", response_head.mime_type); -} - -// Tests that we don't sniff the mime type when the server provides one. -TEST_F(ResourceDispatcherHostTest, MimeNotSniffed) { - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - std::string raw_headers("HTTP/1.1 200 OK\n" - "Content-type: image/jpeg\n\n"); - std::string response_data("<html><title>Test One</title></html>"); - SetResponse(raw_headers, response_data); - - HandleScheme("http"); - MakeTestRequest(0, 1, GURL("http:bla")); - - // Flush all pending requests. - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - // Sorts out all the messages we saw by request. - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - ASSERT_EQ(1U, msgs.size()); - - ResourceResponseHead response_head; - GetResponseHead(msgs[0], &response_head); - ASSERT_EQ("image/jpeg", response_head.mime_type); -} - -// Tests that we don't sniff the mime type when there is no message body. -TEST_F(ResourceDispatcherHostTest, MimeNotSniffed2) { - - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - SetResponse("HTTP/1.1 304 Not Modified\n\n"); - - HandleScheme("http"); - MakeTestRequest(0, 1, GURL("http:bla")); - - // Flush all pending requests. - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - // Sorts out all the messages we saw by request. - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - ASSERT_EQ(1U, msgs.size()); - - ResourceResponseHead response_head; - GetResponseHead(msgs[0], &response_head); - ASSERT_EQ("", response_head.mime_type); -} - -TEST_F(ResourceDispatcherHostTest, MimeSniff204) { - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - SetResponse("HTTP/1.1 204 No Content\n\n"); - - HandleScheme("http"); - MakeTestRequest(0, 1, GURL("http:bla")); - - // Flush all pending requests. - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - // Sorts out all the messages we saw by request. - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - ASSERT_EQ(1U, msgs.size()); - - ResourceResponseHead response_head; - GetResponseHead(msgs[0], &response_head); - ASSERT_EQ("text/plain", response_head.mime_type); -} - -TEST_F(ResourceDispatcherHostTest, MimeSniffEmpty) { - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - SetResponse("HTTP/1.1 200 OK\n\n"); - - HandleScheme("http"); - MakeTestRequest(0, 1, GURL("http:bla")); - - // Flush all pending requests. - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - // Sorts out all the messages we saw by request. - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - ASSERT_EQ(1U, msgs.size()); - - ResourceResponseHead response_head; - GetResponseHead(msgs[0], &response_head); - ASSERT_EQ("text/plain", response_head.mime_type); -} - -// Tests for crbug.com/31266 (Non-2xx + application/octet-stream). -TEST_F(ResourceDispatcherHostTest, ForbiddenDownload) { - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - std::string raw_headers("HTTP/1.1 403 Forbidden\n" - "Content-disposition: attachment; filename=blah\n" - "Content-type: application/octet-stream\n\n"); - std::string response_data("<html><title>Test One</title></html>"); - SetResponse(raw_headers, response_data); - - // Only MAIN_FRAMEs can trigger a download. - SetResourceType(ResourceType::MAIN_FRAME); - - HandleScheme("http"); - MakeTestRequest(0, 1, GURL("http:bla")); - - // Flush all pending requests. - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); - - // Sorts out all the messages we saw by request. - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - - // We should have gotten one RequestComplete message. - ASSERT_EQ(1U, msgs[0].size()); - EXPECT_EQ(ResourceMsg_RequestComplete::ID, msgs[0][0].type()); - - // The RequestComplete message should have had the error code of - // ERR_FILE_NOT_FOUND. - int request_id; - int error_code; - - PickleIterator iter(msgs[0][0]); - EXPECT_TRUE(IPC::ReadParam(&msgs[0][0], &iter, &request_id)); - EXPECT_TRUE(IPC::ReadParam(&msgs[0][0], &iter, &error_code)); - - EXPECT_EQ(1, request_id); - EXPECT_EQ(net::ERR_FILE_NOT_FOUND, error_code); -} - -// Test for http://crbug.com/76202 . We don't want to destroy a -// download request prematurely when processing a cancellation from -// the renderer. -TEST_F(ResourceDispatcherHostTest, IgnoreCancelForDownloads) { - EXPECT_EQ(0, host_.pending_requests()); - - int render_view_id = 0; - int request_id = 1; - - std::string raw_headers("HTTP\n" - "Content-disposition: attachment; filename=foo\n\n"); - std::string response_data("01234567890123456789\x01foobar"); - - // Get past sniffing metrics in the BufferedResourceHandler. Note that - // if we don't get past the sniffing metrics, the result will be that - // the BufferedResourceHandler won't have figured out that it's a download, - // won't have constructed a DownloadResourceHandler, and and the request - // will be successfully canceled below, failing the test. - response_data.resize(1025, ' '); - - SetResponse(raw_headers, response_data); - SetResourceType(ResourceType::MAIN_FRAME); - SetDelayedCompleteJobGeneration(true); - HandleScheme("http"); - - MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah")); - // Return some data so that the request is identified as a download - // and the proper resource handlers are created. - EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage()); - - // And now simulate a cancellation coming from the renderer. - ResourceHostMsg_CancelRequest msg(filter_->child_id(), request_id); - bool msg_was_ok; - host_.OnMessageReceived(msg, filter_.get(), &msg_was_ok); - - // Since the request had already started processing as a download, - // the cancellation above should have been ignored and the request - // should still be alive. - EXPECT_EQ(1, host_.pending_requests()); - - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0)); -} - -TEST_F(ResourceDispatcherHostTest, CancelRequestsForContext) { - EXPECT_EQ(0, host_.pending_requests()); - - int render_view_id = 0; - int request_id = 1; - - std::string raw_headers("HTTP\n" - "Content-disposition: attachment; filename=foo\n\n"); - std::string response_data("01234567890123456789\x01foobar"); - // Get past sniffing metrics. - response_data.resize(1025, ' '); - - SetResponse(raw_headers, response_data); - SetResourceType(ResourceType::MAIN_FRAME); - SetDelayedCompleteJobGeneration(true); - HandleScheme("http"); - - MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah")); - // Return some data so that the request is identified as a download - // and the proper resource handlers are created. - EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage()); - - // And now simulate a cancellation coming from the renderer. - ResourceHostMsg_CancelRequest msg(filter_->child_id(), request_id); - bool msg_was_ok; - host_.OnMessageReceived(msg, filter_.get(), &msg_was_ok); - - // Since the request had already started processing as a download, - // the cancellation above should have been ignored and the request - // should still be alive. - EXPECT_EQ(1, host_.pending_requests()); - - // Cancelling by other methods shouldn't work either. - host_.CancelRequestsForProcess(render_view_id); - EXPECT_EQ(1, host_.pending_requests()); - - // Cancelling by context should work. - host_.CancelRequestsForContext(filter_->resource_context()); - EXPECT_EQ(0, host_.pending_requests()); -} - -// Test the cancelling of requests that are being transferred to a new renderer -// due to a redirection. -TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextTransferred) { - EXPECT_EQ(0, host_.pending_requests()); - - int render_view_id = 0; - int request_id = 1; - - std::string raw_headers("HTTP/1.1 200 OK\n" - "Content-Type: text/html; charset=utf-8\n\n"); - std::string response_data("<html>foobar</html>"); - - SetResponse(raw_headers, response_data); - SetResourceType(ResourceType::MAIN_FRAME); - HandleScheme("http"); - - MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah")); - - GlobalRequestID global_request_id(filter_->child_id(), request_id); - host_.MarkAsTransferredNavigation(global_request_id); - - // And now simulate a cancellation coming from the renderer. - ResourceHostMsg_CancelRequest msg(filter_->child_id(), request_id); - bool msg_was_ok; - host_.OnMessageReceived(msg, filter_.get(), &msg_was_ok); - - // Since the request is marked as being transferred, - // the cancellation above should have been ignored and the request - // should still be alive. - EXPECT_EQ(1, host_.pending_requests()); - - // Cancelling by other methods shouldn't work either. - host_.CancelRequestsForProcess(render_view_id); - EXPECT_EQ(1, host_.pending_requests()); - - // Cancelling by context should work. - host_.CancelRequestsForContext(filter_->resource_context()); - EXPECT_EQ(0, host_.pending_requests()); -} - -TEST_F(ResourceDispatcherHostTest, TransferNavigation) { - EXPECT_EQ(0, host_.pending_requests()); - - int render_view_id = 0; - int request_id = 1; - - // Configure initial request. - SetResponse("HTTP/1.1 302 Found\n" - "Location: http://other.com/blech\n\n"); - - SetResourceType(ResourceType::MAIN_FRAME); - HandleScheme("http"); - - // Temporarily replace ContentBrowserClient with one that will trigger the - // transfer navigation code paths. - ContentBrowserClient* old_client = GetContentClient()->browser(); - TransfersAllNavigationsContentBrowserClient new_client; - GetContentClient()->set_browser_for_testing(&new_client); - - MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah")); - - // Restore. - GetContentClient()->set_browser_for_testing(old_client); - - // This second filter is used to emulate a second process. - scoped_refptr<ForwardingFilter> second_filter = new ForwardingFilter( - this, browser_context_->GetResourceContext()); - - int new_render_view_id = 1; - int new_request_id = 2; - - const std::string kResponseBody = "hello world"; - SetResponse("HTTP/1.1 200 OK\n" - "Content-Type: text/plain\n\n", - kResponseBody); - - ResourceHostMsg_Request request = - CreateResourceRequest("GET", ResourceType::MAIN_FRAME, - GURL("http://other.com/blech")); - request.transferred_request_child_id = filter_->child_id(); - request.transferred_request_request_id = request_id; - - ResourceHostMsg_RequestResource transfer_request_msg( - new_render_view_id, new_request_id, request); - bool msg_was_ok; - host_.OnMessageReceived(transfer_request_msg, second_filter, &msg_was_ok); - MessageLoop::current()->RunUntilIdle(); - - // Flush all the pending requests. - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - - // Check generated messages. - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - - ASSERT_EQ(1U, msgs.size()); - CheckSuccessfulRequest(msgs[0], kResponseBody); -} - -TEST_F(ResourceDispatcherHostTest, TransferNavigationAndThenRedirect) { - EXPECT_EQ(0, host_.pending_requests()); - - int render_view_id = 0; - int request_id = 1; - - // Configure initial request. - SetResponse("HTTP/1.1 302 Found\n" - "Location: http://other.com/blech\n\n"); - - SetResourceType(ResourceType::MAIN_FRAME); - HandleScheme("http"); - - // Temporarily replace ContentBrowserClient with one that will trigger the - // transfer navigation code paths. - ContentBrowserClient* old_client = GetContentClient()->browser(); - TransfersAllNavigationsContentBrowserClient new_client; - GetContentClient()->set_browser_for_testing(&new_client); - - MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah")); - - // Restore. - GetContentClient()->set_browser_for_testing(old_client); - - // This second filter is used to emulate a second process. - scoped_refptr<ForwardingFilter> second_filter = new ForwardingFilter( - this, browser_context_->GetResourceContext()); - - int new_render_view_id = 1; - int new_request_id = 2; - - // Delay the start of the next request so that we can setup the response for - // the next URL. - SetDelayedStartJobGeneration(true); - - SetResponse("HTTP/1.1 302 Found\n" - "Location: http://other.com/blerg\n\n"); - - ResourceHostMsg_Request request = - CreateResourceRequest("GET", ResourceType::MAIN_FRAME, - GURL("http://other.com/blech")); - request.transferred_request_child_id = filter_->child_id(); - request.transferred_request_request_id = request_id; - - ResourceHostMsg_RequestResource transfer_request_msg( - new_render_view_id, new_request_id, request); - bool msg_was_ok; - host_.OnMessageReceived(transfer_request_msg, second_filter, &msg_was_ok); - MessageLoop::current()->RunUntilIdle(); - - // Response data for "http://other.com/blerg": - const std::string kResponseBody = "hello world"; - SetResponse("HTTP/1.1 200 OK\n" - "Content-Type: text/plain\n\n", - kResponseBody); - - // OK, let the redirect happen. - SetDelayedStartJobGeneration(false); - CompleteStartRequest(second_filter, new_request_id); - MessageLoop::current()->RunUntilIdle(); - - // Flush all the pending requests. - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - - // Now, simulate the renderer choosing to follow the redirect. - ResourceHostMsg_FollowRedirect redirect_msg( - new_render_view_id, new_request_id, false, GURL()); - host_.OnMessageReceived(redirect_msg, second_filter, &msg_was_ok); - MessageLoop::current()->RunUntilIdle(); - - // Flush all the pending requests. - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - - // Check generated messages. - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - - ASSERT_EQ(1U, msgs.size()); - - // We should have received a redirect followed by a "normal" payload. - EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID, msgs[0][0].type()); - msgs[0].erase(msgs[0].begin()); - CheckSuccessfulRequest(msgs[0], kResponseBody); -} - -TEST_F(ResourceDispatcherHostTest, UnknownURLScheme) { - EXPECT_EQ(0, host_.pending_requests()); - - SetResourceType(ResourceType::MAIN_FRAME); - HandleScheme("http"); - - MakeTestRequest(0, 1, GURL("foo://bar")); - - // Flush all pending requests. - while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} - - // Sort all the messages we saw by request. - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - - // We should have gotten one RequestComplete message. - ASSERT_EQ(1U, msgs[0].size()); - EXPECT_EQ(ResourceMsg_RequestComplete::ID, msgs[0][0].type()); - - // The RequestComplete message should have the error code of - // ERR_UNKNOWN_URL_SCHEME. - int request_id; - int error_code; - - PickleIterator iter(msgs[0][0]); - EXPECT_TRUE(IPC::ReadParam(&msgs[0][0], &iter, &request_id)); - EXPECT_TRUE(IPC::ReadParam(&msgs[0][0], &iter, &error_code)); - - EXPECT_EQ(1, request_id); - EXPECT_EQ(net::ERR_UNKNOWN_URL_SCHEME, error_code); -} - -TEST_F(ResourceDispatcherHostTest, DataReceivedACKs) { - EXPECT_EQ(0, host_.pending_requests()); - - SendDataReceivedACKs(true); - - HandleScheme("big-job"); - MakeTestRequest(0, 1, GURL("big-job:0123456789,1000000")); - - // Sort all the messages we saw by request. - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - - size_t size = msgs[0].size(); - - EXPECT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[0][0].type()); - EXPECT_EQ(ResourceMsg_SetDataBuffer::ID, msgs[0][1].type()); - for (size_t i = 2; i < size - 1; ++i) - EXPECT_EQ(ResourceMsg_DataReceived::ID, msgs[0][i].type()); - EXPECT_EQ(ResourceMsg_RequestComplete::ID, msgs[0][size - 1].type()); -} - -TEST_F(ResourceDispatcherHostTest, DelayedDataReceivedACKs) { - EXPECT_EQ(0, host_.pending_requests()); - - HandleScheme("big-job"); - MakeTestRequest(0, 1, GURL("big-job:0123456789,1000000")); - - // Sort all the messages we saw by request. - ResourceIPCAccumulator::ClassifiedMessages msgs; - accum_.GetClassifiedMessages(&msgs); - - // We expect 1x ReceivedResponse, 1x SetDataBuffer, Nx ReceivedData messages. - EXPECT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[0][0].type()); - EXPECT_EQ(ResourceMsg_SetDataBuffer::ID, msgs[0][1].type()); - for (size_t i = 2; i < msgs[0].size(); ++i) - EXPECT_EQ(ResourceMsg_DataReceived::ID, msgs[0][i].type()); - - // NOTE: If we fail the above checks then it means that we probably didn't - // load a big enough response to trigger the delay mechanism we are trying to - // test! - - msgs[0].erase(msgs[0].begin()); - msgs[0].erase(msgs[0].begin()); - - // ACK all DataReceived messages until we find a RequestComplete message. - bool complete = false; - while (!complete) { - for (size_t i = 0; i < msgs[0].size(); ++i) { - if (msgs[0][i].type() == ResourceMsg_RequestComplete::ID) { - complete = true; - break; - } - - EXPECT_EQ(ResourceMsg_DataReceived::ID, msgs[0][i].type()); - - ResourceHostMsg_DataReceived_ACK msg(0, 1); - bool msg_was_ok; - host_.OnMessageReceived(msg, filter_.get(), &msg_was_ok); - } - - MessageLoop::current()->RunUntilIdle(); - - msgs.clear(); - accum_.GetClassifiedMessages(&msgs); - } -} - -} // namespace content diff --git a/content/browser/renderer_host/resource_handler.cc b/content/browser/renderer_host/resource_handler.cc deleted file mode 100644 index a7871ae..0000000 --- a/content/browser/renderer_host/resource_handler.cc +++ /dev/null @@ -1,13 +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/resource_handler.h" - -namespace content { - -void ResourceHandler::SetController(ResourceController* controller) { - controller_ = controller; -} - -} // namespace content diff --git a/content/browser/renderer_host/resource_handler.h b/content/browser/renderer_host/resource_handler.h deleted file mode 100644 index 2d916c1..0000000 --- a/content/browser/renderer_host/resource_handler.h +++ /dev/null @@ -1,116 +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. - -// This is the browser side of the resource dispatcher, it receives requests -// from the RenderProcessHosts, and dispatches them to URLRequests. It then -// fowards the messages from the URLRequests back to the correct process for -// handling. -// -// See http://dev.chromium.org/developers/design-documents/multi-process-resource-loading - -#ifndef CONTENT_BROWSER_RENDERER_HOST_RESOURCE_HANDLER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_RESOURCE_HANDLER_H_ - -#include <string> - -#include "base/sequenced_task_runner_helpers.h" -#include "base/threading/non_thread_safe.h" -#include "content/common/content_export.h" -#include "content/public/browser/browser_thread.h" - -class GURL; - -namespace net { -class IOBuffer; -class URLRequestStatus; -} // namespace net - -namespace content { -class ResourceController; -struct ResourceResponse; - -// The resource dispatcher host uses this interface to process network events -// for an URLRequest instance. A ResourceHandler's lifetime is bound to its -// associated URLRequest. -class CONTENT_EXPORT ResourceHandler - : public NON_EXPORTED_BASE(base::NonThreadSafe) { - public: - virtual ~ResourceHandler() {} - - // Sets the controller for this handler. - virtual void SetController(ResourceController* controller); - - // Called as upload progress is made. The return value is ignored. - virtual bool OnUploadProgress(int request_id, - uint64 position, - uint64 size) = 0; - - // The request was redirected to a new URL. |*defer| has an initial value of - // false. Set |*defer| to true to defer the redirect. The redirect may be - // followed later on via ResourceDispatcherHost::FollowDeferredRedirect. If - // the handler returns false, then the request is cancelled. - virtual bool OnRequestRedirected(int request_id, const GURL& url, - ResourceResponse* response, - bool* defer) = 0; - - // Response headers and meta data are available. If the handler returns - // false, then the request is cancelled. Set |*defer| to true to defer - // processing of the response. Call ResourceDispatcherHostImpl:: - // ResumeDeferredRequest to continue processing the response. - virtual bool OnResponseStarted(int request_id, - ResourceResponse* response, - bool* defer) = 0; - - // Called before the net::URLRequest for |request_id| (whose url is |url|) is - // to be started. If the handler returns false, then the request is - // cancelled. Otherwise if the return value is true, the ResourceHandler can - // delay the request from starting by setting |*defer = true|. A deferred - // request will not have called net::URLRequest::Start(), and will not resume - // until someone calls ResourceDispatcherHost::StartDeferredRequest(). - virtual bool OnWillStart(int request_id, const GURL& url, bool* defer) = 0; - - // Data will be read for the response. Upon success, this method places the - // size and address of the buffer where the data is to be written in its - // out-params. This call will be followed by either OnReadCompleted or - // OnResponseCompleted, at which point the buffer may be recycled. - // - // If the handler returns false, then the request is cancelled. Otherwise, - // once data is available, OnReadCompleted will be called. - virtual bool OnWillRead(int request_id, - net::IOBuffer** buf, - int* buf_size, - int min_size) = 0; - - // Data (*bytes_read bytes) was written into the buffer provided by - // OnWillRead. A return value of false cancels the request, true continues - // reading data. Set |*defer| to true to defer reading more response data. - // Call ResourceDispatcherHostImpl::ResumeDeferredRequest to continue reading - // response data. - virtual bool OnReadCompleted(int request_id, int bytes_read, - bool* defer) = 0; - - // The response is complete. The final response status is given. Returns - // false if the handler is deferring the call to a later time. Otherwise, - // the request will be destroyed upon return. - virtual bool OnResponseCompleted(int request_id, - const net::URLRequestStatus& status, - const std::string& security_info) = 0; - - // This notification is synthesized by the RedirectToFileResourceHandler - // to indicate progress of 'download_to_file' requests. OnReadCompleted - // calls are consumed by the RedirectToFileResourceHandler and replaced - // with OnDataDownloaded calls. - virtual void OnDataDownloaded(int request_id, int bytes_downloaded) {} - - protected: - ResourceHandler() : controller_(NULL) {} - ResourceController* controller() { return controller_; } - - private: - ResourceController* controller_; -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_RESOURCE_HANDLER_H_ diff --git a/content/browser/renderer_host/resource_loader.cc b/content/browser/renderer_host/resource_loader.cc deleted file mode 100644 index be893d7..0000000 --- a/content/browser/renderer_host/resource_loader.cc +++ /dev/null @@ -1,582 +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/resource_loader.h" - -#include "base/message_loop.h" -#include "base/time.h" -#include "content/browser/child_process_security_policy_impl.h" -#include "content/browser/renderer_host/doomed_resource_handler.h" -#include "content/browser/renderer_host/resource_loader_delegate.h" -#include "content/browser/renderer_host/resource_request_info_impl.h" -#include "content/browser/ssl/ssl_client_auth_handler.h" -#include "content/browser/ssl/ssl_manager.h" -#include "content/common/ssl_status_serialization.h" -#include "content/public/browser/cert_store.h" -#include "content/public/browser/resource_dispatcher_host_login_delegate.h" -#include "content/public/common/resource_response.h" -#include "net/base/load_flags.h" -#include "net/http/http_response_headers.h" -#include "webkit/appcache/appcache_interceptor.h" - -using base::TimeDelta; -using base::TimeTicks; - -namespace content { -namespace { - -void PopulateResourceResponse(net::URLRequest* request, - ResourceResponse* response) { - response->head.error_code = request->status().error(); - response->head.request_time = request->request_time(); - response->head.response_time = request->response_time(); - response->head.headers = request->response_headers(); - request->GetCharset(&response->head.charset); - response->head.content_length = request->GetExpectedContentSize(); - request->GetMimeType(&response->head.mime_type); - net::HttpResponseInfo response_info = request->response_info(); - response->head.was_fetched_via_spdy = response_info.was_fetched_via_spdy; - response->head.was_npn_negotiated = response_info.was_npn_negotiated; - response->head.npn_negotiated_protocol = - response_info.npn_negotiated_protocol; - response->head.was_fetched_via_proxy = request->was_fetched_via_proxy(); - response->head.socket_address = request->GetSocketAddress(); - appcache::AppCacheInterceptor::GetExtraResponseInfo( - request, - &response->head.appcache_id, - &response->head.appcache_manifest_url); -} - -} // namespace - -ResourceLoader::ResourceLoader(scoped_ptr<net::URLRequest> request, - scoped_ptr<ResourceHandler> handler, - ResourceLoaderDelegate* delegate) - : deferred_stage_(DEFERRED_NONE), - request_(request.Pass()), - handler_(handler.Pass()), - delegate_(delegate), - last_upload_position_(0), - waiting_for_upload_progress_ack_(false), - is_transferring_(false), - weak_ptr_factory_(this) { - request_->set_delegate(this); - handler_->SetController(this); -} - -ResourceLoader::~ResourceLoader() { - if (login_delegate_) - login_delegate_->OnRequestCancelled(); - if (ssl_client_auth_handler_) - ssl_client_auth_handler_->OnRequestCancelled(); - - // Run ResourceHandler destructor before we tear-down the rest of our state - // as the ResourceHandler may want to inspect the URLRequest and other state. - handler_.reset(); -} - -void ResourceLoader::StartRequest() { - if (delegate_->HandleExternalProtocol(this, request_->url())) { - CancelAndIgnore(); - return; - } - - // Give the handler a chance to delay the URLRequest from being started. - bool defer_start = false; - if (!handler_->OnWillStart(GetRequestInfo()->GetRequestID(), request_->url(), - &defer_start)) { - Cancel(); - return; - } - - if (defer_start) { - deferred_stage_ = DEFERRED_START; - } else { - StartRequestInternal(); - } -} - -void ResourceLoader::CancelRequest(bool from_renderer) { - CancelRequestInternal(net::ERR_ABORTED, from_renderer); -} - -void ResourceLoader::CancelAndIgnore() { - ResourceRequestInfoImpl* info = GetRequestInfo(); - info->set_was_ignored_by_handler(true); - CancelRequest(false); -} - -void ResourceLoader::CancelWithError(int error_code) { - CancelRequestInternal(error_code, false); -} - -void ResourceLoader::ReportUploadProgress() { - ResourceRequestInfoImpl* info = GetRequestInfo(); - - if (waiting_for_upload_progress_ack_) - return; // Send one progress event at a time. - - net::UploadProgress progress = request_->GetUploadProgress(); - if (!progress.size()) - return; // Nothing to upload. - - if (progress.position() == last_upload_position_) - return; // No progress made since last time. - - const uint64 kHalfPercentIncrements = 200; - const TimeDelta kOneSecond = TimeDelta::FromMilliseconds(1000); - - uint64 amt_since_last = progress.position() - last_upload_position_; - TimeDelta time_since_last = TimeTicks::Now() - last_upload_ticks_; - - bool is_finished = (progress.size() == progress.position()); - bool enough_new_progress = - (amt_since_last > (progress.size() / kHalfPercentIncrements)); - bool too_much_time_passed = time_since_last > kOneSecond; - - if (is_finished || enough_new_progress || too_much_time_passed) { - if (request_->load_flags() & net::LOAD_ENABLE_UPLOAD_PROGRESS) { - handler_->OnUploadProgress( - info->GetRequestID(), progress.position(), progress.size()); - waiting_for_upload_progress_ack_ = true; - } - last_upload_ticks_ = TimeTicks::Now(); - last_upload_position_ = progress.position(); - } -} - -void ResourceLoader::MarkAsTransferring() { - is_transferring_ = true; - - // When an URLRequest is transferred to a new RenderViewHost, its - // ResourceHandler should not receive any notifications because it may depend - // on the state of the old RVH. We set a ResourceHandler that only allows - // canceling requests, because on shutdown of the RDH all pending requests - // are canceled. The RVH of requests that are being transferred may be gone - // by that time. In CompleteTransfer, the ResoureHandlers are substituted - // again. - handler_.reset(new DoomedResourceHandler(handler_.Pass())); -} - -void ResourceLoader::WillCompleteTransfer() { - handler_.reset(); -} - -void ResourceLoader::CompleteTransfer(scoped_ptr<ResourceHandler> new_handler) { - DCHECK_EQ(DEFERRED_REDIRECT, deferred_stage_); - DCHECK(!handler_.get()); - - handler_ = new_handler.Pass(); - handler_->SetController(this); - is_transferring_ = false; - - Resume(); -} - -ResourceRequestInfoImpl* ResourceLoader::GetRequestInfo() { - return ResourceRequestInfoImpl::ForRequest(request_.get()); -} - -void ResourceLoader::ClearLoginDelegate() { - login_delegate_ = NULL; -} - -void ResourceLoader::ClearSSLClientAuthHandler() { - ssl_client_auth_handler_ = NULL; -} - -void ResourceLoader::OnUploadProgressACK() { - waiting_for_upload_progress_ack_ = false; -} - -void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused, - const GURL& new_url, - bool* defer) { - DCHECK_EQ(request_.get(), unused); - - VLOG(1) << "OnReceivedRedirect: " << request_->url().spec(); - DCHECK(request_->status().is_success()); - - ResourceRequestInfoImpl* info = GetRequestInfo(); - - if (info->process_type() != PROCESS_TYPE_PLUGIN && - !ChildProcessSecurityPolicyImpl::GetInstance()-> - CanRequestURL(info->GetChildID(), new_url)) { - VLOG(1) << "Denied unauthorized request for " - << new_url.possibly_invalid_spec(); - - // Tell the renderer that this request was disallowed. - Cancel(); - return; - } - - delegate_->DidReceiveRedirect(this, new_url); - - if (delegate_->HandleExternalProtocol(this, new_url)) { - // The request is complete so we can remove it. - CancelAndIgnore(); - return; - } - - scoped_refptr<ResourceResponse> response(new ResourceResponse()); - PopulateResourceResponse(request_.get(), response); - - if (!handler_->OnRequestRedirected(info->GetRequestID(), new_url, response, - defer)) { - Cancel(); - } else if (*defer) { - deferred_stage_ = DEFERRED_REDIRECT; // Follow redirect when resumed. - } -} - -void ResourceLoader::OnAuthRequired(net::URLRequest* unused, - net::AuthChallengeInfo* auth_info) { - DCHECK_EQ(request_.get(), unused); - - if (request_->load_flags() & net::LOAD_DO_NOT_PROMPT_FOR_LOGIN) { - request_->CancelAuth(); - return; - } - - if (!delegate_->AcceptAuthRequest(this, auth_info)) { - request_->CancelAuth(); - return; - } - - // Create a login dialog on the UI thread to get authentication data, or pull - // from cache and continue on the IO thread. - - DCHECK(!login_delegate_) << - "OnAuthRequired called with login_delegate pending"; - login_delegate_ = delegate_->CreateLoginDelegate(this, auth_info); - if (!login_delegate_) - request_->CancelAuth(); -} - -void ResourceLoader::OnCertificateRequested( - net::URLRequest* unused, - net::SSLCertRequestInfo* cert_info) { - DCHECK_EQ(request_.get(), unused); - - if (!delegate_->AcceptSSLClientCertificateRequest(this, cert_info)) { - request_->Cancel(); - return; - } - - if (cert_info->client_certs.empty()) { - // No need to query the user if there are no certs to choose from. - request_->ContinueWithCertificate(NULL); - return; - } - - DCHECK(!ssl_client_auth_handler_) << - "OnCertificateRequested called with ssl_client_auth_handler pending"; - ssl_client_auth_handler_ = new SSLClientAuthHandler(request_.get(), - cert_info); - ssl_client_auth_handler_->SelectCertificate(); -} - -void ResourceLoader::OnSSLCertificateError(net::URLRequest* request, - const net::SSLInfo& ssl_info, - bool fatal) { - ResourceRequestInfoImpl* info = GetRequestInfo(); - - int render_process_id; - int render_view_id; - if (!info->GetAssociatedRenderView(&render_process_id, &render_view_id)) - NOTREACHED(); - - SSLManager::OnSSLCertificateError( - weak_ptr_factory_.GetWeakPtr(), - info->GetGlobalRequestID(), - info->GetResourceType(), - request_->url(), - render_process_id, - render_view_id, - ssl_info, - fatal); -} - -void ResourceLoader::OnResponseStarted(net::URLRequest* unused) { - DCHECK_EQ(request_.get(), unused); - - VLOG(1) << "OnResponseStarted: " << request_->url().spec(); - - if (!request_->status().is_success()) { - ResponseCompleted(); - return; - } - - // We want to send a final upload progress message prior to sending the - // response complete message even if we're waiting for an ack to to a - // previous upload progress message. - waiting_for_upload_progress_ack_ = false; - ReportUploadProgress(); - - CompleteResponseStarted(); - - if (is_deferred()) - return; - - if (request_->status().is_success()) { - StartReading(false); // Read the first chunk. - } else { - ResponseCompleted(); - } -} - -void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) { - DCHECK_EQ(request_.get(), unused); - VLOG(1) << "OnReadCompleted: \"" << request_->url().spec() << "\"" - << " bytes_read = " << bytes_read; - - // bytes_read == -1 always implies an error. - if (bytes_read == -1 || !request_->status().is_success()) { - ResponseCompleted(); - return; - } - - CompleteRead(bytes_read); - - if (is_deferred()) - return; - - if (request_->status().is_success() && bytes_read > 0) { - StartReading(true); // Read the next chunk. - } else { - ResponseCompleted(); - } -} - -void ResourceLoader::CancelSSLRequest(const GlobalRequestID& id, - int error, - const net::SSLInfo* ssl_info) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - - // The request can be NULL if it was cancelled by the renderer (as the - // request of the user navigating to a new page from the location bar). - if (!request_->is_pending()) - return; - DVLOG(1) << "CancelSSLRequest() url: " << request_->url().spec(); - - if (ssl_info) { - request_->CancelWithSSLError(error, *ssl_info); - } else { - request_->CancelWithError(error); - } -} - -void ResourceLoader::ContinueSSLRequest(const GlobalRequestID& id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - - DVLOG(1) << "ContinueSSLRequest() url: " << request_->url().spec(); - - request_->ContinueDespiteLastError(); -} - -void ResourceLoader::Resume() { - DCHECK(!is_transferring_); - - DeferredStage stage = deferred_stage_; - deferred_stage_ = DEFERRED_NONE; - switch (stage) { - case DEFERRED_NONE: - NOTREACHED(); - break; - case DEFERRED_START: - StartRequestInternal(); - break; - case DEFERRED_REDIRECT: - request_->FollowDeferredRedirect(); - break; - case DEFERRED_READ: - MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&ResourceLoader::ResumeReading, - weak_ptr_factory_.GetWeakPtr())); - break; - case DEFERRED_FINISH: - // Delay self-destruction since we don't know how we were reached. - MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&ResourceLoader::CallDidFinishLoading, - weak_ptr_factory_.GetWeakPtr())); - break; - } -} - -void ResourceLoader::Cancel() { - CancelRequest(false); -} - -void ResourceLoader::StartRequestInternal() { - DCHECK(!request_->is_pending()); - request_->Start(); - - delegate_->DidStartRequest(this); -} - -void ResourceLoader::CancelRequestInternal(int error, bool from_renderer) { - VLOG(1) << "CancelRequestInternal: " << request_->url().spec(); - - ResourceRequestInfoImpl* info = GetRequestInfo(); - - // WebKit will send us a cancel for downloads since it no longer handles - // them. In this case, ignore the cancel since we handle downloads in the - // browser. - if (from_renderer && info->is_download()) - return; - - // TODO(darin): Perhaps we should really be looking to see if the status is - // IO_PENDING? - bool was_pending = request_->is_pending(); - - if (login_delegate_) { - login_delegate_->OnRequestCancelled(); - login_delegate_ = NULL; - } - if (ssl_client_auth_handler_) { - ssl_client_auth_handler_->OnRequestCancelled(); - ssl_client_auth_handler_ = NULL; - } - - request_->CancelWithError(error); - - if (!was_pending) { - // If the request isn't in flight, then we won't get an asynchronous - // notification from the request, so we have to signal ourselves to finish - // this request. - MessageLoop::current()->PostTask( - FROM_HERE, base::Bind(&ResourceLoader::ResponseCompleted, - weak_ptr_factory_.GetWeakPtr())); - } -} - -void ResourceLoader::CompleteResponseStarted() { - ResourceRequestInfoImpl* info = GetRequestInfo(); - - scoped_refptr<ResourceResponse> response(new ResourceResponse()); - PopulateResourceResponse(request_.get(), response); - - if (request_->ssl_info().cert) { - int cert_id = - CertStore::GetInstance()->StoreCert(request_->ssl_info().cert, - info->GetChildID()); - response->head.security_info = SerializeSecurityInfo( - cert_id, - request_->ssl_info().cert_status, - request_->ssl_info().security_bits, - request_->ssl_info().connection_status); - } else { - // We should not have any SSL state. - DCHECK(!request_->ssl_info().cert_status && - request_->ssl_info().security_bits == -1 && - !request_->ssl_info().connection_status); - } - - delegate_->DidReceiveResponse(this); - - bool defer = false; - if (!handler_->OnResponseStarted(info->GetRequestID(), response, &defer)) { - Cancel(); - } else if (defer) { - deferred_stage_ = DEFERRED_READ; // Read first chunk when resumed. - } -} - -void ResourceLoader::StartReading(bool is_continuation) { - int bytes_read = 0; - ReadMore(&bytes_read); - - // If IO is pending, wait for the URLRequest to call OnReadCompleted. - if (request_->status().is_io_pending()) - return; - - if (!is_continuation || bytes_read <= 0) { - OnReadCompleted(request_.get(), bytes_read); - } else { - // Else, trigger OnReadCompleted asynchronously to avoid starving the IO - // thread in case the URLRequest can provide data synchronously. - MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&ResourceLoader::OnReadCompleted, - weak_ptr_factory_.GetWeakPtr(), - request_.get(), bytes_read)); - } -} - -void ResourceLoader::ResumeReading() { - DCHECK(!is_deferred()); - - if (request_->status().is_success()) { - StartReading(false); // Read the next chunk (OK to complete synchronously). - } else { - ResponseCompleted(); - } -} - -void ResourceLoader::ReadMore(int* bytes_read) { - ResourceRequestInfoImpl* info = GetRequestInfo(); - DCHECK(!is_deferred()); - - net::IOBuffer* buf; - int buf_size; - if (!handler_->OnWillRead(info->GetRequestID(), &buf, &buf_size, -1)) { - Cancel(); - return; - } - - DCHECK(buf); - DCHECK(buf_size > 0); - - request_->Read(buf, buf_size, bytes_read); - - // No need to check the return value here as we'll detect errors by - // inspecting the URLRequest's status. -} - -void ResourceLoader::CompleteRead(int bytes_read) { - DCHECK(bytes_read >= 0); - DCHECK(request_->status().is_success()); - - ResourceRequestInfoImpl* info = GetRequestInfo(); - - bool defer = false; - if (!handler_->OnReadCompleted(info->GetRequestID(), bytes_read, &defer)) { - Cancel(); - } else if (defer) { - deferred_stage_ = DEFERRED_READ; // Read next chunk when resumed. - } -} - -void ResourceLoader::ResponseCompleted() { - VLOG(1) << "ResponseCompleted: " << request_->url().spec(); - ResourceRequestInfoImpl* info = GetRequestInfo(); - - std::string security_info; - const net::SSLInfo& ssl_info = request_->ssl_info(); - if (ssl_info.cert != NULL) { - int cert_id = CertStore::GetInstance()->StoreCert(ssl_info.cert, - info->GetChildID()); - security_info = SerializeSecurityInfo( - cert_id, ssl_info.cert_status, ssl_info.security_bits, - ssl_info.connection_status); - } - - if (handler_->OnResponseCompleted(info->GetRequestID(), request_->status(), - security_info)) { - // This will result in our destruction. - CallDidFinishLoading(); - } else { - // The handler is not ready to die yet. We will call DidFinishLoading when - // we resume. - deferred_stage_ = DEFERRED_FINISH; - } -} - -void ResourceLoader::CallDidFinishLoading() { - delegate_->DidFinishLoading(this); -} - -} // namespace content diff --git a/content/browser/renderer_host/resource_loader.h b/content/browser/renderer_host/resource_loader.h deleted file mode 100644 index 8937503..0000000 --- a/content/browser/renderer_host/resource_loader.h +++ /dev/null @@ -1,124 +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. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_RESOURCE_LOADER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_RESOURCE_LOADER_H_ - -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "content/browser/renderer_host/resource_handler.h" -#include "content/browser/ssl/ssl_error_handler.h" -#include "content/public/browser/resource_controller.h" -#include "net/url_request/url_request.h" - -namespace content { -class ResourceDispatcherHostLoginDelegate; -class ResourceLoaderDelegate; -class ResourceRequestInfoImpl; -class SSLClientAuthHandler; - -// This class is responsible for driving the URLRequest (i.e., calling Start, -// Read, and servicing events). It has a ResourceHandler, which is typically a -// chain of ResourceHandlers, and is the ResourceController for its handler. -class ResourceLoader : public net::URLRequest::Delegate, - public SSLErrorHandler::Delegate, - public ResourceController { - public: - ResourceLoader(scoped_ptr<net::URLRequest> request, - scoped_ptr<ResourceHandler> handler, - ResourceLoaderDelegate* delegate); - virtual ~ResourceLoader(); - - void StartRequest(); - void CancelRequest(bool from_renderer); - - void ReportUploadProgress(); - - bool is_transferring() const { return is_transferring_; } - void MarkAsTransferring(); - void WillCompleteTransfer(); - void CompleteTransfer(scoped_ptr<ResourceHandler> new_handler); - - net::URLRequest* request() { return request_.get(); } - ResourceRequestInfoImpl* GetRequestInfo(); - - void ClearLoginDelegate(); - void ClearSSLClientAuthHandler(); - - // IPC message handlers: - void OnUploadProgressACK(); - - private: - // net::URLRequest::Delegate implementation: - virtual void OnReceivedRedirect(net::URLRequest* request, - const GURL& new_url, - bool* defer) OVERRIDE; - virtual void OnAuthRequired(net::URLRequest* request, - net::AuthChallengeInfo* info) OVERRIDE; - virtual void OnCertificateRequested(net::URLRequest* request, - net::SSLCertRequestInfo* info) OVERRIDE; - virtual void OnSSLCertificateError(net::URLRequest* request, - const net::SSLInfo& info, - bool fatal) OVERRIDE; - virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE; - virtual void OnReadCompleted(net::URLRequest* request, - int bytes_read) OVERRIDE; - - // SSLErrorHandler::Delegate implementation: - virtual void CancelSSLRequest(const GlobalRequestID& id, - int error, - const net::SSLInfo* ssl_info) OVERRIDE; - virtual void ContinueSSLRequest(const GlobalRequestID& id) OVERRIDE; - - // ResourceController implementation: - virtual void Resume() OVERRIDE; - virtual void Cancel() OVERRIDE; - virtual void CancelAndIgnore() OVERRIDE; - virtual void CancelWithError(int error_code) OVERRIDE; - - void StartRequestInternal(); - void CancelRequestInternal(int error, bool from_renderer); - void CompleteResponseStarted(); - void StartReading(bool is_continuation); - void ResumeReading(); - void ReadMore(int* bytes_read); - void CompleteRead(int bytes_read); - void ResponseCompleted(); - void CallDidFinishLoading(); - - bool is_deferred() const { return deferred_stage_ != DEFERRED_NONE; } - - enum DeferredStage { - DEFERRED_NONE, - DEFERRED_START, - DEFERRED_REDIRECT, - DEFERRED_READ, - DEFERRED_FINISH - }; - DeferredStage deferred_stage_; - - scoped_ptr<net::URLRequest> request_; - scoped_ptr<ResourceHandler> handler_; - ResourceLoaderDelegate* delegate_; - - scoped_refptr<ResourceDispatcherHostLoginDelegate> login_delegate_; - scoped_refptr<SSLClientAuthHandler> ssl_client_auth_handler_; - - uint64 last_upload_position_; - bool waiting_for_upload_progress_ack_; - base::TimeTicks last_upload_ticks_; - - // Indicates that we are in a state of being transferred to a new downstream - // consumer. We are waiting for a notification to complete the transfer, at - // which point we'll receive a new ResourceHandler. - bool is_transferring_; - - base::WeakPtrFactory<ResourceLoader> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(ResourceLoader); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_RESOURCE_LOADER_H_ diff --git a/content/browser/renderer_host/resource_loader_delegate.h b/content/browser/renderer_host/resource_loader_delegate.h deleted file mode 100644 index 55f8960..0000000 --- a/content/browser/renderer_host/resource_loader_delegate.h +++ /dev/null @@ -1,49 +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. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_RESOURCE_LOADER_DELEGATE_H_ -#define CONTENT_BROWSER_RENDERER_HOST_RESOURCE_LOADER_DELEGATE_H_ - -#include "content/common/content_export.h" - -namespace net { -class AuthChallengeInfo; -class SSLCertRequestInfo; -} - -namespace content { -class ResourceDispatcherHostLoginDelegate; -class ResourceLoader; - -class CONTENT_EXPORT ResourceLoaderDelegate { - public: - virtual ResourceDispatcherHostLoginDelegate* CreateLoginDelegate( - ResourceLoader* loader, - net::AuthChallengeInfo* auth_info) = 0; - - virtual bool AcceptAuthRequest(ResourceLoader* loader, - net::AuthChallengeInfo* auth_info) = 0; - virtual bool AcceptSSLClientCertificateRequest( - ResourceLoader* loader, - net::SSLCertRequestInfo* cert_info) = 0; - - virtual bool HandleExternalProtocol(ResourceLoader* loader, - const GURL& url) = 0; - - virtual void DidStartRequest(ResourceLoader* loader) = 0; - virtual void DidReceiveRedirect(ResourceLoader* loader, - const GURL& new_url) = 0; - virtual void DidReceiveResponse(ResourceLoader* loader) = 0; - - // This method informs the delegate that the loader is done, and the loader - // expects to be destroyed as a side-effect of this call. - virtual void DidFinishLoading(ResourceLoader* loader) = 0; - - protected: - virtual ~ResourceLoaderDelegate() {} -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_RESOURCE_LOADER_DELEGATE_H_ diff --git a/content/browser/renderer_host/resource_message_filter.cc b/content/browser/renderer_host/resource_message_filter.cc deleted file mode 100644 index 5bf7f52..0000000 --- a/content/browser/renderer_host/resource_message_filter.cc +++ /dev/null @@ -1,55 +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/resource_message_filter.h" - -#include "content/browser/renderer_host/resource_dispatcher_host_impl.h" -#include "content/browser/appcache/chrome_appcache_service.h" -#include "content/browser/fileapi/chrome_blob_storage_context.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/resource_context.h" - -namespace content { - -ResourceMessageFilter::ResourceMessageFilter( - int child_id, - ProcessType process_type, - ResourceContext* resource_context, - ChromeAppCacheService* appcache_service, - ChromeBlobStorageContext* blob_storage_context, - URLRequestContextSelector* url_request_context_selector) - : child_id_(child_id), - process_type_(process_type), - resource_context_(resource_context), - appcache_service_(appcache_service), - blob_storage_context_(blob_storage_context), - url_request_context_selector_(url_request_context_selector) { - DCHECK(resource_context); - DCHECK(url_request_context_selector); - // |appcache_service| and |blob_storage_context| may be NULL in unittests. -} - -ResourceMessageFilter::~ResourceMessageFilter() { -} - -void ResourceMessageFilter::OnChannelClosing() { - BrowserMessageFilter::OnChannelClosing(); - - // Unhook us from all pending network requests so they don't get sent to a - // deleted object. - ResourceDispatcherHostImpl::Get()->CancelRequestsForProcess(child_id_); -} - -bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message, - bool* message_was_ok) { - return ResourceDispatcherHostImpl::Get()->OnMessageReceived( - message, this, message_was_ok); -} - -net::URLRequestContext* ResourceMessageFilter::GetURLRequestContext( - ResourceType::Type type) { - return url_request_context_selector_->GetRequestContext(type); -} - -} // namespace content diff --git a/content/browser/renderer_host/resource_message_filter.h b/content/browser/renderer_host/resource_message_filter.h deleted file mode 100644 index 86fda74..0000000 --- a/content/browser/renderer_host/resource_message_filter.h +++ /dev/null @@ -1,99 +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. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_RESOURCE_MESSAGE_FILTER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_RESOURCE_MESSAGE_FILTER_H_ - -#include "base/memory/scoped_ptr.h" -#include "content/common/content_export.h" -#include "content/public/browser/browser_message_filter.h" -#include "content/public/common/process_type.h" -#include "webkit/glue/resource_type.h" - -namespace net { -class URLRequestContext; -} // namespace net - - -namespace content { -class ChromeAppCacheService; -class ChromeBlobStorageContext; -class ResourceContext; - -// This class filters out incoming IPC messages for network requests and -// processes them on the IPC thread. As a result, network requests are not -// delayed by costly UI processing that may be occuring on the main thread of -// the browser. It also means that any hangs in starting a network request -// will not interfere with browser UI. -class CONTENT_EXPORT ResourceMessageFilter : public BrowserMessageFilter { - public: - // Allows selecting the net::URLRequestContext used to service requests. - class URLRequestContextSelector { - public: - URLRequestContextSelector() {} - virtual ~URLRequestContextSelector() {} - - virtual net::URLRequestContext* GetRequestContext( - ResourceType::Type request_type) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(URLRequestContextSelector); - }; - - ResourceMessageFilter( - int child_id, - ProcessType process_type, - ResourceContext* resource_context, - ChromeAppCacheService* appcache_service, - ChromeBlobStorageContext* blob_storage_context, - URLRequestContextSelector* url_request_context_selector); - - // BrowserMessageFilter implementation. - virtual void OnChannelClosing() OVERRIDE; - virtual bool OnMessageReceived(const IPC::Message& message, - bool* message_was_ok) OVERRIDE; - - ResourceContext* resource_context() const { - return resource_context_; - } - - ChromeAppCacheService* appcache_service() const { - return appcache_service_; - } - - ChromeBlobStorageContext* blob_storage_context() const { - return blob_storage_context_; - } - - // Returns the net::URLRequestContext for the given request. - net::URLRequestContext* GetURLRequestContext( - ResourceType::Type request_type); - - int child_id() const { return child_id_; } - ProcessType process_type() const { return process_type_; } - - protected: - // Protected destructor so that we can be overriden in tests. - virtual ~ResourceMessageFilter(); - - private: - // The ID of the child process. - int child_id_; - - ProcessType process_type_; - - // Owned by ProfileIOData* which is guaranteed to outlive us. - ResourceContext* resource_context_; - - scoped_refptr<ChromeAppCacheService> appcache_service_; - scoped_refptr<ChromeBlobStorageContext> blob_storage_context_; - - const scoped_ptr<URLRequestContextSelector> url_request_context_selector_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(ResourceMessageFilter); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_RESOURCE_MESSAGE_FILTER_H_ diff --git a/content/browser/renderer_host/resource_request_info_impl.cc b/content/browser/renderer_host/resource_request_info_impl.cc deleted file mode 100644 index cd3ce5e..0000000 --- a/content/browser/renderer_host/resource_request_info_impl.cc +++ /dev/null @@ -1,220 +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/resource_request_info_impl.h" - -#include "content/browser/worker_host/worker_service_impl.h" -#include "content/common/net/url_request_user_data.h" -#include "content/public/browser/global_request_id.h" -#include "net/url_request/url_request.h" -#include "webkit/blob/blob_data.h" - -namespace content { - -// ---------------------------------------------------------------------------- -// ResourceRequestInfo - -// static -const ResourceRequestInfo* ResourceRequestInfo::ForRequest( - const net::URLRequest* request) { - return ResourceRequestInfoImpl::ForRequest(request); -} - -// static -void ResourceRequestInfo::AllocateForTesting( - net::URLRequest* request, - ResourceType::Type resource_type, - ResourceContext* context, - int render_process_id, - int render_view_id) { - ResourceRequestInfoImpl* info = - new ResourceRequestInfoImpl( - PROCESS_TYPE_RENDERER, // process_type - render_process_id, // child_id - render_view_id, // route_id - 0, // origin_pid - 0, // request_id - resource_type == ResourceType::MAIN_FRAME, // is_main_frame - 0, // frame_id - false, // parent_is_main_frame - 0, // parent_frame_id - resource_type, // resource_type - PAGE_TRANSITION_LINK, // transition_type - false, // is_download - true, // allow_download - false, // has_user_gesture - WebKit::WebReferrerPolicyDefault, // referrer_policy - context); // context - info->AssociateWithRequest(request); -} - -// static -bool ResourceRequestInfo::GetRenderViewForRequest( - const net::URLRequest* request, - int* render_process_id, - int* render_view_id) { - URLRequestUserData* user_data = static_cast<URLRequestUserData*>( - request->GetUserData(URLRequestUserData::kUserDataKey)); - if (!user_data) - return false; - *render_process_id = user_data->render_process_id(); - *render_view_id = user_data->render_view_id(); - return true; -} - -// ---------------------------------------------------------------------------- -// ResourceRequestInfoImpl - -// static -ResourceRequestInfoImpl* ResourceRequestInfoImpl::ForRequest( - net::URLRequest* request) { - return static_cast<ResourceRequestInfoImpl*>(request->GetUserData(NULL)); -} - -// static -const ResourceRequestInfoImpl* ResourceRequestInfoImpl::ForRequest( - const net::URLRequest* request) { - return ForRequest(const_cast<net::URLRequest*>(request)); -} - -ResourceRequestInfoImpl::ResourceRequestInfoImpl( - ProcessType process_type, - int child_id, - int route_id, - int origin_pid, - int request_id, - bool is_main_frame, - int64 frame_id, - bool parent_is_main_frame, - int64 parent_frame_id, - ResourceType::Type resource_type, - PageTransition transition_type, - bool is_download, - bool allow_download, - bool has_user_gesture, - WebKit::WebReferrerPolicy referrer_policy, - ResourceContext* context) - : cross_site_handler_(NULL), - async_handler_(NULL), - process_type_(process_type), - child_id_(child_id), - route_id_(route_id), - origin_pid_(origin_pid), - request_id_(request_id), - is_main_frame_(is_main_frame), - frame_id_(frame_id), - parent_is_main_frame_(parent_is_main_frame), - parent_frame_id_(parent_frame_id), - is_download_(is_download), - allow_download_(allow_download), - has_user_gesture_(has_user_gesture), - was_ignored_by_handler_(false), - resource_type_(resource_type), - transition_type_(transition_type), - memory_cost_(0), - referrer_policy_(referrer_policy), - context_(context) { -} - -ResourceRequestInfoImpl::~ResourceRequestInfoImpl() { -} - -ResourceContext* ResourceRequestInfoImpl::GetContext() const { - return context_; -} - -int ResourceRequestInfoImpl::GetChildID() const { - return child_id_; -} - -int ResourceRequestInfoImpl::GetRouteID() const { - return route_id_; -} - -int ResourceRequestInfoImpl::GetOriginPID() const { - return origin_pid_; -} - -int ResourceRequestInfoImpl::GetRequestID() const { - return request_id_; -} - -bool ResourceRequestInfoImpl::IsMainFrame() const { - return is_main_frame_; -} - -int64 ResourceRequestInfoImpl::GetFrameID() const { - return frame_id_; -} - -bool ResourceRequestInfoImpl::ParentIsMainFrame() const { - return parent_is_main_frame_; -} - -int64 ResourceRequestInfoImpl::GetParentFrameID() const { - return parent_frame_id_; -} - -ResourceType::Type ResourceRequestInfoImpl::GetResourceType() const { - return resource_type_; -} - -WebKit::WebReferrerPolicy ResourceRequestInfoImpl::GetReferrerPolicy() const { - return referrer_policy_; -} - -bool ResourceRequestInfoImpl::HasUserGesture() const { - return has_user_gesture_; -} - -bool ResourceRequestInfoImpl::WasIgnoredByHandler() const { - return was_ignored_by_handler_; -} - -bool ResourceRequestInfoImpl::GetAssociatedRenderView( - int* render_process_id, - int* render_view_id) const { - // If the request is from the worker process, find a content that owns the - // worker. - if (process_type_ == PROCESS_TYPE_WORKER) { - // Need to display some related UI for this network request - pick an - // arbitrary parent to do so. - if (!WorkerServiceImpl::GetInstance()->GetRendererForWorker( - child_id_, render_process_id, render_view_id)) { - *render_process_id = -1; - *render_view_id = -1; - return false; - } - } else { - *render_process_id = child_id_; - *render_view_id = route_id_; - } - return true; -} - -bool ResourceRequestInfoImpl::IsAsync() const { - return async_handler_ != NULL; -} - -void ResourceRequestInfoImpl::AssociateWithRequest(net::URLRequest* request) { - request->SetUserData(NULL, this); - int render_process_id; - int render_view_id; - if (GetAssociatedRenderView(&render_process_id, &render_view_id)) { - request->SetUserData( - URLRequestUserData::kUserDataKey, - new URLRequestUserData(render_process_id, render_view_id)); - } -} - -GlobalRequestID ResourceRequestInfoImpl::GetGlobalRequestID() const { - return GlobalRequestID(child_id_, request_id_); -} - -void ResourceRequestInfoImpl::set_requested_blob_data( - webkit_blob::BlobData* data) { - requested_blob_data_ = data; -} - -} // namespace content diff --git a/content/browser/renderer_host/resource_request_info_impl.h b/content/browser/renderer_host/resource_request_info_impl.h deleted file mode 100644 index f989087..0000000 --- a/content/browser/renderer_host/resource_request_info_impl.h +++ /dev/null @@ -1,162 +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. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_RESOURCE_REQUEST_INFO_IMPL_H_ -#define CONTENT_BROWSER_RENDERER_HOST_RESOURCE_REQUEST_INFO_IMPL_H_ - -#include <string> - -#include "base/basictypes.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/supports_user_data.h" -#include "content/public/browser/resource_request_info.h" -#include "content/public/common/page_transition_types.h" -#include "content/public/common/process_type.h" -#include "content/public/common/referrer.h" -#include "net/base/load_states.h" -#include "webkit/glue/resource_type.h" - -namespace webkit_blob { -class BlobData; -} - -namespace content { -class AsyncResourceHandler; -class CrossSiteResourceHandler; -class ResourceContext; -struct GlobalRequestID; - -// Holds the data ResourceDispatcherHost associates with each request. -// Retrieve this data by calling ResourceDispatcherHost::InfoForRequest. -class ResourceRequestInfoImpl : public ResourceRequestInfo, - public base::SupportsUserData::Data { - public: - // Returns the ResourceRequestInfoImpl associated with the given URLRequest. - CONTENT_EXPORT static ResourceRequestInfoImpl* ForRequest( - net::URLRequest* request); - - // And, a const version for cases where you only need read access. - static const ResourceRequestInfoImpl* ForRequest( - const net::URLRequest* request); - - CONTENT_EXPORT ResourceRequestInfoImpl( - ProcessType process_type, - int child_id, - int route_id, - int origin_pid, - int request_id, - bool is_main_frame, - int64 frame_id, - bool parent_is_main_frame, - int64 parent_frame_id, - ResourceType::Type resource_type, - PageTransition transition_type, - bool is_download, - bool allow_download, - bool has_user_gesture, - WebKit::WebReferrerPolicy referrer_policy, - ResourceContext* context); - virtual ~ResourceRequestInfoImpl(); - - // ResourceRequestInfo implementation: - virtual ResourceContext* GetContext() const OVERRIDE; - virtual int GetChildID() const OVERRIDE; - virtual int GetRouteID() const OVERRIDE; - virtual int GetOriginPID() const OVERRIDE; - virtual int GetRequestID() const OVERRIDE; - virtual bool IsMainFrame() const OVERRIDE; - virtual int64 GetFrameID() const OVERRIDE; - virtual bool ParentIsMainFrame() const OVERRIDE; - virtual int64 GetParentFrameID() const OVERRIDE; - virtual ResourceType::Type GetResourceType() const OVERRIDE; - virtual WebKit::WebReferrerPolicy GetReferrerPolicy() const OVERRIDE; - virtual bool HasUserGesture() const OVERRIDE; - virtual bool WasIgnoredByHandler() const OVERRIDE; - virtual bool GetAssociatedRenderView(int* render_process_id, - int* render_view_id) const OVERRIDE; - virtual bool IsAsync() const OVERRIDE; - - - void AssociateWithRequest(net::URLRequest* request); - - GlobalRequestID GetGlobalRequestID() const; - - // CrossSiteResourceHandler for this request. May be null. - CrossSiteResourceHandler* cross_site_handler() { - return cross_site_handler_; - } - void set_cross_site_handler(CrossSiteResourceHandler* h) { - cross_site_handler_ = h; - } - - // AsyncResourceHandler for this request. May be null. - AsyncResourceHandler* async_handler() { - return async_handler_; - } - void set_async_handler(AsyncResourceHandler* h) { - async_handler_ = h; - } - - // Identifies the type of process (renderer, plugin, etc.) making the request. - ProcessType process_type() const { - return process_type_; - } - - // Downloads are allowed only as a top level request. - bool allow_download() const { return allow_download_; } - - // Whether this is a download. - bool is_download() const { return is_download_; } - void set_is_download(bool download) { is_download_ = download; } - - PageTransition transition_type() const { return transition_type_; } - - void set_was_ignored_by_handler(bool value) { - was_ignored_by_handler_ = value; - } - - // The approximate in-memory size (bytes) that we credited this request - // as consuming in |outstanding_requests_memory_cost_map_|. - int memory_cost() const { return memory_cost_; } - void set_memory_cost(int cost) { memory_cost_ = cost; } - - // We hold a reference to the requested blob data to ensure it doesn't - // get finally released prior to the net::URLRequestJob being started. - webkit_blob::BlobData* requested_blob_data() const { - return requested_blob_data_.get(); - } - void set_requested_blob_data(webkit_blob::BlobData* data); - - private: - // Non-owning, may be NULL. - CrossSiteResourceHandler* cross_site_handler_; - AsyncResourceHandler* async_handler_; - - ProcessType process_type_; - int child_id_; - int route_id_; - int origin_pid_; - int request_id_; - bool is_main_frame_; - int64 frame_id_; - bool parent_is_main_frame_; - int64 parent_frame_id_; - bool is_download_; - bool allow_download_; - bool has_user_gesture_; - bool was_ignored_by_handler_; - ResourceType::Type resource_type_; - PageTransition transition_type_; - int memory_cost_; - scoped_refptr<webkit_blob::BlobData> requested_blob_data_; - WebKit::WebReferrerPolicy referrer_policy_; - ResourceContext* context_; - - DISALLOW_COPY_AND_ASSIGN(ResourceRequestInfoImpl); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_RESOURCE_REQUEST_INFO_IMPL_H_ diff --git a/content/browser/renderer_host/socket_stream_dispatcher_host.h b/content/browser/renderer_host/socket_stream_dispatcher_host.h index 4709227..7426acc 100644 --- a/content/browser/renderer_host/socket_stream_dispatcher_host.h +++ b/content/browser/renderer_host/socket_stream_dispatcher_host.h @@ -9,7 +9,7 @@ #include "base/id_map.h" #include "base/memory/weak_ptr.h" -#include "content/browser/renderer_host/resource_message_filter.h" +#include "content/browser/loader/resource_message_filter.h" #include "content/browser/ssl/ssl_error_handler.h" #include "content/public/browser/browser_message_filter.h" #include "net/socket_stream/socket_stream.h" diff --git a/content/browser/renderer_host/sync_resource_handler.cc b/content/browser/renderer_host/sync_resource_handler.cc deleted file mode 100644 index c25c13d..0000000 --- a/content/browser/renderer_host/sync_resource_handler.cc +++ /dev/null @@ -1,130 +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/sync_resource_handler.h" - -#include "base/logging.h" -#include "content/browser/debugger/devtools_netlog_observer.h" -#include "content/browser/renderer_host/resource_dispatcher_host_impl.h" -#include "content/browser/renderer_host/resource_message_filter.h" -#include "content/common/resource_messages.h" -#include "content/public/browser/global_request_id.h" -#include "content/public/browser/resource_dispatcher_host_delegate.h" -#include "net/base/io_buffer.h" -#include "net/http/http_response_headers.h" - -namespace content { - -SyncResourceHandler::SyncResourceHandler( - ResourceMessageFilter* filter, - net::URLRequest* request, - IPC::Message* result_message, - ResourceDispatcherHostImpl* resource_dispatcher_host) - : read_buffer_(new net::IOBuffer(kReadBufSize)), - filter_(filter), - request_(request), - result_message_(result_message), - rdh_(resource_dispatcher_host) { - result_.final_url = request_->url(); -} - -SyncResourceHandler::~SyncResourceHandler() { - if (result_message_) { - result_message_->set_reply_error(); - filter_->Send(result_message_); - } -} - -bool SyncResourceHandler::OnUploadProgress(int request_id, - uint64 position, - uint64 size) { - return true; -} - -bool SyncResourceHandler::OnRequestRedirected( - int request_id, - const GURL& new_url, - ResourceResponse* response, - bool* defer) { - if (rdh_->delegate()) { - rdh_->delegate()->OnRequestRedirected(new_url, request_, - filter_->resource_context(), - response); - } - - DevToolsNetLogObserver::PopulateResponseInfo(request_, response); - // TODO(darin): It would be much better if this could live in WebCore, but - // doing so requires API changes at all levels. Similar code exists in - // WebCore/platform/network/cf/ResourceHandleCFNet.cpp :-( - if (new_url.GetOrigin() != result_.final_url.GetOrigin()) { - LOG(ERROR) << "Cross origin redirect denied"; - return false; - } - result_.final_url = new_url; - return true; -} - -bool SyncResourceHandler::OnResponseStarted( - int request_id, - ResourceResponse* response, - bool* defer) { - if (rdh_->delegate()) { - rdh_->delegate()->OnResponseStarted(request_, filter_->resource_context(), - response, filter_); - } - - DevToolsNetLogObserver::PopulateResponseInfo(request_, response); - - // We don't care about copying the status here. - result_.headers = response->head.headers; - result_.mime_type = response->head.mime_type; - result_.charset = response->head.charset; - result_.download_file_path = response->head.download_file_path; - result_.request_time = response->head.request_time; - result_.response_time = response->head.response_time; - result_.connection_id = response->head.connection_id; - result_.connection_reused = response->head.connection_reused; - result_.load_timing = response->head.load_timing; - result_.devtools_info = response->head.devtools_info; - return true; -} - -bool SyncResourceHandler::OnWillStart(int request_id, - const GURL& url, - bool* defer) { - return true; -} - -bool SyncResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf, - int* buf_size, int min_size) { - DCHECK(min_size == -1); - *buf = read_buffer_.get(); - *buf_size = kReadBufSize; - return true; -} - -bool SyncResourceHandler::OnReadCompleted(int request_id, int bytes_read, - bool* defer) { - if (!bytes_read) - return true; - result_.data.append(read_buffer_->data(), bytes_read); - return true; -} - -bool SyncResourceHandler::OnResponseCompleted( - int request_id, - const net::URLRequestStatus& status, - const std::string& security_info) { - result_.error_code = status.error(); - - result_.encoded_data_length = - DevToolsNetLogObserver::GetAndResetEncodedDataLength(request_); - - ResourceHostMsg_SyncLoad::WriteReplyParams(result_message_, result_); - filter_->Send(result_message_); - result_message_ = NULL; - return true; -} - -} // namespace content diff --git a/content/browser/renderer_host/sync_resource_handler.h b/content/browser/renderer_host/sync_resource_handler.h deleted file mode 100644 index 48da05b..0000000 --- a/content/browser/renderer_host/sync_resource_handler.h +++ /dev/null @@ -1,74 +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. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_SYNC_RESOURCE_HANDLER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_SYNC_RESOURCE_HANDLER_H_ - -#include <string> - -#include "content/browser/renderer_host/resource_handler.h" -#include "content/public/common/resource_response.h" - -namespace IPC { -class Message; -} - -namespace net { -class IOBuffer; -class URLRequest; -} - -namespace content { -class ResourceDispatcherHostImpl; -class ResourceMessageFilter; - -// Used to complete a synchronous resource request in response to resource load -// events from the resource dispatcher host. -class SyncResourceHandler : public ResourceHandler { - public: - SyncResourceHandler(ResourceMessageFilter* filter, - net::URLRequest* request, - IPC::Message* result_message, - ResourceDispatcherHostImpl* resource_dispatcher_host); - virtual ~SyncResourceHandler(); - - virtual bool OnUploadProgress(int request_id, - uint64 position, - uint64 size) OVERRIDE; - virtual bool OnRequestRedirected(int request_id, - const GURL& new_url, - ResourceResponse* response, - bool* defer) OVERRIDE; - virtual bool OnResponseStarted(int request_id, - ResourceResponse* response, - bool* defer) OVERRIDE; - virtual bool OnWillStart(int request_id, - const GURL& url, - bool* defer) OVERRIDE; - virtual bool OnWillRead(int request_id, - net::IOBuffer** buf, - int* buf_size, - int min_size) OVERRIDE; - virtual bool OnReadCompleted(int request_id, - int bytes_read, - bool* defer) OVERRIDE; - virtual bool OnResponseCompleted(int request_id, - const net::URLRequestStatus& status, - const std::string& security_info) OVERRIDE; - - private: - enum { kReadBufSize = 3840 }; - - scoped_refptr<net::IOBuffer> read_buffer_; - - SyncLoadResult result_; - scoped_refptr<ResourceMessageFilter> filter_; - net::URLRequest* request_; - IPC::Message* result_message_; - ResourceDispatcherHostImpl* rdh_; -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_SYNC_RESOURCE_HANDLER_H_ diff --git a/content/browser/renderer_host/throttling_resource_handler.cc b/content/browser/renderer_host/throttling_resource_handler.cc deleted file mode 100644 index bd4ad68..0000000 --- a/content/browser/renderer_host/throttling_resource_handler.cc +++ /dev/null @@ -1,184 +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/throttling_resource_handler.h" - -#include "content/public/browser/resource_throttle.h" -#include "content/public/common/resource_response.h" - -namespace content { - -ThrottlingResourceHandler::ThrottlingResourceHandler( - scoped_ptr<ResourceHandler> next_handler, - int child_id, - int request_id, - ScopedVector<ResourceThrottle> throttles) - : LayeredResourceHandler(next_handler.Pass()), - deferred_stage_(DEFERRED_NONE), - request_id_(request_id), - throttles_(throttles.Pass()), - index_(0), - cancelled_by_resource_throttle_(false) { - for (size_t i = 0; i < throttles_.size(); ++i) - throttles_[i]->set_controller(this); -} - -ThrottlingResourceHandler::~ThrottlingResourceHandler() { -} - -bool ThrottlingResourceHandler::OnRequestRedirected(int request_id, - const GURL& new_url, - ResourceResponse* response, - bool* defer) { - DCHECK_EQ(request_id_, request_id); - DCHECK(!cancelled_by_resource_throttle_); - - *defer = false; - while (index_ < throttles_.size()) { - throttles_[index_]->WillRedirectRequest(new_url, defer); - index_++; - if (cancelled_by_resource_throttle_) - return false; - if (*defer) { - deferred_stage_ = DEFERRED_REDIRECT; - deferred_url_ = new_url; - deferred_response_ = response; - return true; // Do not cancel. - } - } - - index_ = 0; // Reset for next time. - - return next_handler_->OnRequestRedirected(request_id, new_url, response, - defer); -} - -bool ThrottlingResourceHandler::OnWillStart(int request_id, - const GURL& url, - bool* defer) { - DCHECK_EQ(request_id_, request_id); - DCHECK(!cancelled_by_resource_throttle_); - - *defer = false; - while (index_ < throttles_.size()) { - throttles_[index_]->WillStartRequest(defer); - index_++; - if (cancelled_by_resource_throttle_) - return false; - if (*defer) { - deferred_stage_ = DEFERRED_START; - deferred_url_ = url; - return true; // Do not cancel. - } - } - - index_ = 0; // Reset for next time. - - return next_handler_->OnWillStart(request_id, url, defer); -} - -bool ThrottlingResourceHandler::OnResponseStarted(int request_id, - ResourceResponse* response, - bool* defer) { - DCHECK_EQ(request_id_, request_id); - DCHECK(!cancelled_by_resource_throttle_); - - while (index_ < throttles_.size()) { - throttles_[index_]->WillProcessResponse(defer); - index_++; - if (cancelled_by_resource_throttle_) - return false; - if (*defer) { - deferred_stage_ = DEFERRED_RESPONSE; - deferred_response_ = response; - return true; // Do not cancel. - } - } - - index_ = 0; // Reset for next time. - - return next_handler_->OnResponseStarted(request_id, response, defer); -} - -void ThrottlingResourceHandler::Cancel() { - cancelled_by_resource_throttle_ = true; - controller()->Cancel(); -} - -void ThrottlingResourceHandler::CancelAndIgnore() { - cancelled_by_resource_throttle_ = true; - controller()->CancelAndIgnore(); -} - -void ThrottlingResourceHandler::CancelWithError(int error_code) { - cancelled_by_resource_throttle_ = true; - controller()->CancelWithError(error_code); -} - -void ThrottlingResourceHandler::Resume() { - DCHECK(!cancelled_by_resource_throttle_); - - DeferredStage last_deferred_stage = deferred_stage_; - deferred_stage_ = DEFERRED_NONE; - switch (last_deferred_stage) { - case DEFERRED_NONE: - NOTREACHED(); - break; - case DEFERRED_START: - ResumeStart(); - break; - case DEFERRED_REDIRECT: - ResumeRedirect(); - break; - case DEFERRED_RESPONSE: - ResumeResponse(); - break; - } -} - -void ThrottlingResourceHandler::ResumeStart() { - DCHECK(!cancelled_by_resource_throttle_); - - GURL url = deferred_url_; - deferred_url_ = GURL(); - - bool defer = false; - if (!OnWillStart(request_id_, url, &defer)) { - controller()->Cancel(); - } else if (!defer) { - controller()->Resume(); - } -} - -void ThrottlingResourceHandler::ResumeRedirect() { - DCHECK(!cancelled_by_resource_throttle_); - - GURL new_url = deferred_url_; - deferred_url_ = GURL(); - scoped_refptr<ResourceResponse> response; - deferred_response_.swap(response); - - bool defer = false; - if (!OnRequestRedirected(request_id_, new_url, response, &defer)) { - controller()->Cancel(); - } else if (!defer) { - controller()->Resume(); - } -} - -void ThrottlingResourceHandler::ResumeResponse() { - DCHECK(!cancelled_by_resource_throttle_); - - scoped_refptr<ResourceResponse> response; - deferred_response_.swap(response); - - bool defer = false; - if (!OnResponseStarted(request_id_, response, &defer)) { - controller()->Cancel(); - } else if (!defer) { - controller()->Resume(); - } -} - -} // namespace content diff --git a/content/browser/renderer_host/throttling_resource_handler.h b/content/browser/renderer_host/throttling_resource_handler.h deleted file mode 100644 index 1636963..0000000 --- a/content/browser/renderer_host/throttling_resource_handler.h +++ /dev/null @@ -1,72 +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. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_THROTTLING_RESOURCE_HANDLER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_THROTTLING_RESOURCE_HANDLER_H_ - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_vector.h" -#include "content/browser/renderer_host/layered_resource_handler.h" -#include "content/public/browser/resource_controller.h" -#include "googleurl/src/gurl.h" - -namespace content { - -class ResourceThrottle; -struct ResourceResponse; - -// Used to apply a list of ResourceThrottle instances to an URLRequest. -class ThrottlingResourceHandler : public LayeredResourceHandler, - public ResourceController { - public: - // Takes ownership of the ResourceThrottle instances. - ThrottlingResourceHandler(scoped_ptr<ResourceHandler> next_handler, - int child_id, - int request_id, - ScopedVector<ResourceThrottle> throttles); - virtual ~ThrottlingResourceHandler(); - - // LayeredResourceHandler overrides: - virtual bool OnRequestRedirected(int request_id, const GURL& url, - ResourceResponse* response, - bool* defer) OVERRIDE; - virtual bool OnResponseStarted(int request_id, - ResourceResponse* response, - bool* defer) OVERRIDE; - virtual bool OnWillStart(int request_id, const GURL& url, - bool* defer) OVERRIDE; - - // ResourceThrottleController implementation: - virtual void Cancel() OVERRIDE; - virtual void CancelAndIgnore() OVERRIDE; - virtual void CancelWithError(int error_code) OVERRIDE; - virtual void Resume() OVERRIDE; - - private: - void ResumeStart(); - void ResumeRedirect(); - void ResumeResponse(); - - enum DeferredStage { - DEFERRED_NONE, - DEFERRED_START, - DEFERRED_REDIRECT, - DEFERRED_RESPONSE - }; - DeferredStage deferred_stage_; - - int request_id_; - - ScopedVector<ResourceThrottle> throttles_; - size_t index_; - - GURL deferred_url_; - scoped_refptr<ResourceResponse> deferred_response_; - - bool cancelled_by_resource_throttle_; -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_THROTTLING_RESOURCE_HANDLER_H_ diff --git a/content/browser/renderer_host/transfer_navigation_resource_throttle.cc b/content/browser/renderer_host/transfer_navigation_resource_throttle.cc deleted file mode 100644 index b623dad..0000000 --- a/content/browser/renderer_host/transfer_navigation_resource_throttle.cc +++ /dev/null @@ -1,88 +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/transfer_navigation_resource_throttle.h" - -#include "base/bind.h" -#include "content/browser/renderer_host/render_view_host_delegate.h" -#include "content/browser/renderer_host/resource_dispatcher_host_impl.h" -#include "content/public/browser/content_browser_client.h" -#include "content/public/browser/global_request_id.h" -#include "content/public/browser/render_view_host.h" -#include "content/public/browser/resource_request_info.h" -#include "content/public/common/referrer.h" -#include "net/url_request/url_request.h" - -namespace content { - -namespace { - -void RequestTransferURLOnUIThread(int render_process_id, - int render_view_id, - const GURL& new_url, - const Referrer& referrer, - WindowOpenDisposition window_open_disposition, - int64 frame_id, - const GlobalRequestID& global_request_id) { - RenderViewHost* rvh = - RenderViewHost::FromID(render_process_id, render_view_id); - if (!rvh) - return; - - RenderViewHostDelegate* delegate = rvh->GetDelegate(); - if (!delegate) - return; - - delegate->RequestTransferURL( - new_url, referrer, window_open_disposition, - frame_id, global_request_id, false); -} - -} // namespace - -TransferNavigationResourceThrottle::TransferNavigationResourceThrottle( - net::URLRequest* request) - : request_(request) { -} - -TransferNavigationResourceThrottle::~TransferNavigationResourceThrottle() { -} - -void TransferNavigationResourceThrottle::WillRedirectRequest( - const GURL& new_url, - bool* defer) { - const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_); - - // If a toplevel request is redirecting across extension extents, we want to - // switch processes. We do this by deferring the redirect and resuming the - // request once the navigation controller properly assigns the right process - // to host the new URL. - // TODO(mpcomplete): handle for cases other than extensions (e.g. WebUI). - ResourceContext* resource_context = info->GetContext(); - if (GetContentClient()->browser()->ShouldSwapProcessesForRedirect( - resource_context, request_->url(), new_url)) { - int render_process_id, render_view_id; - if (info->GetAssociatedRenderView(&render_process_id, &render_view_id)) { - GlobalRequestID global_id(info->GetChildID(), info->GetRequestID()); - - ResourceDispatcherHostImpl::Get()->MarkAsTransferredNavigation(global_id); - - BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(&RequestTransferURLOnUIThread, - render_process_id, - render_view_id, - new_url, - Referrer(GURL(request_->referrer()), info->GetReferrerPolicy()), - CURRENT_TAB, - info->GetFrameID(), - global_id)); - - *defer = true; - } - } -} - -} // namespace content diff --git a/content/browser/renderer_host/transfer_navigation_resource_throttle.h b/content/browser/renderer_host/transfer_navigation_resource_throttle.h deleted file mode 100644 index 3093836..0000000 --- a/content/browser/renderer_host/transfer_navigation_resource_throttle.h +++ /dev/null @@ -1,38 +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. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_TRANSFER_NAVIGATION_RESOURCE_THROTTLE_H_ -#define CONTENT_BROWSER_RENDERER_HOST_TRANSFER_NAVIGATION_RESOURCE_THROTTLE_H_ - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "content/public/browser/resource_throttle.h" - -namespace net { -class URLRequest; -} - -namespace content { - -// This ResourceThrottle checks whether a navigation redirect will cause a -// renderer process swap. When that happens, we remember the request so -// that we can transfer it to be handled by the new renderer. This fixes -// http://crbug.com/79520 -class TransferNavigationResourceThrottle : public ResourceThrottle { - public: - explicit TransferNavigationResourceThrottle(net::URLRequest* request); - virtual ~TransferNavigationResourceThrottle(); - - // ResourceThrottle implementation: - virtual void WillRedirectRequest(const GURL& new_url, bool* defer) OVERRIDE; - - private: - net::URLRequest* request_; - - DISALLOW_COPY_AND_ASSIGN(TransferNavigationResourceThrottle); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_TRANSFER_NAVIGATION_RESOURCE_THROTTLE_H_ diff --git a/content/browser/renderer_host/x509_user_cert_resource_handler.cc b/content/browser/renderer_host/x509_user_cert_resource_handler.cc deleted file mode 100644 index aa3fe34..0000000 --- a/content/browser/renderer_host/x509_user_cert_resource_handler.cc +++ /dev/null @@ -1,140 +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/x509_user_cert_resource_handler.h" - -#include "base/string_util.h" -#include "content/browser/renderer_host/resource_request_info_impl.h" -#include "content/public/browser/content_browser_client.h" -#include "content/public/common/resource_response.h" -#include "net/base/io_buffer.h" -#include "net/base/mime_sniffer.h" -#include "net/base/mime_util.h" -#include "net/base/x509_certificate.h" -#include "net/http/http_response_headers.h" -#include "net/url_request/url_request.h" -#include "net/url_request/url_request_status.h" - -namespace content { - -X509UserCertResourceHandler::X509UserCertResourceHandler( - net::URLRequest* request, - int render_process_host_id, - int render_view_id) - : request_(request), - content_length_(0), - read_buffer_(NULL), - resource_buffer_(NULL), - render_process_host_id_(render_process_host_id), - render_view_id_(render_view_id) { -} - -X509UserCertResourceHandler::~X509UserCertResourceHandler() { -} - -bool X509UserCertResourceHandler::OnUploadProgress(int request_id, - uint64 position, - uint64 size) { - return true; -} - -bool X509UserCertResourceHandler::OnRequestRedirected(int request_id, - const GURL& url, - ResourceResponse* resp, - bool* defer) { - url_ = url; - return true; -} - -bool X509UserCertResourceHandler::OnResponseStarted(int request_id, - ResourceResponse* resp, - bool* defer) { - return (resp->head.mime_type == "application/x-x509-user-cert"); -} - -bool X509UserCertResourceHandler::OnWillStart(int request_id, - const GURL& url, - bool* defer) { - return true; -} - -bool X509UserCertResourceHandler::OnWillRead(int request_id, - net::IOBuffer** buf, - int* buf_size, - int min_size) { - static const int kReadBufSize = 32768; - - // TODO(gauravsh): Should we use 'min_size' here? - DCHECK(buf && buf_size); - if (!read_buffer_) { - read_buffer_ = new net::IOBuffer(kReadBufSize); - } - *buf = read_buffer_.get(); - *buf_size = kReadBufSize; - - return true; -} - -bool X509UserCertResourceHandler::OnReadCompleted(int request_id, - int bytes_read, - bool* defer) { - if (!bytes_read) - return true; - - // We have more data to read. - DCHECK(read_buffer_); - content_length_ += bytes_read; - - // Release the ownership of the buffer, and store a reference - // to it. A new one will be allocated in OnWillRead(). - net::IOBuffer* buffer = NULL; - read_buffer_.swap(&buffer); - // TODO(gauravsh): Should this be handled by a separate thread? - buffer_.push_back(std::make_pair(buffer, bytes_read)); - - return true; -} - -bool X509UserCertResourceHandler::OnResponseCompleted( - int request_id, - const net::URLRequestStatus& urs, - const std::string& sec_info) { - if (urs.status() != net::URLRequestStatus::SUCCESS) - return false; - - AssembleResource(); - scoped_refptr<net::X509Certificate> cert; - if (resource_buffer_) { - cert = net::X509Certificate::CreateFromBytes(resource_buffer_->data(), - content_length_); - } - GetContentClient()->browser()->AddNewCertificate( - request_, cert, render_process_host_id_, render_view_id_); - return true; -} - -void X509UserCertResourceHandler::AssembleResource() { - // 0-length IOBuffers are not allowed. - if (content_length_ == 0) { - resource_buffer_ = NULL; - return; - } - - // Create the new buffer. - resource_buffer_ = new net::IOBuffer(content_length_); - - // Copy the data into it. - size_t bytes_copied = 0; - for (size_t i = 0; i < buffer_.size(); ++i) { - net::IOBuffer* data = buffer_[i].first; - size_t data_len = buffer_[i].second; - DCHECK(data != NULL); - DCHECK_LE(bytes_copied + data_len, content_length_); - memcpy(resource_buffer_->data() + bytes_copied, data->data(), data_len); - bytes_copied += data_len; - } - DCHECK_EQ(content_length_, bytes_copied); -} - -} // namespace content diff --git a/content/browser/renderer_host/x509_user_cert_resource_handler.h b/content/browser/renderer_host/x509_user_cert_resource_handler.h deleted file mode 100644 index 13dbba6..0000000 --- a/content/browser/renderer_host/x509_user_cert_resource_handler.h +++ /dev/null @@ -1,95 +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. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_X509_USER_CERT_RESOURCE_HANDLER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_X509_USER_CERT_RESOURCE_HANDLER_H_ - -#include <string> -#include <utility> -#include <vector> - -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/ref_counted.h" -#include "content/browser/renderer_host/resource_handler.h" -#include "googleurl/src/gurl.h" - -namespace net { -class IOBuffer; -class URLRequest; -class URLRequestStatus; -} // namespace net - -namespace content { - -// This class handles the "application/x-x509-user-cert" mime-type -// which is a certificate generated by a CA, typically after a previous -// <keygen> form post. - -class X509UserCertResourceHandler : public ResourceHandler { - public: - X509UserCertResourceHandler(net::URLRequest* request, - int render_process_host_id, - int render_view_id); - virtual ~X509UserCertResourceHandler(); - - virtual bool OnUploadProgress(int request_id, - uint64 position, - uint64 size) OVERRIDE; - - // Not needed, as this event handler ought to be the final resource. - virtual bool OnRequestRedirected(int request_id, - const GURL& url, - ResourceResponse* resp, - bool* defer) OVERRIDE; - - // Check if this indeed an X509 cert. - virtual bool OnResponseStarted(int request_id, - ResourceResponse* resp, - bool* defer) OVERRIDE; - - // Pass-through implementation. - virtual bool OnWillStart(int request_id, - const GURL& url, - bool* defer) OVERRIDE; - - // Create a new buffer to store received data. - virtual bool OnWillRead(int request_id, - net::IOBuffer** buf, - int* buf_size, - int min_size) OVERRIDE; - - // A read was completed, maybe allocate a new buffer for further data. - virtual bool OnReadCompleted(int request_id, - int bytes_read, - bool* defer) OVERRIDE; - - // Done downloading the certificate. - virtual bool OnResponseCompleted(int request_id, - const net::URLRequestStatus& urs, - const std::string& sec_info) OVERRIDE; - - private: - typedef std::vector<std::pair<scoped_refptr<net::IOBuffer>, - size_t> > ContentVector; - - void AssembleResource(); - - GURL url_; - net::URLRequest* request_; - size_t content_length_; - ContentVector buffer_; - scoped_refptr<net::IOBuffer> read_buffer_; - scoped_refptr<net::IOBuffer> resource_buffer_; // Downloaded certificate. - // The id of the |RenderProcessHost| which started the download. - int render_process_host_id_; - // The id of the |RenderView| which started the download. - int render_view_id_; - - DISALLOW_COPY_AND_ASSIGN(X509UserCertResourceHandler); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_X509_USER_CERT_RESOURCE_HANDLER_H_ |