1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/net/resource_prefetch_predictor_observer.h" 6 7 #include <string> 8 9 #include "base/metrics/histogram.h" 10 #include "content/public/browser/browser_thread.h" 11 #include "content/public/browser/resource_request_info.h" 12 #include "net/url_request/url_request.h" 13 #include "url/gurl.h" 14 15 using content::BrowserThread; 16 using predictors::ResourcePrefetchPredictor; 17 18 namespace { 19 20 // Enum for measuring statistics pertaining to observed request, responses and 21 // redirects. 22 enum RequestStats { 23 REQUEST_STATS_TOTAL_RESPONSES = 0, 24 REQUEST_STATS_TOTAL_PROCESSED_RESPONSES = 1, 25 REQUEST_STATS_NO_RESOURCE_REQUEST_INFO = 2, 26 REQUEST_STATS_NO_RENDER_VIEW_ID_FROM_REQUEST_INFO = 3, 27 REQUEST_STATS_MAX = 4, 28 }; 29 30 // Specific to main frame requests. 31 enum MainFrameRequestStats { 32 MAIN_FRAME_REQUEST_STATS_TOTAL_REQUESTS = 0, 33 MAIN_FRAME_REQUEST_STATS_PROCESSED_REQUESTS = 1, 34 MAIN_FRAME_REQUEST_STATS_TOTAL_REDIRECTS = 2, 35 MAIN_FRAME_REQUEST_STATS_PROCESSED_REDIRECTS = 3, 36 MAIN_FRAME_REQUEST_STATS_TOTAL_RESPONSES = 4, 37 MAIN_FRAME_REQUEST_STATS_PROCESSED_RESPONSES = 5, 38 MAIN_FRAME_REQUEST_STATS_MAX = 6, 39 }; 40 41 void ReportRequestStats(RequestStats stat) { 42 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.RequestStats", 43 stat, 44 REQUEST_STATS_MAX); 45 } 46 47 void ReportMainFrameRequestStats(MainFrameRequestStats stat) { 48 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.MainFrameRequestStats", 49 stat, 50 MAIN_FRAME_REQUEST_STATS_MAX); 51 } 52 53 bool SummarizeResponse(net::URLRequest* request, 54 ResourcePrefetchPredictor::URLRequestSummary* summary) { 55 const content::ResourceRequestInfo* info = 56 content::ResourceRequestInfo::ForRequest(request); 57 if (!info) { 58 ReportRequestStats(REQUEST_STATS_NO_RESOURCE_REQUEST_INFO); 59 return false; 60 } 61 62 int render_process_id, render_view_id; 63 if (!info->GetAssociatedRenderView(&render_process_id, &render_view_id)) { 64 ReportRequestStats(REQUEST_STATS_NO_RENDER_VIEW_ID_FROM_REQUEST_INFO); 65 return false; 66 } 67 68 summary->navigation_id.render_process_id = render_process_id; 69 summary->navigation_id.render_view_id = render_view_id; 70 summary->navigation_id.main_frame_url = request->first_party_for_cookies(); 71 summary->navigation_id.creation_time = request->creation_time(); 72 summary->resource_url = request->original_url(); 73 summary->resource_type = info->GetResourceType(); 74 request->GetMimeType(&summary->mime_type); 75 summary->was_cached = request->was_cached(); 76 77 // Use the mime_type to determine the resource type for subresources since 78 // types such as PREFETCH, SUB_RESOURCE, etc are not useful. 79 if (summary->resource_type != ResourceType::MAIN_FRAME) { 80 summary->resource_type = 81 ResourcePrefetchPredictor::GetResourceTypeFromMimeType( 82 summary->mime_type, 83 summary->resource_type); 84 } 85 return true; 86 } 87 88 } // namespace 89 90 namespace chrome_browser_net { 91 92 ResourcePrefetchPredictorObserver::ResourcePrefetchPredictorObserver( 93 ResourcePrefetchPredictor* predictor) 94 : predictor_(predictor->AsWeakPtr()) { 95 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 96 } 97 98 ResourcePrefetchPredictorObserver::~ResourcePrefetchPredictorObserver() { 99 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || 100 BrowserThread::CurrentlyOn(BrowserThread::IO)); 101 } 102 103 void ResourcePrefetchPredictorObserver::OnRequestStarted( 104 net::URLRequest* request, 105 ResourceType::Type resource_type, 106 int child_id, 107 int route_id) { 108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 109 110 if (resource_type == ResourceType::MAIN_FRAME) 111 ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_TOTAL_REQUESTS); 112 113 if (!ResourcePrefetchPredictor::ShouldRecordRequest(request, resource_type)) 114 return; 115 116 ResourcePrefetchPredictor::URLRequestSummary summary; 117 summary.navigation_id.render_process_id = child_id; 118 summary.navigation_id.render_view_id = route_id; 119 summary.navigation_id.main_frame_url = request->first_party_for_cookies(); 120 summary.resource_url = request->original_url(); 121 summary.resource_type = resource_type; 122 123 BrowserThread::PostTask( 124 BrowserThread::UI, 125 FROM_HERE, 126 base::Bind(&ResourcePrefetchPredictor::RecordURLRequest, 127 predictor_, 128 summary)); 129 130 if (resource_type == ResourceType::MAIN_FRAME) 131 ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_PROCESSED_REQUESTS); 132 } 133 134 void ResourcePrefetchPredictorObserver::OnRequestRedirected( 135 const GURL& redirect_url, 136 net::URLRequest* request) { 137 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 138 139 const content::ResourceRequestInfo* request_info = 140 content::ResourceRequestInfo::ForRequest(request); 141 if (request_info && 142 request_info->GetResourceType() == ResourceType::MAIN_FRAME) { 143 ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_TOTAL_REDIRECTS); 144 } 145 146 if (!ResourcePrefetchPredictor::ShouldRecordRedirect(request)) 147 return; 148 149 ResourcePrefetchPredictor::URLRequestSummary summary; 150 if (!SummarizeResponse(request, &summary)) 151 return; 152 153 summary.redirect_url = redirect_url; 154 155 BrowserThread::PostTask( 156 BrowserThread::UI, 157 FROM_HERE, 158 base::Bind(&ResourcePrefetchPredictor::RecordUrlRedirect, 159 predictor_, 160 summary)); 161 162 if (request_info && 163 request_info->GetResourceType() == ResourceType::MAIN_FRAME) { 164 ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_PROCESSED_REDIRECTS); 165 } 166 } 167 168 void ResourcePrefetchPredictorObserver::OnResponseStarted( 169 net::URLRequest* request) { 170 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 171 172 ReportRequestStats(REQUEST_STATS_TOTAL_RESPONSES); 173 174 const content::ResourceRequestInfo* request_info = 175 content::ResourceRequestInfo::ForRequest(request); 176 if (request_info && 177 request_info->GetResourceType() == ResourceType::MAIN_FRAME) { 178 ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_TOTAL_RESPONSES); 179 } 180 181 if (!ResourcePrefetchPredictor::ShouldRecordResponse(request)) 182 return; 183 ResourcePrefetchPredictor::URLRequestSummary summary; 184 if (!SummarizeResponse(request, &summary)) 185 return; 186 187 BrowserThread::PostTask( 188 BrowserThread::UI, 189 FROM_HERE, 190 base::Bind(&ResourcePrefetchPredictor::RecordUrlResponse, 191 predictor_, 192 summary)); 193 194 ReportRequestStats(REQUEST_STATS_TOTAL_PROCESSED_RESPONSES); 195 if (request_info && 196 request_info->GetResourceType() == ResourceType::MAIN_FRAME) { 197 ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_PROCESSED_RESPONSES); 198 } 199 } 200 201 } // namespace chrome_browser_net 202