// 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 "chrome/browser/net/resource_prefetch_predictor_observer.h" #include #include "base/metrics/histogram.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/resource_request_info.h" #include "googleurl/src/gurl.h" #include "net/url_request/url_request.h" using content::BrowserThread; using predictors::ResourcePrefetchPredictor; namespace { // Enum for measuring statistics pertaining to observed request, responses and // redirects. enum RequestStats { REQUEST_STATS_TOTAL_RESPONSES = 0, REQUEST_STATS_TOTAL_PROCESSED_RESPONSES = 1, REQUEST_STATS_NO_RESOURCE_REQUEST_INFO = 2, REQUEST_STATS_NO_RENDER_VIEW_ID_FROM_REQUEST_INFO = 3, REQUEST_STATS_MAX = 4, }; // Specific to main frame requests. enum MainFrameRequestStats { MAIN_FRAME_REQUEST_STATS_TOTAL_REQUESTS = 0, MAIN_FRAME_REQUEST_STATS_PROCESSED_REQUESTS = 1, MAIN_FRAME_REQUEST_STATS_TOTAL_REDIRECTS = 2, MAIN_FRAME_REQUEST_STATS_PROCESSED_REDIRECTS = 3, MAIN_FRAME_REQUEST_STATS_TOTAL_RESPONSES = 4, MAIN_FRAME_REQUEST_STATS_PROCESSED_RESPONSES = 5, MAIN_FRAME_REQUEST_STATS_MAX = 6, }; void ReportRequestStats(RequestStats stat) { UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.RequestStats", stat, REQUEST_STATS_MAX); } void ReportMainFrameRequestStats(MainFrameRequestStats stat) { UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.MainFrameRequestStats", stat, MAIN_FRAME_REQUEST_STATS_MAX); } bool SummarizeResponse(net::URLRequest* request, ResourcePrefetchPredictor::URLRequestSummary* summary) { const content::ResourceRequestInfo* info = content::ResourceRequestInfo::ForRequest(request); if (!info) { ReportRequestStats(REQUEST_STATS_NO_RESOURCE_REQUEST_INFO); return false; } int render_process_id, render_view_id; if (!info->GetAssociatedRenderView(&render_process_id, &render_view_id)) { ReportRequestStats(REQUEST_STATS_NO_RENDER_VIEW_ID_FROM_REQUEST_INFO); return false; } summary->navigation_id.render_process_id = render_process_id; summary->navigation_id.render_view_id = render_view_id; summary->navigation_id.main_frame_url = request->first_party_for_cookies(); summary->navigation_id.creation_time = request->creation_time(); summary->resource_url = request->original_url(); summary->resource_type = info->GetResourceType(); request->GetMimeType(&summary->mime_type); summary->was_cached = request->was_cached(); // Use the mime_type to determine the resource type for subresources since // types such as PREFETCH, SUB_RESOURCE, etc are not useful. if (summary->resource_type != ResourceType::MAIN_FRAME) { summary->resource_type = ResourcePrefetchPredictor::GetResourceTypeFromMimeType( summary->mime_type, summary->resource_type); } return true; } } // namespace namespace chrome_browser_net { ResourcePrefetchPredictorObserver::ResourcePrefetchPredictorObserver( ResourcePrefetchPredictor* predictor) : predictor_(predictor->AsWeakPtr()) { CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); } ResourcePrefetchPredictorObserver::~ResourcePrefetchPredictorObserver() { CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || BrowserThread::CurrentlyOn(BrowserThread::IO)); } void ResourcePrefetchPredictorObserver::OnRequestStarted( net::URLRequest* request, ResourceType::Type resource_type, int child_id, int route_id) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); if (resource_type == ResourceType::MAIN_FRAME) ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_TOTAL_REQUESTS); if (!ResourcePrefetchPredictor::ShouldRecordRequest(request, resource_type)) return; ResourcePrefetchPredictor::URLRequestSummary summary; summary.navigation_id.render_process_id = child_id; summary.navigation_id.render_view_id = route_id; summary.navigation_id.main_frame_url = request->first_party_for_cookies(); summary.resource_url = request->original_url(); summary.resource_type = resource_type; BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(&ResourcePrefetchPredictor::RecordURLRequest, predictor_, summary)); if (resource_type == ResourceType::MAIN_FRAME) ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_PROCESSED_REQUESTS); } void ResourcePrefetchPredictorObserver::OnRequestRedirected( const GURL& redirect_url, net::URLRequest* request) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); const content::ResourceRequestInfo* request_info = content::ResourceRequestInfo::ForRequest(request); if (request_info && request_info->GetResourceType() == ResourceType::MAIN_FRAME) { ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_TOTAL_REDIRECTS); } if (!ResourcePrefetchPredictor::ShouldRecordRedirect(request)) return; ResourcePrefetchPredictor::URLRequestSummary summary; if (!SummarizeResponse(request, &summary)) return; summary.redirect_url = redirect_url; BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(&ResourcePrefetchPredictor::RecordUrlRedirect, predictor_, summary)); if (request_info && request_info->GetResourceType() == ResourceType::MAIN_FRAME) { ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_PROCESSED_REDIRECTS); } } void ResourcePrefetchPredictorObserver::OnResponseStarted( net::URLRequest* request) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); ReportRequestStats(REQUEST_STATS_TOTAL_RESPONSES); const content::ResourceRequestInfo* request_info = content::ResourceRequestInfo::ForRequest(request); if (request_info && request_info->GetResourceType() == ResourceType::MAIN_FRAME) { ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_TOTAL_RESPONSES); } if (!ResourcePrefetchPredictor::ShouldRecordResponse(request)) return; ResourcePrefetchPredictor::URLRequestSummary summary; if (!SummarizeResponse(request, &summary)) return; BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(&ResourcePrefetchPredictor::RecordUrlResponse, predictor_, summary)); ReportRequestStats(REQUEST_STATS_TOTAL_PROCESSED_RESPONSES); if (request_info && request_info->GetResourceType() == ResourceType::MAIN_FRAME) { ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_PROCESSED_RESPONSES); } } } // namespace chrome_browser_net