| 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 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 376 observer_(nullptr), | 376 observer_(nullptr), |
| 377 config_(config), | 377 config_(config), |
| 378 initialization_state_(NOT_INITIALIZED), | 378 initialization_state_(NOT_INITIALIZED), |
| 379 tables_(PredictorDatabaseFactory::GetForProfile(profile) | 379 tables_(PredictorDatabaseFactory::GetForProfile(profile) |
| 380 ->resource_prefetch_tables()), | 380 ->resource_prefetch_tables()), |
| 381 history_service_observer_(this) { | 381 history_service_observer_(this) { |
| 382 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 382 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 383 | 383 |
| 384 // Some form of learning has to be enabled. | 384 // Some form of learning has to be enabled. |
| 385 DCHECK(config_.IsLearningEnabled()); | 385 DCHECK(config_.IsLearningEnabled()); |
| 386 if (config_.IsURLPrefetchingEnabled(profile_)) | |
| 387 DCHECK(config_.IsURLLearningEnabled()); | |
| 388 if (config_.IsHostPrefetchingEnabled(profile_)) | |
| 389 DCHECK(config_.IsHostLearningEnabled()); | |
| 390 } | 386 } |
| 391 | 387 |
| 392 ResourcePrefetchPredictor::~ResourcePrefetchPredictor() {} | 388 ResourcePrefetchPredictor::~ResourcePrefetchPredictor() {} |
| 393 | 389 |
| 394 void ResourcePrefetchPredictor::StartInitialization() { | 390 void ResourcePrefetchPredictor::StartInitialization() { |
| 395 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 391 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 396 TRACE_EVENT0("browser", "ResourcePrefetchPredictor::StartInitialization"); | 392 TRACE_EVENT0("browser", "ResourcePrefetchPredictor::StartInitialization"); |
| 397 | 393 |
| 398 if (initialization_state_ != NOT_INITIALIZED) | 394 if (initialization_state_ != NOT_INITIALIZED) |
| 399 return; | 395 return; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 // corresponding to the navigation has not been created yet. | 464 // corresponding to the navigation has not been created yet. |
| 469 if (!navigation_id.main_frame_url.is_empty()) | 465 if (!navigation_id.main_frame_url.is_empty()) |
| 470 OnNavigationComplete(navigation_id); | 466 OnNavigationComplete(navigation_id); |
| 471 break; | 467 break; |
| 472 default: | 468 default: |
| 473 NOTREACHED() << "Unexpected initialization_state_: " | 469 NOTREACHED() << "Unexpected initialization_state_: " |
| 474 << initialization_state_; | 470 << initialization_state_; |
| 475 } | 471 } |
| 476 } | 472 } |
| 477 | 473 |
| 478 void ResourcePrefetchPredictor::StartPrefetching(const GURL& url) { | 474 void ResourcePrefetchPredictor::StartPrefetching( |
| 475 const GURL& url, |
| 476 ResourcePrefetchPredictorConfig::Origin origin) { |
| 479 TRACE_EVENT1("browser", "ResourcePrefetchPredictor::StartPrefetching", "url", | 477 TRACE_EVENT1("browser", "ResourcePrefetchPredictor::StartPrefetching", "url", |
| 480 url.spec()); | 478 url.spec()); |
| 481 if (!prefetch_manager_.get()) // Prefetching not enabled. | 479 if (!prefetch_manager_.get()) // Prefetching not enabled. |
| 482 return; | 480 return; |
| 481 if (!config_.IsPrefetchingEnabled(profile_, origin)) |
| 482 return; |
| 483 | 483 |
| 484 std::vector<GURL> subresource_urls; | 484 std::vector<GURL> subresource_urls; |
| 485 if (!GetPrefetchData(url, &subresource_urls)) { | 485 if (!GetPrefetchData(url, &subresource_urls)) |
| 486 // No prefetching data at host or URL level. | |
| 487 return; | 486 return; |
| 488 } | |
| 489 | 487 |
| 490 BrowserThread::PostTask( | 488 BrowserThread::PostTask( |
| 491 BrowserThread::IO, FROM_HERE, | 489 BrowserThread::IO, FROM_HERE, |
| 492 base::Bind(&ResourcePrefetcherManager::MaybeAddPrefetch, | 490 base::Bind(&ResourcePrefetcherManager::MaybeAddPrefetch, |
| 493 prefetch_manager_, url, subresource_urls)); | 491 prefetch_manager_, url, subresource_urls)); |
| 494 } | 492 } |
| 495 | 493 |
| 496 void ResourcePrefetchPredictor::StopPrefetching(const GURL& url) { | 494 void ResourcePrefetchPredictor::StopPrefetching(const GURL& url) { |
| 497 TRACE_EVENT1("browser", "ResourcePrefetchPredictor::StopPrefetching", "url", | 495 TRACE_EVENT1("browser", "ResourcePrefetchPredictor::StopPrefetching", "url", |
| 498 url.spec()); | 496 url.spec()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 516 } | 514 } |
| 517 history_service_observer_.RemoveAll(); | 515 history_service_observer_.RemoveAll(); |
| 518 } | 516 } |
| 519 | 517 |
| 520 void ResourcePrefetchPredictor::OnMainFrameRequest( | 518 void ResourcePrefetchPredictor::OnMainFrameRequest( |
| 521 const URLRequestSummary& request) { | 519 const URLRequestSummary& request) { |
| 522 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 520 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 523 DCHECK_EQ(INITIALIZED, initialization_state_); | 521 DCHECK_EQ(INITIALIZED, initialization_state_); |
| 524 | 522 |
| 525 const GURL& main_frame_url = request.navigation_id.main_frame_url; | 523 const GURL& main_frame_url = request.navigation_id.main_frame_url; |
| 526 StartPrefetching(main_frame_url); | 524 StartPrefetching(main_frame_url, |
| 525 ResourcePrefetchPredictorConfig::ORIGIN_NAVIGATION); |
| 527 | 526 |
| 528 // Cleanup older navigations. | 527 // Cleanup older navigations. |
| 529 CleanupAbandonedNavigations(request.navigation_id); | 528 CleanupAbandonedNavigations(request.navigation_id); |
| 530 | 529 |
| 531 // New empty navigation entry. | 530 // New empty navigation entry. |
| 532 inflight_navigations_.insert( | 531 inflight_navigations_.insert( |
| 533 std::make_pair(request.navigation_id, | 532 std::make_pair(request.navigation_id, |
| 534 base::MakeUnique<PageRequestSummary>(main_frame_url))); | 533 base::MakeUnique<PageRequestSummary>(main_frame_url))); |
| 535 } | 534 } |
| 536 | 535 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 610 std::move(summary), | 609 std::move(summary), |
| 611 base::Bind(&ResourcePrefetchPredictor::OnVisitCountLookup, | 610 base::Bind(&ResourcePrefetchPredictor::OnVisitCountLookup, |
| 612 AsWeakPtr()))), | 611 AsWeakPtr()))), |
| 613 &history_lookup_consumer_); | 612 &history_lookup_consumer_); |
| 614 } | 613 } |
| 615 | 614 |
| 616 bool ResourcePrefetchPredictor::GetPrefetchData(const GURL& main_frame_url, | 615 bool ResourcePrefetchPredictor::GetPrefetchData(const GURL& main_frame_url, |
| 617 std::vector<GURL>* urls) { | 616 std::vector<GURL>* urls) { |
| 618 DCHECK(urls); | 617 DCHECK(urls); |
| 619 DCHECK(urls->empty()); | 618 DCHECK(urls->empty()); |
| 620 bool use_url_data = config_.IsPrefetchingEnabled(profile_) ? | |
| 621 config_.IsURLPrefetchingEnabled(profile_) : | |
| 622 config_.IsURLLearningEnabled(); | |
| 623 bool use_host_data = config_.IsPrefetchingEnabled(profile_) ? | |
| 624 config_.IsHostPrefetchingEnabled(profile_) : | |
| 625 config_.IsHostLearningEnabled(); | |
| 626 | 619 |
| 627 // Fetch URLs based on a redirect endpoint for URL/host first. | 620 // Fetch URLs based on a redirect endpoint for URL/host first. |
| 628 std::string redirect_endpoint; | 621 std::string redirect_endpoint; |
| 629 if (use_url_data && | 622 if (GetRedirectEndpoint(main_frame_url.spec(), *url_redirect_table_cache_, |
| 630 GetRedirectEndpoint(main_frame_url.spec(), *url_redirect_table_cache_, | |
| 631 &redirect_endpoint) && | 623 &redirect_endpoint) && |
| 632 PopulatePrefetcherRequest(redirect_endpoint, *url_table_cache_, urls)) { | 624 PopulatePrefetcherRequest(redirect_endpoint, *url_table_cache_, urls)) { |
| 633 return true; | 625 return true; |
| 634 } | 626 } |
| 635 | 627 |
| 636 if (use_host_data && | 628 if (GetRedirectEndpoint(main_frame_url.host(), *host_redirect_table_cache_, |
| 637 GetRedirectEndpoint(main_frame_url.host(), *host_redirect_table_cache_, | |
| 638 &redirect_endpoint) && | 629 &redirect_endpoint) && |
| 639 PopulatePrefetcherRequest(redirect_endpoint, *host_table_cache_, urls)) { | 630 PopulatePrefetcherRequest(redirect_endpoint, *host_table_cache_, urls)) { |
| 640 return true; | 631 return true; |
| 641 } | 632 } |
| 642 | 633 |
| 643 // Fallback to fetching URLs based on the incoming URL/host. | 634 // Fallback to fetching URLs based on the incoming URL/host. |
| 644 if (use_url_data && PopulatePrefetcherRequest(main_frame_url.spec(), | 635 if (PopulatePrefetcherRequest(main_frame_url.spec(), *url_table_cache_, |
| 645 *url_table_cache_, urls)) { | 636 urls)) { |
| 646 return true; | 637 return true; |
| 647 } | 638 } |
| 648 | 639 |
| 649 return use_host_data && PopulatePrefetcherRequest(main_frame_url.host(), | 640 return PopulatePrefetcherRequest(main_frame_url.host(), *host_table_cache_, |
| 650 *host_table_cache_, urls); | 641 urls); |
| 651 } | 642 } |
| 652 | 643 |
| 653 bool ResourcePrefetchPredictor::PopulatePrefetcherRequest( | 644 bool ResourcePrefetchPredictor::PopulatePrefetcherRequest( |
| 654 const std::string& main_frame_key, | 645 const std::string& main_frame_key, |
| 655 const PrefetchDataMap& data_map, | 646 const PrefetchDataMap& data_map, |
| 656 std::vector<GURL>* urls) { | 647 std::vector<GURL>* urls) { |
| 657 DCHECK(urls); | 648 DCHECK(urls); |
| 658 PrefetchDataMap::const_iterator it = data_map.find(main_frame_key); | 649 PrefetchDataMap::const_iterator it = data_map.find(main_frame_key); |
| 659 if (it == data_map.end()) | 650 if (it == data_map.end()) |
| 660 return false; | 651 return false; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 700 host_table_cache_->size()); | 691 host_table_cache_->size()); |
| 701 | 692 |
| 702 ConnectToHistoryService(); | 693 ConnectToHistoryService(); |
| 703 } | 694 } |
| 704 | 695 |
| 705 void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() { | 696 void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() { |
| 706 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 697 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 707 DCHECK_EQ(INITIALIZING, initialization_state_); | 698 DCHECK_EQ(INITIALIZING, initialization_state_); |
| 708 | 699 |
| 709 // Initialize the prefetch manager only if prefetching is enabled. | 700 // Initialize the prefetch manager only if prefetching is enabled. |
| 710 if (config_.IsPrefetchingEnabled(profile_)) { | 701 if (config_.IsAnyPrefetchingEnabled(profile_)) { |
| 711 prefetch_manager_ = new ResourcePrefetcherManager( | 702 prefetch_manager_ = new ResourcePrefetcherManager( |
| 712 this, config_, profile_->GetRequestContext()); | 703 this, config_, profile_->GetRequestContext()); |
| 713 } | 704 } |
| 714 initialization_state_ = INITIALIZED; | 705 initialization_state_ = INITIALIZED; |
| 715 | 706 |
| 716 if (observer_) | 707 if (observer_) |
| 717 observer_->OnPredictorInitialized(); | 708 observer_->OnPredictorInitialized(); |
| 718 } | 709 } |
| 719 | 710 |
| 720 void ResourcePrefetchPredictor::CleanupAbandonedNavigations( | 711 void ResourcePrefetchPredictor::CleanupAbandonedNavigations( |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 851 // TODO(alexilin): make only one request to DB thread. | 842 // TODO(alexilin): make only one request to DB thread. |
| 852 | 843 |
| 853 // URL level data - merge only if we already saved the data, or it | 844 // URL level data - merge only if we already saved the data, or it |
| 854 // meets the cutoff requirement. | 845 // meets the cutoff requirement. |
| 855 const std::string url_spec = summary.main_frame_url.spec(); | 846 const std::string url_spec = summary.main_frame_url.spec(); |
| 856 bool already_tracking = url_table_cache_->find(url_spec) != | 847 bool already_tracking = url_table_cache_->find(url_spec) != |
| 857 url_table_cache_->end(); | 848 url_table_cache_->end(); |
| 858 bool should_track_url = | 849 bool should_track_url = |
| 859 already_tracking || (url_visit_count >= config_.min_url_visit_count); | 850 already_tracking || (url_visit_count >= config_.min_url_visit_count); |
| 860 | 851 |
| 861 if (should_track_url && config_.IsURLLearningEnabled()) { | 852 if (should_track_url) { |
| 862 LearnNavigation(url_spec, PREFETCH_KEY_TYPE_URL, | 853 LearnNavigation(url_spec, PREFETCH_KEY_TYPE_URL, |
| 863 summary.subresource_requests, config_.max_urls_to_track, | 854 summary.subresource_requests, config_.max_urls_to_track, |
| 864 url_table_cache_.get(), summary.initial_url.spec(), | 855 url_table_cache_.get(), summary.initial_url.spec(), |
| 865 url_redirect_table_cache_.get()); | 856 url_redirect_table_cache_.get()); |
| 866 } | 857 } |
| 867 | 858 |
| 868 // Host level data - no cutoff, always learn the navigation if enabled. | 859 // Host level data - no cutoff, always learn the navigation if enabled. |
| 869 if (config_.IsHostLearningEnabled()) { | 860 const std::string host = summary.main_frame_url.host(); |
| 870 const std::string host = summary.main_frame_url.host(); | 861 LearnNavigation(host, PREFETCH_KEY_TYPE_HOST, summary.subresource_requests, |
| 871 LearnNavigation(host, PREFETCH_KEY_TYPE_HOST, summary.subresource_requests, | 862 config_.max_hosts_to_track, host_table_cache_.get(), |
| 872 config_.max_hosts_to_track, host_table_cache_.get(), | 863 summary.initial_url.host(), host_redirect_table_cache_.get()); |
| 873 summary.initial_url.host(), | |
| 874 host_redirect_table_cache_.get()); | |
| 875 } | |
| 876 | 864 |
| 877 if (observer_) | 865 if (observer_) |
| 878 observer_->OnNavigationLearned(url_visit_count, summary); | 866 observer_->OnNavigationLearned(url_visit_count, summary); |
| 879 } | 867 } |
| 880 | 868 |
| 881 void ResourcePrefetchPredictor::LearnNavigation( | 869 void ResourcePrefetchPredictor::LearnNavigation( |
| 882 const std::string& key, | 870 const std::string& key, |
| 883 PrefetchKeyType key_type, | 871 PrefetchKeyType key_type, |
| 884 const std::vector<URLRequestSummary>& new_resources, | 872 const std::vector<URLRequestSummary>& new_resources, |
| 885 size_t max_data_map_size, | 873 size_t max_data_map_size, |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1170 TestObserver::~TestObserver() { | 1158 TestObserver::~TestObserver() { |
| 1171 predictor_->SetObserverForTesting(nullptr); | 1159 predictor_->SetObserverForTesting(nullptr); |
| 1172 } | 1160 } |
| 1173 | 1161 |
| 1174 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) | 1162 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) |
| 1175 : predictor_(predictor) { | 1163 : predictor_(predictor) { |
| 1176 predictor_->SetObserverForTesting(this); | 1164 predictor_->SetObserverForTesting(this); |
| 1177 } | 1165 } |
| 1178 | 1166 |
| 1179 } // namespace predictors | 1167 } // namespace predictors |
| OLD | NEW |