| Index: content/browser/loader/detachable_resource_handler.cc
|
| diff --git a/content/browser/loader/detachable_resource_handler.cc b/content/browser/loader/detachable_resource_handler.cc
|
| index 42c7d1f191d5a6261dfbc2bf265d689b313886f9..88e402bf65a49e00ba5a59fea5c6c67b23cf0512 100644
|
| --- a/content/browser/loader/detachable_resource_handler.cc
|
| +++ b/content/browser/loader/detachable_resource_handler.cc
|
| @@ -5,6 +5,7 @@
|
| #include "content/browser/loader/detachable_resource_handler.h"
|
|
|
| #include "base/logging.h"
|
| +#include "base/metrics/histogram.h"
|
| #include "base/time/time.h"
|
| #include "content/browser/loader/resource_request_info_impl.h"
|
| #include "net/base/io_buffer.h"
|
| @@ -12,9 +13,29 @@
|
| #include "net/url_request/url_request_status.h"
|
|
|
| namespace {
|
| +
|
| // This matches the maximum allocation size of AsyncResourceHandler.
|
| const int kReadBufSize = 32 * 1024;
|
| -}
|
| +
|
| +// Enum type for <a ping> result histograms. Only add new values to the end.
|
| +enum UMAPingResultType {
|
| + // The ping request completed successfully.
|
| + UMA_PING_RESULT_TYPE_SUCCESS = 0,
|
| + // The ping request received a response, but did not consume the entire body.
|
| + UMA_PING_RESULT_TYPE_RESPONSE_STARTED = 1,
|
| + // The ping request was canceled due to the internal timeout.
|
| + UMA_PING_RESULT_TYPE_TIMEDOUT = 2,
|
| + // The ping request was canceled for some other reason.
|
| + UMA_PING_RESULT_TYPE_CANCELED = 3,
|
| + // The ping request failed for some reason.
|
| + UMA_PING_RESULT_TYPE_FAILED = 4,
|
| + // The ping request was deleted before OnResponseCompleted.
|
| + UMA_PING_RESULT_TYPE_UNCOMPLETED = 5,
|
| +
|
| + UMA_PING_RESULT_TYPE_MAX,
|
| +};
|
| +
|
| +} // namespace
|
|
|
| namespace content {
|
|
|
| @@ -26,13 +47,51 @@ DetachableResourceHandler::DetachableResourceHandler(
|
| next_handler_(next_handler.Pass()),
|
| cancel_delay_(cancel_delay),
|
| is_deferred_(false),
|
| - is_finished_(false) {
|
| + is_finished_(false),
|
| + timed_out_(false),
|
| + response_started_(false),
|
| + status_(net::URLRequestStatus::IO_PENDING) {
|
| GetRequestInfo()->set_detachable_handler(this);
|
| }
|
|
|
| DetachableResourceHandler::~DetachableResourceHandler() {
|
| // Cleanup back-pointer stored on the request info.
|
| GetRequestInfo()->set_detachable_handler(NULL);
|
| +
|
| + // Record the status of <a ping> requests.
|
| + // http://crbug.com/302816
|
| + if (GetRequestInfo()->GetResourceType() == ResourceType::PING) {
|
| + UMAPingResultType result_type = UMA_PING_RESULT_TYPE_MAX;
|
| +
|
| + if (status_ == net::URLRequestStatus::SUCCESS) {
|
| + result_type = UMA_PING_RESULT_TYPE_SUCCESS;
|
| + } else if (response_started_) {
|
| + // However the request ended, bucket this under RESPONSE_STARTED because
|
| + // OnResponseStarted was received. Note: OnResponseCompleted is also sent
|
| + // when a request is canceled before completion, so it is possible to
|
| + // receive OnResponseCompleted without OnResponseStarted.
|
| + result_type = UMA_PING_RESULT_TYPE_RESPONSE_STARTED;
|
| + } else if (status_ == net::URLRequestStatus::IO_PENDING) {
|
| + // The request was deleted without OnResponseCompleted and before any
|
| + // response was received.
|
| + result_type = UMA_PING_RESULT_TYPE_UNCOMPLETED;
|
| + } else if (status_ == net::URLRequestStatus::CANCELED) {
|
| + if (timed_out_) {
|
| + result_type = UMA_PING_RESULT_TYPE_TIMEDOUT;
|
| + } else {
|
| + result_type = UMA_PING_RESULT_TYPE_CANCELED;
|
| + }
|
| + } else if (status_ == net::URLRequestStatus::FAILED) {
|
| + result_type = UMA_PING_RESULT_TYPE_FAILED;
|
| + }
|
| +
|
| + if (result_type < UMA_PING_RESULT_TYPE_MAX) {
|
| + UMA_HISTOGRAM_ENUMERATION("Net.Ping_Result", result_type,
|
| + UMA_PING_RESULT_TYPE_MAX);
|
| + } else {
|
| + NOTREACHED();
|
| + }
|
| + }
|
| }
|
|
|
| void DetachableResourceHandler::Detach() {
|
| @@ -65,7 +124,7 @@ void DetachableResourceHandler::Detach() {
|
| // Time the request out if it takes too long.
|
| detached_timer_.reset(new base::OneShotTimer<DetachableResourceHandler>());
|
| detached_timer_->Start(
|
| - FROM_HERE, cancel_delay_, this, &DetachableResourceHandler::Cancel);
|
| + FROM_HERE, cancel_delay_, this, &DetachableResourceHandler::TimedOut);
|
|
|
| // Resume if necessary. The request may have been deferred, say, waiting on a
|
| // full buffer in AsyncResourceHandler. Now that it has been detached, resume
|
| @@ -111,6 +170,15 @@ bool DetachableResourceHandler::OnResponseStarted(int request_id,
|
| ResourceResponse* response,
|
| bool* defer) {
|
| DCHECK(!is_deferred_);
|
| + DCHECK(!response_started_);
|
| + response_started_ = true;
|
| +
|
| + // Record how long it takes for <a ping> to respond.
|
| + // http://crbug.com/302816
|
| + if (GetRequestInfo()->GetResourceType() == ResourceType::PING) {
|
| + UMA_HISTOGRAM_MEDIUM_TIMES("Net.Ping_ResponseStartedTime",
|
| + time_since_start_.Elapsed());
|
| + }
|
|
|
| if (!next_handler_)
|
| return true;
|
| @@ -184,6 +252,9 @@ void DetachableResourceHandler::OnResponseCompleted(
|
| // No DCHECK(!is_deferred_) as the request may have been cancelled while
|
| // deferred.
|
|
|
| + status_ = status.status();
|
| + DCHECK_NE(net::URLRequestStatus::IO_PENDING, status_);
|
| +
|
| if (!next_handler_)
|
| return;
|
|
|
| @@ -220,4 +291,9 @@ void DetachableResourceHandler::CancelWithError(int error_code) {
|
| controller()->CancelWithError(error_code);
|
| }
|
|
|
| +void DetachableResourceHandler::TimedOut() {
|
| + timed_out_ = true;
|
| + controller()->Cancel();
|
| +}
|
| +
|
| } // namespace content
|
|
|