11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved.
21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be
31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file.
41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/net/resource_prefetch_predictor_observer.h"
61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <string>
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/metrics/histogram.h"
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/browser/browser_thread.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/browser/render_frame_host.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/browser/resource_request_info.h"
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/url_request/url_request.h"
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "url/gurl.h"
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing content::BrowserThread;
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing predictors::ResourcePrefetchPredictor;
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace {
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Enum for measuring statistics pertaining to observed request, responses and
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// redirects.
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccienum RequestStats {
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  REQUEST_STATS_TOTAL_RESPONSES = 0,
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  REQUEST_STATS_TOTAL_PROCESSED_RESPONSES = 1,
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  REQUEST_STATS_NO_RESOURCE_REQUEST_INFO = 2,
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  REQUEST_STATS_NO_RENDER_FRAME_ID_FROM_REQUEST_INFO = 3,
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  REQUEST_STATS_MAX = 4,
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Specific to main frame requests.
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccienum MainFrameRequestStats {
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MAIN_FRAME_REQUEST_STATS_TOTAL_REQUESTS = 0,
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MAIN_FRAME_REQUEST_STATS_PROCESSED_REQUESTS = 1,
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MAIN_FRAME_REQUEST_STATS_TOTAL_REDIRECTS = 2,
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MAIN_FRAME_REQUEST_STATS_PROCESSED_REDIRECTS = 3,
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MAIN_FRAME_REQUEST_STATS_TOTAL_RESPONSES = 4,
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MAIN_FRAME_REQUEST_STATS_PROCESSED_RESPONSES = 5,
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MAIN_FRAME_REQUEST_STATS_MAX = 6,
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ReportRequestStats(RequestStats stat) {
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.RequestStats",
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            stat,
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            REQUEST_STATS_MAX);
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ReportMainFrameRequestStats(MainFrameRequestStats stat) {
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.MainFrameRequestStats",
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            stat,
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            MAIN_FRAME_REQUEST_STATS_MAX);
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool SummarizeResponse(net::URLRequest* request,
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       ResourcePrefetchPredictor::URLRequestSummary* summary) {
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const content::ResourceRequestInfo* info =
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      content::ResourceRequestInfo::ForRequest(request);
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!info) {
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ReportRequestStats(REQUEST_STATS_NO_RESOURCE_REQUEST_INFO);
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int render_process_id, render_frame_id;
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_id)) {
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ReportRequestStats(REQUEST_STATS_NO_RENDER_FRAME_ID_FROM_REQUEST_INFO);
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  summary->navigation_id.render_process_id = render_process_id;
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  summary->navigation_id.render_frame_id = render_frame_id;
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  summary->navigation_id.main_frame_url = request->first_party_for_cookies();
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  summary->navigation_id.creation_time = request->creation_time();
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  summary->resource_url = request->original_url();
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  summary->resource_type = info->GetResourceType();
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  request->GetMimeType(&summary->mime_type);
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  summary->was_cached = request->was_cached();
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Use the mime_type to determine the resource type for subresources since
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // types such as PREFETCH, SUB_RESOURCE, etc are not useful.
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (summary->resource_type != content::RESOURCE_TYPE_MAIN_FRAME) {
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    summary->resource_type =
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        ResourcePrefetchPredictor::GetResourceTypeFromMimeType(
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            summary->mime_type,
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            summary->resource_type);
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return true;
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace chrome_browser_net {
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciResourcePrefetchPredictorObserver::ResourcePrefetchPredictorObserver(
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ResourcePrefetchPredictor* predictor)
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : predictor_(predictor->AsWeakPtr()) {
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_CURRENTLY_ON(BrowserThread::UI);
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciResourcePrefetchPredictorObserver::~ResourcePrefetchPredictorObserver() {
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        BrowserThread::CurrentlyOn(BrowserThread::IO));
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ResourcePrefetchPredictorObserver::OnRequestStarted(
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    net::URLRequest* request,
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    content::ResourceType resource_type,
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int child_id,
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int frame_id) {
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_CURRENTLY_ON(BrowserThread::IO);
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (resource_type == content::RESOURCE_TYPE_MAIN_FRAME)
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_TOTAL_REQUESTS);
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!ResourcePrefetchPredictor::ShouldRecordRequest(request, resource_type))
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ResourcePrefetchPredictor::URLRequestSummary summary;
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  summary.navigation_id.render_process_id = child_id;
1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  summary.navigation_id.render_frame_id = frame_id;
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  summary.navigation_id.main_frame_url = request->first_party_for_cookies();
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  summary.resource_url = request->original_url();
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  summary.resource_type = resource_type;
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  BrowserThread::PostTask(
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      BrowserThread::UI,
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      FROM_HERE,
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&ResourcePrefetchPredictor::RecordURLRequest,
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 predictor_,
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 summary));
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (resource_type == content::RESOURCE_TYPE_MAIN_FRAME)
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_PROCESSED_REQUESTS);
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ResourcePrefetchPredictorObserver::OnRequestRedirected(
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const GURL& redirect_url,
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    net::URLRequest* request) {
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_CURRENTLY_ON(BrowserThread::IO);
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const content::ResourceRequestInfo* request_info =
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      content::ResourceRequestInfo::ForRequest(request);
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (request_info &&
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      request_info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME) {
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_TOTAL_REDIRECTS);
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!ResourcePrefetchPredictor::ShouldRecordRedirect(request))
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ResourcePrefetchPredictor::URLRequestSummary summary;
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!SummarizeResponse(request, &summary))
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  summary.redirect_url = redirect_url;
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  BrowserThread::PostTask(
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      BrowserThread::UI,
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      FROM_HERE,
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&ResourcePrefetchPredictor::RecordURLRedirect,
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 predictor_,
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 summary));
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (request_info &&
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      request_info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME) {
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_PROCESSED_REDIRECTS);
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ResourcePrefetchPredictorObserver::OnResponseStarted(
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    net::URLRequest* request) {
1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_CURRENTLY_ON(BrowserThread::IO);
1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ReportRequestStats(REQUEST_STATS_TOTAL_RESPONSES);
1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const content::ResourceRequestInfo* request_info =
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      content::ResourceRequestInfo::ForRequest(request);
1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (request_info &&
1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      request_info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME) {
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_TOTAL_RESPONSES);
1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!ResourcePrefetchPredictor::ShouldRecordResponse(request))
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ResourcePrefetchPredictor::URLRequestSummary summary;
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!SummarizeResponse(request, &summary))
1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  BrowserThread::PostTask(
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      BrowserThread::UI,
1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      FROM_HERE,
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&ResourcePrefetchPredictor::RecordURLResponse,
1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 predictor_,
1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 summary));
1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ReportRequestStats(REQUEST_STATS_TOTAL_PROCESSED_RESPONSES);
1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (request_info &&
1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      request_info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME) {
1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_PROCESSED_RESPONSES);
1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace chrome_browser_net
203