Home | History | Annotate | Download | only in net
      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