OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/predictors/resource_prefetch_predictor.h" | 5 #include "chrome/browser/predictors/resource_prefetch_predictor.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <set> | 8 #include <set> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
462 first_occurrence(0) {} | 462 first_occurrence(0) {} |
463 | 463 |
464 ResourcePrefetchPredictor::OriginRequestSummary::OriginRequestSummary( | 464 ResourcePrefetchPredictor::OriginRequestSummary::OriginRequestSummary( |
465 const OriginRequestSummary& other) = default; | 465 const OriginRequestSummary& other) = default; |
466 | 466 |
467 ResourcePrefetchPredictor::OriginRequestSummary::~OriginRequestSummary() {} | 467 ResourcePrefetchPredictor::OriginRequestSummary::~OriginRequestSummary() {} |
468 | 468 |
469 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary() | 469 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary() |
470 : resource_type(content::RESOURCE_TYPE_LAST_TYPE), | 470 : resource_type(content::RESOURCE_TYPE_LAST_TYPE), |
471 priority(net::IDLE), | 471 priority(net::IDLE), |
472 response_time(base::TimeTicks()), | |
473 before_first_contentful_paint(false), | |
472 was_cached(false), | 474 was_cached(false), |
473 has_validators(false), | 475 has_validators(false), |
474 always_revalidate(false), | 476 always_revalidate(false), |
475 is_no_store(false), | 477 is_no_store(false), |
476 network_accessed(false) {} | 478 network_accessed(false) {} |
477 | 479 |
478 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary( | 480 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary( |
479 const URLRequestSummary& other) = default; | 481 const URLRequestSummary& other) = default; |
480 | 482 |
481 ResourcePrefetchPredictor::URLRequestSummary::~URLRequestSummary() { | 483 ResourcePrefetchPredictor::URLRequestSummary::~URLRequestSummary() { |
482 } | 484 } |
483 | 485 |
484 // static | 486 // static |
485 bool ResourcePrefetchPredictor::URLRequestSummary::SummarizeResponse( | 487 bool ResourcePrefetchPredictor::URLRequestSummary::SummarizeResponse( |
486 const net::URLRequest& request, | 488 const net::URLRequest& request, |
487 URLRequestSummary* summary) { | 489 URLRequestSummary* summary) { |
488 const content::ResourceRequestInfo* request_info = | 490 const content::ResourceRequestInfo* request_info = |
489 content::ResourceRequestInfo::ForRequest(&request); | 491 content::ResourceRequestInfo::ForRequest(&request); |
490 if (!request_info) | 492 if (!request_info) |
491 return false; | 493 return false; |
492 | 494 |
495 summary->response_time = base::TimeTicks::Now(); | |
493 summary->resource_url = request.original_url(); | 496 summary->resource_url = request.original_url(); |
494 summary->request_url = request.url(); | 497 summary->request_url = request.url(); |
495 content::ResourceType resource_type_from_request = | 498 content::ResourceType resource_type_from_request = |
496 request_info->GetResourceType(); | 499 request_info->GetResourceType(); |
497 summary->priority = request.priority(); | 500 summary->priority = request.priority(); |
498 request.GetMimeType(&summary->mime_type); | 501 request.GetMimeType(&summary->mime_type); |
499 summary->was_cached = request.was_cached(); | 502 summary->was_cached = request.was_cached(); |
500 summary->resource_type = | 503 summary->resource_type = |
501 GetResourceType(resource_type_from_request, summary->mime_type); | 504 GetResourceType(resource_type_from_request, summary->mime_type); |
502 | 505 |
503 scoped_refptr<net::HttpResponseHeaders> headers = | 506 scoped_refptr<net::HttpResponseHeaders> headers = |
504 request.response_info().headers; | 507 request.response_info().headers; |
505 if (headers.get()) { | 508 if (headers.get()) { |
506 summary->has_validators = headers->HasValidators(); | 509 summary->has_validators = headers->HasValidators(); |
507 // RFC 2616, section 14.9. | 510 // RFC 2616, section 14.9. |
508 summary->always_revalidate = | 511 summary->always_revalidate = |
509 headers->HasHeaderValue("cache-control", "no-cache") || | 512 headers->HasHeaderValue("cache-control", "no-cache") || |
510 headers->HasHeaderValue("pragma", "no-cache") || | 513 headers->HasHeaderValue("pragma", "no-cache") || |
511 headers->HasHeaderValue("vary", "*"); | 514 headers->HasHeaderValue("vary", "*"); |
512 summary->is_no_store = IsNoStore(request); | 515 summary->is_no_store = IsNoStore(request); |
513 } | 516 } |
514 summary->network_accessed = request.response_info().network_accessed; | 517 summary->network_accessed = request.response_info().network_accessed; |
515 return true; | 518 return true; |
516 } | 519 } |
517 | 520 |
518 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary( | 521 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary( |
519 const GURL& i_main_frame_url) | 522 const GURL& i_main_frame_url) |
520 : main_frame_url(i_main_frame_url), initial_url(i_main_frame_url) {} | 523 : main_frame_url(i_main_frame_url), |
524 initial_url(i_main_frame_url), | |
525 first_contentful_paint(base::TimeTicks::Max()) {} | |
521 | 526 |
522 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary( | 527 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary( |
523 const PageRequestSummary& other) = default; | 528 const PageRequestSummary& other) = default; |
524 | 529 |
525 ResourcePrefetchPredictor::PageRequestSummary::~PageRequestSummary() {} | 530 ResourcePrefetchPredictor::PageRequestSummary::~PageRequestSummary() {} |
526 | 531 |
527 ResourcePrefetchPredictor::Prediction::Prediction() = default; | 532 ResourcePrefetchPredictor::Prediction::Prediction() = default; |
528 | 533 |
529 ResourcePrefetchPredictor::Prediction::Prediction( | 534 ResourcePrefetchPredictor::Prediction::Prediction( |
530 const ResourcePrefetchPredictor::Prediction& other) = default; | 535 const ResourcePrefetchPredictor::Prediction& other) = default; |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
638 // corresponding to the navigation has not been created yet. | 643 // corresponding to the navigation has not been created yet. |
639 if (!navigation_id.main_frame_url.is_empty()) | 644 if (!navigation_id.main_frame_url.is_empty()) |
640 OnNavigationComplete(navigation_id); | 645 OnNavigationComplete(navigation_id); |
641 break; | 646 break; |
642 default: | 647 default: |
643 NOTREACHED() << "Unexpected initialization_state_: " | 648 NOTREACHED() << "Unexpected initialization_state_: " |
644 << initialization_state_; | 649 << initialization_state_; |
645 } | 650 } |
646 } | 651 } |
647 | 652 |
653 void ResourcePrefetchPredictor::RecordFirstContentfulPaint( | |
654 const NavigationID& navigation_id, | |
655 const base::TimeTicks& first_contentful_paint) { | |
656 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
657 if (initialization_state_ != INITIALIZED) | |
658 return; | |
659 | |
660 NavigationMap::iterator nav_it = inflight_navigations_.find(navigation_id); | |
661 if (nav_it != inflight_navigations_.end()) | |
662 nav_it->second->first_contentful_paint = first_contentful_paint; | |
663 } | |
664 | |
648 void ResourcePrefetchPredictor::StartPrefetching(const GURL& url, | 665 void ResourcePrefetchPredictor::StartPrefetching(const GURL& url, |
649 PrefetchOrigin origin) { | 666 PrefetchOrigin origin) { |
650 TRACE_EVENT1("browser", "ResourcePrefetchPredictor::StartPrefetching", "url", | 667 TRACE_EVENT1("browser", "ResourcePrefetchPredictor::StartPrefetching", "url", |
651 url.spec()); | 668 url.spec()); |
652 // Save prefetch start time to report prefetching duration. | 669 // Save prefetch start time to report prefetching duration. |
653 if (inflight_prefetches_.find(url) == inflight_prefetches_.end() && | 670 if (inflight_prefetches_.find(url) == inflight_prefetches_.end() && |
654 IsUrlPrefetchable(url)) { | 671 IsUrlPrefetchable(url)) { |
655 inflight_prefetches_.insert(std::make_pair(url, base::TimeTicks::Now())); | 672 inflight_prefetches_.insert(std::make_pair(url, base::TimeTicks::Now())); |
656 } | 673 } |
657 | 674 |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
837 | 854 |
838 NavigationMap::iterator nav_it = | 855 NavigationMap::iterator nav_it = |
839 inflight_navigations_.find(nav_id_without_timing_info); | 856 inflight_navigations_.find(nav_id_without_timing_info); |
840 if (nav_it == inflight_navigations_.end()) | 857 if (nav_it == inflight_navigations_.end()) |
841 return; | 858 return; |
842 | 859 |
843 // Remove the navigation from the inflight navigations. | 860 // Remove the navigation from the inflight navigations. |
844 std::unique_ptr<PageRequestSummary> summary = std::move(nav_it->second); | 861 std::unique_ptr<PageRequestSummary> summary = std::move(nav_it->second); |
845 inflight_navigations_.erase(nav_it); | 862 inflight_navigations_.erase(nav_it); |
846 | 863 |
864 // Set before_first_contentful paint for each resource. | |
Benoit L
2017/04/25 15:30:36
If I understand the code correctly, this will slig
trevordixon
2017/04/25 20:23:55
OK, documented above where response_time is record
| |
865 for (auto& request_summary : summary->subresource_requests) { | |
866 request_summary.before_first_contentful_paint = | |
867 request_summary.response_time < summary->first_contentful_paint; | |
868 } | |
869 | |
847 const GURL& initial_url = summary->initial_url; | 870 const GURL& initial_url = summary->initial_url; |
848 ResourcePrefetchPredictor::Prediction prediction; | 871 ResourcePrefetchPredictor::Prediction prediction; |
849 bool has_data = GetPrefetchData(initial_url, &prediction); | 872 bool has_data = GetPrefetchData(initial_url, &prediction); |
850 if (has_data) | 873 if (has_data) |
851 ReportPredictionAccuracy(prediction, *summary); | 874 ReportPredictionAccuracy(prediction, *summary); |
852 | 875 |
853 auto it = prefetcher_stats_.find(initial_url); | 876 auto it = prefetcher_stats_.find(initial_url); |
854 if (it != prefetcher_stats_.end()) { | 877 if (it != prefetcher_stats_.end()) { |
855 const std::vector<URLRequestSummary>& summaries = | 878 const std::vector<URLRequestSummary>& summaries = |
856 summary->subresource_requests; | 879 summary->subresource_requests; |
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1336 continue; | 1359 continue; |
1337 | 1360 |
1338 ResourceData* resource_to_add = data.add_resources(); | 1361 ResourceData* resource_to_add = data.add_resources(); |
1339 resource_to_add->set_resource_url(summary.resource_url.spec()); | 1362 resource_to_add->set_resource_url(summary.resource_url.spec()); |
1340 resource_to_add->set_resource_type( | 1363 resource_to_add->set_resource_type( |
1341 static_cast<ResourceData::ResourceType>(summary.resource_type)); | 1364 static_cast<ResourceData::ResourceType>(summary.resource_type)); |
1342 resource_to_add->set_number_of_hits(1); | 1365 resource_to_add->set_number_of_hits(1); |
1343 resource_to_add->set_average_position(i + 1); | 1366 resource_to_add->set_average_position(i + 1); |
1344 resource_to_add->set_priority( | 1367 resource_to_add->set_priority( |
1345 static_cast<ResourceData::Priority>(summary.priority)); | 1368 static_cast<ResourceData::Priority>(summary.priority)); |
1369 resource_to_add->set_before_first_contentful_paint( | |
1370 summary.before_first_contentful_paint); | |
1346 resource_to_add->set_has_validators(summary.has_validators); | 1371 resource_to_add->set_has_validators(summary.has_validators); |
1347 resource_to_add->set_always_revalidate(summary.always_revalidate); | 1372 resource_to_add->set_always_revalidate(summary.always_revalidate); |
1348 | 1373 |
1349 resources_seen.insert(summary.resource_url); | 1374 resources_seen.insert(summary.resource_url); |
1350 } | 1375 } |
1351 } else { | 1376 } else { |
1352 PrefetchData& data = cache_entry->second; | 1377 PrefetchData& data = cache_entry->second; |
1353 data.set_last_visit_time(base::Time::Now().ToInternalValue()); | 1378 data.set_last_visit_time(base::Time::Now().ToInternalValue()); |
1354 | 1379 |
1355 // Build indices over the data. | 1380 // Build indices over the data. |
(...skipping 29 matching lines...) Expand all Loading... | |
1385 | 1410 |
1386 // Update the resource type since it could have changed. | 1411 // Update the resource type since it could have changed. |
1387 if (new_summary.resource_type != content::RESOURCE_TYPE_LAST_TYPE) { | 1412 if (new_summary.resource_type != content::RESOURCE_TYPE_LAST_TYPE) { |
1388 old_resource->set_resource_type( | 1413 old_resource->set_resource_type( |
1389 static_cast<ResourceData::ResourceType>( | 1414 static_cast<ResourceData::ResourceType>( |
1390 new_summary.resource_type)); | 1415 new_summary.resource_type)); |
1391 } | 1416 } |
1392 | 1417 |
1393 old_resource->set_priority( | 1418 old_resource->set_priority( |
1394 static_cast<ResourceData::Priority>(new_summary.priority)); | 1419 static_cast<ResourceData::Priority>(new_summary.priority)); |
1420 old_resource->set_before_first_contentful_paint( | |
1421 new_summary.before_first_contentful_paint); | |
1395 | 1422 |
1396 int position = new_index[resource_url] + 1; | 1423 int position = new_index[resource_url] + 1; |
1397 int total = | 1424 int total = |
1398 old_resource->number_of_hits() + old_resource->number_of_misses(); | 1425 old_resource->number_of_hits() + old_resource->number_of_misses(); |
1399 old_resource->set_average_position( | 1426 old_resource->set_average_position( |
1400 ((old_resource->average_position() * total) + position) / | 1427 ((old_resource->average_position() * total) + position) / |
1401 (total + 1)); | 1428 (total + 1)); |
1402 old_resource->set_number_of_hits(old_resource->number_of_hits() + 1); | 1429 old_resource->set_number_of_hits(old_resource->number_of_hits() + 1); |
1403 old_resource->set_consecutive_misses(0); | 1430 old_resource->set_consecutive_misses(0); |
1404 } | 1431 } |
1405 } | 1432 } |
1406 | 1433 |
1407 // Add the new ones that we have not seen before. | 1434 // Add the new ones that we have not seen before. |
1408 for (int i = 0; i < new_resources_size; ++i) { | 1435 for (int i = 0; i < new_resources_size; ++i) { |
1409 const URLRequestSummary& summary = new_resources[i]; | 1436 const URLRequestSummary& summary = new_resources[i]; |
1410 if (old_index.find(summary.resource_url) != old_index.end()) | 1437 if (old_index.find(summary.resource_url) != old_index.end()) |
1411 continue; | 1438 continue; |
1412 | 1439 |
1413 // Only need to add new stuff. | 1440 // Only need to add new stuff. |
1414 ResourceData* resource_to_add = data.add_resources(); | 1441 ResourceData* resource_to_add = data.add_resources(); |
1415 resource_to_add->set_resource_url(summary.resource_url.spec()); | 1442 resource_to_add->set_resource_url(summary.resource_url.spec()); |
1416 resource_to_add->set_resource_type( | 1443 resource_to_add->set_resource_type( |
1417 static_cast<ResourceData::ResourceType>(summary.resource_type)); | 1444 static_cast<ResourceData::ResourceType>(summary.resource_type)); |
1418 resource_to_add->set_number_of_hits(1); | 1445 resource_to_add->set_number_of_hits(1); |
1419 resource_to_add->set_average_position(i + 1); | 1446 resource_to_add->set_average_position(i + 1); |
1420 resource_to_add->set_priority( | 1447 resource_to_add->set_priority( |
1421 static_cast<ResourceData::Priority>(summary.priority)); | 1448 static_cast<ResourceData::Priority>(summary.priority)); |
1449 resource_to_add->set_before_first_contentful_paint( | |
1450 summary.before_first_contentful_paint); | |
1422 resource_to_add->set_has_validators(new_resources[i].has_validators); | 1451 resource_to_add->set_has_validators(new_resources[i].has_validators); |
1423 resource_to_add->set_always_revalidate( | 1452 resource_to_add->set_always_revalidate( |
1424 new_resources[i].always_revalidate); | 1453 new_resources[i].always_revalidate); |
1425 | 1454 |
1426 // To ensure we dont add the same url twice. | 1455 // To ensure we dont add the same url twice. |
1427 old_index[summary.resource_url] = 0; | 1456 old_index[summary.resource_url] = 0; |
1428 } | 1457 } |
1429 } | 1458 } |
1430 | 1459 |
1431 PrefetchData& data = cache_entry->second; | 1460 PrefetchData& data = cache_entry->second; |
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1800 TestObserver::~TestObserver() { | 1829 TestObserver::~TestObserver() { |
1801 predictor_->SetObserverForTesting(nullptr); | 1830 predictor_->SetObserverForTesting(nullptr); |
1802 } | 1831 } |
1803 | 1832 |
1804 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) | 1833 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) |
1805 : predictor_(predictor) { | 1834 : predictor_(predictor) { |
1806 predictor_->SetObserverForTesting(this); | 1835 predictor_->SetObserverForTesting(this); |
1807 } | 1836 } |
1808 | 1837 |
1809 } // namespace predictors | 1838 } // namespace predictors |
OLD | NEW |