Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(48)

Side by Side Diff: chrome/browser/predictors/resource_prefetch_predictor.cc

Issue 2355273002: Redirect handling in the resource_prefetch_predictor. (Closed)
Patch Set: Minor changes Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/macros.h" 12 #include "base/macros.h"
13 #include "base/memory/ptr_util.h"
13 #include "base/metrics/histogram_macros.h" 14 #include "base/metrics/histogram_macros.h"
14 #include "base/metrics/sparse_histogram.h" 15 #include "base/metrics/sparse_histogram.h"
15 #include "base/strings/string_number_conversions.h" 16 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/stringprintf.h" 17 #include "base/strings/stringprintf.h"
17 #include "base/time/time.h" 18 #include "base/time/time.h"
18 #include "chrome/browser/history/history_service_factory.h" 19 #include "chrome/browser/history/history_service_factory.h"
19 #include "chrome/browser/predictors/predictor_database.h" 20 #include "chrome/browser/predictors/predictor_database.h"
20 #include "chrome/browser/predictors/predictor_database_factory.h" 21 #include "chrome/browser/predictors/predictor_database_factory.h"
21 #include "chrome/browser/predictors/resource_prefetcher_manager.h" 22 #include "chrome/browser/predictors/resource_prefetcher_manager.h"
22 #include "chrome/browser/profiles/profile.h" 23 #include "chrome/browser/profiles/profile.h"
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 enum ReportingEvent { 59 enum ReportingEvent {
59 REPORTING_EVENT_ALL_HISTORY_CLEARED = 0, 60 REPORTING_EVENT_ALL_HISTORY_CLEARED = 0,
60 REPORTING_EVENT_PARTIAL_HISTORY_CLEARED = 1, 61 REPORTING_EVENT_PARTIAL_HISTORY_CLEARED = 1,
61 REPORTING_EVENT_COUNT = 2 62 REPORTING_EVENT_COUNT = 2
62 }; 63 };
63 64
64 } // namespace 65 } // namespace
65 66
66 namespace predictors { 67 namespace predictors {
67 68
69 const int kMaxRedirectsPerEntry = 20;
70
68 //////////////////////////////////////////////////////////////////////////////// 71 ////////////////////////////////////////////////////////////////////////////////
69 // History lookup task. 72 // History lookup task.
70 73
71 // Used to fetch the visit count for a URL from the History database. 74 // Used to fetch the visit count for a URL from the History database.
72 class GetUrlVisitCountTask : public history::HistoryDBTask { 75 class GetUrlVisitCountTask : public history::HistoryDBTask {
73 public: 76 public:
74 typedef ResourcePrefetchPredictor::URLRequestSummary URLRequestSummary; 77 typedef ResourcePrefetchPredictor::URLRequestSummary URLRequestSummary;
75 typedef base::Callback<void( 78 typedef ResourcePrefetchPredictor::Navigation Navigation;
76 size_t, // Visit count. 79 typedef base::Callback<void(size_t, // Visit count.
77 const NavigationID&, 80 const NavigationID&,
78 const std::vector<URLRequestSummary>&)> VisitInfoCallback; 81 const Navigation&)>
82 VisitInfoCallback;
79 83
80 GetUrlVisitCountTask( 84 GetUrlVisitCountTask(const NavigationID& navigation_id,
81 const NavigationID& navigation_id, 85 std::unique_ptr<Navigation> navigation,
82 std::vector<URLRequestSummary>* requests, 86 VisitInfoCallback callback)
83 VisitInfoCallback callback)
84 : visit_count_(0), 87 : visit_count_(0),
85 navigation_id_(navigation_id), 88 navigation_id_(navigation_id),
86 requests_(requests), 89 navigation_(std::move(navigation)),
87 callback_(callback) { 90 callback_(callback) {
88 DCHECK(requests_.get()); 91 DCHECK(navigation_.get());
89 } 92 }
90 93
91 bool RunOnDBThread(history::HistoryBackend* backend, 94 bool RunOnDBThread(history::HistoryBackend* backend,
92 history::HistoryDatabase* db) override { 95 history::HistoryDatabase* db) override {
93 history::URLRow url_row; 96 history::URLRow url_row;
94 if (db->GetRowForURL(navigation_id_.main_frame_url, &url_row)) 97 if (db->GetRowForURL(navigation_id_.main_frame_url, &url_row))
95 visit_count_ = url_row.visit_count(); 98 visit_count_ = url_row.visit_count();
96 return true; 99 return true;
97 } 100 }
98 101
99 void DoneRunOnMainThread() override { 102 void DoneRunOnMainThread() override {
100 callback_.Run(visit_count_, navigation_id_, *requests_); 103 callback_.Run(visit_count_, navigation_id_, *navigation_);
101 } 104 }
102 105
103 private: 106 private:
104 ~GetUrlVisitCountTask() override {} 107 ~GetUrlVisitCountTask() override {}
105 108
106 int visit_count_; 109 int visit_count_;
107 NavigationID navigation_id_; 110 NavigationID navigation_id_;
108 std::unique_ptr<std::vector<URLRequestSummary>> requests_; 111 std::unique_ptr<Navigation> navigation_;
109 VisitInfoCallback callback_; 112 VisitInfoCallback callback_;
110 113
111 DISALLOW_COPY_AND_ASSIGN(GetUrlVisitCountTask); 114 DISALLOW_COPY_AND_ASSIGN(GetUrlVisitCountTask);
112 }; 115 };
113 116
114 //////////////////////////////////////////////////////////////////////////////// 117 ////////////////////////////////////////////////////////////////////////////////
115 // ResourcePrefetchPredictor static functions. 118 // ResourcePrefetchPredictor static functions.
116 119
117 // static 120 // static
118 bool ResourcePrefetchPredictor::ShouldRecordRequest( 121 bool ResourcePrefetchPredictor::ShouldRecordRequest(
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 priority(other.priority), 277 priority(other.priority),
275 mime_type(other.mime_type), 278 mime_type(other.mime_type),
276 was_cached(other.was_cached), 279 was_cached(other.was_cached),
277 redirect_url(other.redirect_url), 280 redirect_url(other.redirect_url),
278 has_validators(other.has_validators), 281 has_validators(other.has_validators),
279 always_revalidate(other.always_revalidate) {} 282 always_revalidate(other.always_revalidate) {}
280 283
281 ResourcePrefetchPredictor::URLRequestSummary::~URLRequestSummary() { 284 ResourcePrefetchPredictor::URLRequestSummary::~URLRequestSummary() {
282 } 285 }
283 286
287 ResourcePrefetchPredictor::Navigation::Navigation(const GURL& i_initial_url)
288 : initial_url(i_initial_url) {}
289
290 ResourcePrefetchPredictor::Navigation::~Navigation() {}
291
284 // static 292 // static
285 bool ResourcePrefetchPredictor::URLRequestSummary::SummarizeResponse( 293 bool ResourcePrefetchPredictor::URLRequestSummary::SummarizeResponse(
286 const net::URLRequest& request, 294 const net::URLRequest& request,
287 URLRequestSummary* summary) { 295 URLRequestSummary* summary) {
288 const content::ResourceRequestInfo* info = 296 const content::ResourceRequestInfo* info =
289 content::ResourceRequestInfo::ForRequest(&request); 297 content::ResourceRequestInfo::ForRequest(&request);
290 if (!info) 298 if (!info)
291 return false; 299 return false;
292 300
293 int render_process_id, render_frame_id; 301 int render_process_id, render_frame_id;
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 const URLRequestSummary& request) { 438 const URLRequestSummary& request) {
431 DCHECK_CURRENTLY_ON(BrowserThread::UI); 439 DCHECK_CURRENTLY_ON(BrowserThread::UI);
432 DCHECK_EQ(INITIALIZED, initialization_state_); 440 DCHECK_EQ(INITIALIZED, initialization_state_);
433 441
434 StartPrefetching(request.navigation_id); 442 StartPrefetching(request.navigation_id);
435 443
436 // Cleanup older navigations. 444 // Cleanup older navigations.
437 CleanupAbandonedNavigations(request.navigation_id); 445 CleanupAbandonedNavigations(request.navigation_id);
438 446
439 // New empty navigation entry. 447 // New empty navigation entry.
448 const GURL& initial_url = request.navigation_id.main_frame_url;
440 inflight_navigations_.insert(std::make_pair( 449 inflight_navigations_.insert(std::make_pair(
441 request.navigation_id, 450 request.navigation_id, base::MakeUnique<Navigation>(initial_url)));
442 make_linked_ptr(new std::vector<URLRequestSummary>())));
443 } 451 }
444 452
445 void ResourcePrefetchPredictor::OnMainFrameResponse( 453 void ResourcePrefetchPredictor::OnMainFrameResponse(
446 const URLRequestSummary& response) { 454 const URLRequestSummary& response) {
447 DCHECK_CURRENTLY_ON(BrowserThread::UI); 455 DCHECK_CURRENTLY_ON(BrowserThread::UI);
448 if (initialization_state_ != INITIALIZED) 456 if (initialization_state_ != INITIALIZED)
449 return; 457 return;
450 458
451 StopPrefetching(response.navigation_id); 459 StopPrefetching(response.navigation_id);
452 } 460 }
453 461
454 void ResourcePrefetchPredictor::OnMainFrameRedirect( 462 void ResourcePrefetchPredictor::OnMainFrameRedirect(
455 const URLRequestSummary& response) { 463 const URLRequestSummary& response) {
456 DCHECK_CURRENTLY_ON(BrowserThread::UI); 464 DCHECK_CURRENTLY_ON(BrowserThread::UI);
457 465
458 // TODO(shishir): There are significant gains to be had here if we can use the 466 // TODO(shishir): There are significant gains to be had here if we can use the
459 // start URL in a redirect chain as the key to start prefetching. We can save 467 // start URL in a redirect chain as the key to start prefetching. We can save
460 // of redirect times considerably assuming that the redirect chains do not 468 // of redirect times considerably assuming that the redirect chains do not
461 // change. 469 // change.
462 470
463 // Stop any inflight prefetching. Remove the older navigation. 471 // Stop any inflight prefetching. Remove the older navigation.
464 StopPrefetching(response.navigation_id); 472 StopPrefetching(response.navigation_id);
465 inflight_navigations_.erase(response.navigation_id); 473
474 std::unique_ptr<Navigation> navigation;
475 NavigationMap::iterator nav_it =
476 inflight_navigations_.find(response.navigation_id);
477 if (nav_it != inflight_navigations_.end()) {
478 navigation.reset(nav_it->second.release());
479 inflight_navigations_.erase(nav_it);
480 }
466 481
467 // A redirect will not lead to another OnMainFrameRequest call, so record the 482 // A redirect will not lead to another OnMainFrameRequest call, so record the
468 // redirect url as a new navigation. 483 // redirect url as a new navigation.
469 484
470 // The redirect url may be empty if the URL was invalid. 485 // The redirect url may be empty if the URL was invalid.
471 if (response.redirect_url.is_empty()) 486 if (response.redirect_url.is_empty())
472 return; 487 return;
473 488
489 // If we lost information about first hop for some reason
Benoit L 2016/09/26 11:18:36 I'm not entirely sure about what should be done he
alexilin 2016/09/26 12:14:54 It could happen in some rare cases, for example, t
Benoit L 2016/09/27 09:55:06 Ok, thanks. Only a nit then: // If we lost the in
alexilin 2016/09/27 14:52:45 Thanks! Done.
490 if (!navigation)
491 navigation.reset(new Navigation(response.navigation_id.main_frame_url));
pasko 2016/09/22 14:27:09 why not MakeUnique here as well?
alexilin 2016/09/22 16:48:19 How to connect unique_ptr::reset() with MakeUnique
pasko 2016/09/26 12:28:15 navigation = MakeUnique<Navigation>(...)?
alexilin 2016/09/26 15:38:28 There will be one extra construction of unique_ptr
pasko 2016/09/26 15:58:22 I "think" on-stack unique_ptr constructors have al
alexilin 2016/09/27 14:52:45 Done.
492
474 NavigationID navigation_id(response.navigation_id); 493 NavigationID navigation_id(response.navigation_id);
475 navigation_id.main_frame_url = response.redirect_url; 494 navigation_id.main_frame_url = response.redirect_url;
476 inflight_navigations_.insert(std::make_pair( 495 inflight_navigations_.insert(
477 navigation_id, 496 std::make_pair(navigation_id, std::move(navigation)));
478 make_linked_ptr(new std::vector<URLRequestSummary>())));
479 } 497 }
480 498
481 void ResourcePrefetchPredictor::OnSubresourceResponse( 499 void ResourcePrefetchPredictor::OnSubresourceResponse(
482 const URLRequestSummary& response) { 500 const URLRequestSummary& response) {
483 DCHECK_CURRENTLY_ON(BrowserThread::UI); 501 DCHECK_CURRENTLY_ON(BrowserThread::UI);
484 502
485 NavigationMap::const_iterator nav_it = 503 NavigationMap::const_iterator nav_it =
486 inflight_navigations_.find(response.navigation_id); 504 inflight_navigations_.find(response.navigation_id);
487 if (nav_it == inflight_navigations_.end()) { 505 if (nav_it == inflight_navigations_.end()) {
488 return; 506 return;
489 } 507 }
490 508
491 nav_it->second->push_back(response); 509 nav_it->second->subresource_requests.push_back(response);
492 } 510 }
493 511
494 void ResourcePrefetchPredictor::OnNavigationComplete( 512 void ResourcePrefetchPredictor::OnNavigationComplete(
495 const NavigationID& nav_id_without_timing_info) { 513 const NavigationID& nav_id_without_timing_info) {
496 DCHECK_CURRENTLY_ON(BrowserThread::UI); 514 DCHECK_CURRENTLY_ON(BrowserThread::UI);
497 515
498 NavigationMap::iterator nav_it = 516 NavigationMap::iterator nav_it =
499 inflight_navigations_.find(nav_id_without_timing_info); 517 inflight_navigations_.find(nav_id_without_timing_info);
500 if (nav_it == inflight_navigations_.end()) 518 if (nav_it == inflight_navigations_.end())
501 return; 519 return;
502 520
503 const NavigationID navigation_id(nav_it->first); 521 const NavigationID navigation_id(nav_it->first);
504 522
505 // Remove the navigation from the inflight navigations. 523 // Remove the navigation from the inflight navigations.
506 std::vector<URLRequestSummary>* requests = (nav_it->second).release(); 524 std::unique_ptr<Navigation> navigation = std::move(nav_it->second);
507 inflight_navigations_.erase(nav_it); 525 inflight_navigations_.erase(nav_it);
508 526
509 // Kick off history lookup to determine if we should record the URL. 527 // Kick off history lookup to determine if we should record the URL.
510 history::HistoryService* history_service = 528 history::HistoryService* history_service =
511 HistoryServiceFactory::GetForProfile(profile_, 529 HistoryServiceFactory::GetForProfile(profile_,
512 ServiceAccessType::EXPLICIT_ACCESS); 530 ServiceAccessType::EXPLICIT_ACCESS);
513 DCHECK(history_service); 531 DCHECK(history_service);
514 history_service->ScheduleDBTask( 532 history_service->ScheduleDBTask(
515 std::unique_ptr<history::HistoryDBTask>(new GetUrlVisitCountTask( 533 std::unique_ptr<history::HistoryDBTask>(new GetUrlVisitCountTask(
516 navigation_id, requests, 534 navigation_id, std::move(navigation),
517 base::Bind(&ResourcePrefetchPredictor::OnVisitCountLookup, 535 base::Bind(&ResourcePrefetchPredictor::OnVisitCountLookup,
518 AsWeakPtr()))), 536 AsWeakPtr()))),
519 &history_lookup_consumer_); 537 &history_lookup_consumer_);
520 } 538 }
521 539
522 bool ResourcePrefetchPredictor::GetPrefetchData( 540 bool ResourcePrefetchPredictor::GetPrefetchData(
523 const NavigationID& navigation_id, 541 const NavigationID& navigation_id,
524 ResourcePrefetcher::RequestVector* prefetch_requests, 542 ResourcePrefetcher::RequestVector* prefetch_requests,
525 PrefetchKeyType* key_type) { 543 PrefetchKeyType* key_type) {
526 DCHECK(prefetch_requests); 544 DCHECK(prefetch_requests);
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 navigation_id)); 627 navigation_id));
610 } 628 }
611 629
612 void ResourcePrefetchPredictor::StartInitialization() { 630 void ResourcePrefetchPredictor::StartInitialization() {
613 DCHECK_CURRENTLY_ON(BrowserThread::UI); 631 DCHECK_CURRENTLY_ON(BrowserThread::UI);
614 632
615 DCHECK_EQ(NOT_INITIALIZED, initialization_state_); 633 DCHECK_EQ(NOT_INITIALIZED, initialization_state_);
616 initialization_state_ = INITIALIZING; 634 initialization_state_ = INITIALIZING;
617 635
618 // Create local caches using the database as loaded. 636 // Create local caches using the database as loaded.
619 std::unique_ptr<PrefetchDataMap> url_data_map(new PrefetchDataMap()); 637 std::unique_ptr<PrefetchDataMap> url_data_map(new PrefetchDataMap());
Benoit L 2016/09/26 11:18:36 nit: Can you use MakeUnique, here and below? auto
alexilin 2016/09/26 12:14:54 Done.
620 std::unique_ptr<PrefetchDataMap> host_data_map(new PrefetchDataMap()); 638 std::unique_ptr<PrefetchDataMap> host_data_map(new PrefetchDataMap());
639 std::unique_ptr<RedirectDataMap> url_redirect_data_map(new RedirectDataMap());
640 std::unique_ptr<RedirectDataMap> host_redirect_data_map(
641 new RedirectDataMap());
621 PrefetchDataMap* url_data_ptr = url_data_map.get(); 642 PrefetchDataMap* url_data_ptr = url_data_map.get();
622 PrefetchDataMap* host_data_ptr = host_data_map.get(); 643 PrefetchDataMap* host_data_ptr = host_data_map.get();
644 RedirectDataMap* url_redirect_data_ptr = url_redirect_data_map.get();
Benoit L 2016/09/26 11:18:36 nit: you can directly call .get() below.
alexilin 2016/09/26 12:14:54 Done.
645 RedirectDataMap* host_redirect_data_ptr = host_redirect_data_map.get();
623 646
624 BrowserThread::PostTaskAndReply( 647 BrowserThread::PostTaskAndReply(
625 BrowserThread::DB, FROM_HERE, 648 BrowserThread::DB, FROM_HERE,
626 base::Bind(&ResourcePrefetchPredictorTables::GetAllData, 649 base::Bind(&ResourcePrefetchPredictorTables::GetAllData, tables_,
627 tables_, url_data_ptr, host_data_ptr), 650 url_data_ptr, host_data_ptr, url_redirect_data_ptr,
651 host_redirect_data_ptr),
628 base::Bind(&ResourcePrefetchPredictor::CreateCaches, AsWeakPtr(), 652 base::Bind(&ResourcePrefetchPredictor::CreateCaches, AsWeakPtr(),
629 base::Passed(&url_data_map), base::Passed(&host_data_map))); 653 base::Passed(&url_data_map), base::Passed(&host_data_map),
654 base::Passed(&url_redirect_data_map),
655 base::Passed(&host_redirect_data_map)));
630 } 656 }
631 657
632 void ResourcePrefetchPredictor::CreateCaches( 658 void ResourcePrefetchPredictor::CreateCaches(
633 std::unique_ptr<PrefetchDataMap> url_data_map, 659 std::unique_ptr<PrefetchDataMap> url_data_map,
634 std::unique_ptr<PrefetchDataMap> host_data_map) { 660 std::unique_ptr<PrefetchDataMap> host_data_map,
661 std::unique_ptr<RedirectDataMap> url_redirect_data_map,
662 std::unique_ptr<RedirectDataMap> host_redirect_data_map) {
635 DCHECK_CURRENTLY_ON(BrowserThread::UI); 663 DCHECK_CURRENTLY_ON(BrowserThread::UI);
636 664
637 DCHECK_EQ(INITIALIZING, initialization_state_); 665 DCHECK_EQ(INITIALIZING, initialization_state_);
638 DCHECK(!url_table_cache_); 666 DCHECK(!url_table_cache_);
639 DCHECK(!host_table_cache_); 667 DCHECK(!host_table_cache_);
668 DCHECK(!url_redirect_table_cache_);
669 DCHECK(!host_redirect_table_cache_);
640 DCHECK(inflight_navigations_.empty()); 670 DCHECK(inflight_navigations_.empty());
641 671
642 url_table_cache_.reset(url_data_map.release()); 672 url_table_cache_.reset(url_data_map.release());
643 host_table_cache_.reset(host_data_map.release()); 673 host_table_cache_.reset(host_data_map.release());
674 url_redirect_table_cache_.reset(url_redirect_data_map.release());
675 host_redirect_table_cache_.reset(host_redirect_data_map.release());
644 676
645 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.UrlTableMainFrameUrlCount", 677 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.UrlTableMainFrameUrlCount",
646 url_table_cache_->size()); 678 url_table_cache_->size());
647 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.HostTableHostCount", 679 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.HostTableHostCount",
648 host_table_cache_->size()); 680 host_table_cache_->size());
649 681
650 ConnectToHistoryService(); 682 ConnectToHistoryService();
651 } 683 }
652 684
653 void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() { 685 void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 } 742 }
711 743
712 const std::string& host = it.url().host(); 744 const std::string& host = it.url().host();
713 if (host_table_cache_->find(host) != host_table_cache_->end()) { 745 if (host_table_cache_->find(host) != host_table_cache_->end()) {
714 hosts_to_delete.push_back(host); 746 hosts_to_delete.push_back(host);
715 host_table_cache_->erase(host); 747 host_table_cache_->erase(host);
716 } 748 }
717 } 749 }
718 750
719 if (!urls_to_delete.empty() || !hosts_to_delete.empty()) { 751 if (!urls_to_delete.empty() || !hosts_to_delete.empty()) {
720 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, 752 BrowserThread::PostTask(
721 base::Bind(&ResourcePrefetchPredictorTables::DeleteData, 753 BrowserThread::DB, FROM_HERE,
722 tables_, 754 base::Bind(&ResourcePrefetchPredictorTables::DeleteResourceData,
723 urls_to_delete, 755 tables_, urls_to_delete, hosts_to_delete));
724 hosts_to_delete));
725 } 756 }
726 } 757 }
727 758
728 void ResourcePrefetchPredictor::RemoveOldestEntryInPrefetchDataMap( 759 void ResourcePrefetchPredictor::RemoveOldestEntryInPrefetchDataMap(
729 PrefetchKeyType key_type, 760 PrefetchKeyType key_type,
730 PrefetchDataMap* data_map) { 761 PrefetchDataMap* data_map) {
731 if (data_map->empty()) 762 if (data_map->empty())
732 return; 763 return;
733 764
734 base::Time oldest_time; 765 base::Time oldest_time;
735 std::string key_to_delete; 766 std::string key_to_delete;
736 for (PrefetchDataMap::iterator it = data_map->begin(); 767 for (PrefetchDataMap::iterator it = data_map->begin();
737 it != data_map->end(); ++it) { 768 it != data_map->end(); ++it) {
738 if (key_to_delete.empty() || it->second.last_visit < oldest_time) { 769 if (key_to_delete.empty() || it->second.last_visit < oldest_time) {
739 key_to_delete = it->first; 770 key_to_delete = it->first;
740 oldest_time = it->second.last_visit; 771 oldest_time = it->second.last_visit;
741 } 772 }
742 } 773 }
743 774
744 data_map->erase(key_to_delete); 775 data_map->erase(key_to_delete);
745 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, 776 BrowserThread::PostTask(
746 base::Bind(&ResourcePrefetchPredictorTables::DeleteSingleDataPoint, 777 BrowserThread::DB, FROM_HERE,
747 tables_, 778 base::Bind(
748 key_to_delete, 779 &ResourcePrefetchPredictorTables::DeleteSingleResourceDataPoint,
749 key_type)); 780 tables_, key_to_delete, key_type));
781 }
782
783 void ResourcePrefetchPredictor::RemoveOldestEntryInRedirectDataMap(
784 PrefetchKeyType key_type,
785 RedirectDataMap* data_map) {
786 if (data_map->empty())
787 return;
788
789 uint64_t oldest_time;
790 std::string key_to_delete;
791 for (const auto& kv : *data_map) {
792 const RedirectData& data = kv.second;
793 if (key_to_delete.empty() || data.last_visit_time() < oldest_time) {
794 key_to_delete = data.primary_key();
795 oldest_time = data.last_visit_time();
796 }
797 }
798
799 data_map->erase(key_to_delete);
800 BrowserThread::PostTask(
801 BrowserThread::DB, FROM_HERE,
802 base::Bind(
803 &ResourcePrefetchPredictorTables::DeleteSingleRedirectDataPoint,
804 tables_, key_to_delete, key_type));
750 } 805 }
751 806
752 void ResourcePrefetchPredictor::OnVisitCountLookup( 807 void ResourcePrefetchPredictor::OnVisitCountLookup(
753 size_t visit_count, 808 size_t visit_count,
754 const NavigationID& navigation_id, 809 const NavigationID& navigation_id,
755 const std::vector<URLRequestSummary>& requests) { 810 const Navigation& navigation) {
756 DCHECK_CURRENTLY_ON(BrowserThread::UI); 811 DCHECK_CURRENTLY_ON(BrowserThread::UI);
757 812
758 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.HistoryVisitCountForUrl", 813 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.HistoryVisitCountForUrl",
759 visit_count); 814 visit_count);
760 815
816 // TODO(alexilin) make only one request to DB thread
817
761 // URL level data - merge only if we are already saving the data, or we it 818 // URL level data - merge only if we are already saving the data, or we it
762 // meets the cutoff requirement. 819 // meets the cutoff requirement.
763 const std::string url_spec = navigation_id.main_frame_url.spec(); 820 const std::string url_spec = navigation_id.main_frame_url.spec();
764 bool already_tracking = url_table_cache_->find(url_spec) != 821 bool already_tracking = url_table_cache_->find(url_spec) !=
765 url_table_cache_->end(); 822 url_table_cache_->end();
766 bool should_track_url = already_tracking || 823 bool should_track_url = already_tracking ||
767 (visit_count >= config_.min_url_visit_count); 824 (visit_count >= config_.min_url_visit_count);
768 825
769 if (should_track_url && config_.IsURLLearningEnabled()) { 826 if (should_track_url && config_.IsURLLearningEnabled()) {
770 LearnNavigation(url_spec, PREFETCH_KEY_TYPE_URL, requests, 827 LearnNavigation(url_spec, PREFETCH_KEY_TYPE_URL,
771 config_.max_urls_to_track, url_table_cache_.get()); 828 navigation.subresource_requests, config_.max_urls_to_track,
829 url_table_cache_.get(), navigation.initial_url.spec(),
830 url_redirect_table_cache_.get());
772 } 831 }
773 832
774 // Host level data - no cutoff, always learn the navigation if enabled. 833 // Host level data - no cutoff, always learn the navigation if enabled.
775 if (config_.IsHostLearningEnabled()) { 834 if (config_.IsHostLearningEnabled()) {
776 LearnNavigation(navigation_id.main_frame_url.host(), 835 const std::string host = navigation_id.main_frame_url.host();
777 PREFETCH_KEY_TYPE_HOST, 836 LearnNavigation(host, PREFETCH_KEY_TYPE_HOST,
778 requests, 837 navigation.subresource_requests, config_.max_hosts_to_track,
779 config_.max_hosts_to_track, 838 host_table_cache_.get(), navigation.initial_url.host(),
780 host_table_cache_.get()); 839 host_redirect_table_cache_.get());
781 } 840 }
782 841
783 // Remove the navigation from the results map. 842 // Remove the navigation from the results map.
784 results_map_.erase(navigation_id); 843 results_map_.erase(navigation_id);
785 } 844 }
786 845
787 void ResourcePrefetchPredictor::LearnNavigation( 846 void ResourcePrefetchPredictor::LearnNavigation(
788 const std::string& key, 847 const std::string& key,
789 PrefetchKeyType key_type, 848 PrefetchKeyType key_type,
790 const std::vector<URLRequestSummary>& new_resources, 849 const std::vector<URLRequestSummary>& new_resources,
791 size_t max_data_map_size, 850 size_t max_data_map_size,
792 PrefetchDataMap* data_map) { 851 PrefetchDataMap* data_map,
852 const std::string& redirect_origin_key,
853 RedirectDataMap* redirect_map) {
793 DCHECK_CURRENTLY_ON(BrowserThread::UI); 854 DCHECK_CURRENTLY_ON(BrowserThread::UI);
794 855
795 // If the primary key is too long reject it. 856 // If the primary key is too long reject it.
796 if (key.length() > ResourcePrefetchPredictorTables::kMaxStringLength) 857 if (key.length() > ResourcePrefetchPredictorTables::kMaxStringLength)
797 return; 858 return;
798 859
799 PrefetchDataMap::iterator cache_entry = data_map->find(key); 860 PrefetchDataMap::iterator cache_entry = data_map->find(key);
800 if (cache_entry == data_map->end()) { 861 if (cache_entry == data_map->end()) {
801 if (data_map->size() >= max_data_map_size) { 862 // If the table is full, delete an entry.
802 // The table is full, delete an entry. 863 if (data_map->size() >= max_data_map_size)
803 RemoveOldestEntryInPrefetchDataMap(key_type, data_map); 864 RemoveOldestEntryInPrefetchDataMap(key_type, data_map);
804 }
805 865
806 cache_entry = data_map->insert(std::make_pair( 866 cache_entry = data_map->insert(std::make_pair(
807 key, PrefetchData(key_type, key))).first; 867 key, PrefetchData(key_type, key))).first;
808 cache_entry->second.last_visit = base::Time::Now(); 868 cache_entry->second.last_visit = base::Time::Now();
809 size_t new_resources_size = new_resources.size(); 869 size_t new_resources_size = new_resources.size();
810 std::set<GURL> resources_seen; 870 std::set<GURL> resources_seen;
811 for (size_t i = 0; i < new_resources_size; ++i) { 871 for (size_t i = 0; i < new_resources_size; ++i) {
812 if (resources_seen.find(new_resources[i].resource_url) != 872 if (resources_seen.find(new_resources[i].resource_url) !=
813 resources_seen.end()) { 873 resources_seen.end()) {
814 continue; 874 continue;
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
914 ResourcePrefetchPredictorTables::SortResources(&resources); 974 ResourcePrefetchPredictorTables::SortResources(&resources);
915 if (resources.size() > config_.max_resources_per_entry) 975 if (resources.size() > config_.max_resources_per_entry)
916 resources.resize(config_.max_resources_per_entry); 976 resources.resize(config_.max_resources_per_entry);
917 977
918 // If the row has no resources, remove it from the cache and delete the 978 // If the row has no resources, remove it from the cache and delete the
919 // entry in the database. Else update the database. 979 // entry in the database. Else update the database.
920 if (resources.empty()) { 980 if (resources.empty()) {
921 data_map->erase(key); 981 data_map->erase(key);
922 BrowserThread::PostTask( 982 BrowserThread::PostTask(
923 BrowserThread::DB, FROM_HERE, 983 BrowserThread::DB, FROM_HERE,
924 base::Bind(&ResourcePrefetchPredictorTables::DeleteSingleDataPoint, 984 base::Bind(
925 tables_, 985 &ResourcePrefetchPredictorTables::DeleteSingleResourceDataPoint,
926 key, 986 tables_, key, key_type));
927 key_type));
928 } else { 987 } else {
929 bool is_host = key_type == PREFETCH_KEY_TYPE_HOST; 988 bool is_host = key_type == PREFETCH_KEY_TYPE_HOST;
930 PrefetchData empty_data( 989 PrefetchData empty_data(
931 !is_host ? PREFETCH_KEY_TYPE_HOST : PREFETCH_KEY_TYPE_URL, 990 !is_host ? PREFETCH_KEY_TYPE_HOST : PREFETCH_KEY_TYPE_URL,
932 std::string()); 991 std::string());
992 RedirectData empty_redirect_data;
933 const PrefetchData& host_data = is_host ? cache_entry->second : empty_data; 993 const PrefetchData& host_data = is_host ? cache_entry->second : empty_data;
934 const PrefetchData& url_data = is_host ? empty_data : cache_entry->second; 994 const PrefetchData& url_data = is_host ? empty_data : cache_entry->second;
935 BrowserThread::PostTask( 995 BrowserThread::PostTask(
936 BrowserThread::DB, FROM_HERE, 996 BrowserThread::DB, FROM_HERE,
937 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, 997 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, tables_,
938 tables_, 998 url_data, host_data, empty_redirect_data,
939 url_data, 999 empty_redirect_data));
940 host_data)); 1000 }
1001
1002 if (key != redirect_origin_key) {
1003 LearnRedirect(redirect_origin_key, key_type, key, max_data_map_size,
1004 redirect_map);
941 } 1005 }
942 } 1006 }
943 1007
1008 void ResourcePrefetchPredictor::LearnRedirect(const std::string& key,
1009 PrefetchKeyType key_type,
1010 const std::string& final_redirect,
1011 size_t max_redirect_map_size,
1012 RedirectDataMap* redirect_map) {
1013 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1014
1015 RedirectDataMap::iterator cache_entry = redirect_map->find(key);
1016 if (cache_entry == redirect_map->end()) {
1017 if (redirect_map->size() >= max_redirect_map_size)
1018 RemoveOldestEntryInRedirectDataMap(key_type, redirect_map);
1019
1020 RedirectData new_data;
1021 new_data.set_primary_key(key);
1022 cache_entry = redirect_map->insert(std::make_pair(key, new_data)).first;
1023 cache_entry->second.set_last_visit_time(
1024 base::Time::Now().ToInternalValue());
1025 RedirectStat* redirect_to_add = cache_entry->second.add_redirects();
1026 redirect_to_add->set_url(final_redirect);
1027 redirect_to_add->set_number_of_hits(1);
1028 } else {
1029 bool need_to_add = true;
1030 cache_entry->second.set_last_visit_time(
1031 base::Time::Now().ToInternalValue());
1032
1033 for (RedirectStat& redirect : *(cache_entry->second.mutable_redirects())) {
1034 if (redirect.url() == final_redirect) {
1035 need_to_add = false;
1036 redirect.set_number_of_hits(redirect.number_of_hits() + 1);
1037 redirect.set_consecutive_misses(0);
1038 } else {
1039 redirect.set_number_of_misses(redirect.number_of_misses() + 1);
1040 redirect.set_consecutive_misses(redirect.consecutive_misses() + 1);
1041 }
1042 }
1043
1044 if (need_to_add) {
1045 RedirectStat* redirect_to_add = cache_entry->second.add_redirects();
1046 redirect_to_add->set_url(final_redirect);
1047 redirect_to_add->set_number_of_hits(1);
1048 }
1049 }
1050
1051 // Trim and sort redirects after update.
1052 std::vector<RedirectStat> redirects;
1053 redirects.reserve(cache_entry->second.redirects_size());
1054 for (const RedirectStat& redirect : cache_entry->second.redirects()) {
1055 if (redirect.consecutive_misses() < config_.max_consecutive_misses)
1056 redirects.push_back(redirect);
1057 }
1058 ResourcePrefetchPredictorTables::SortRedirects(&redirects);
1059
1060 if (redirects.size() > kMaxRedirectsPerEntry)
1061 redirects.resize(kMaxRedirectsPerEntry);
1062
1063 cache_entry->second.clear_redirects();
1064 for (const RedirectStat& redirect : redirects)
1065 cache_entry->second.add_redirects()->CopyFrom(redirect);
1066
1067 if (redirects.empty()) {
1068 redirect_map->erase(cache_entry);
1069 BrowserThread::PostTask(
1070 BrowserThread::DB, FROM_HERE,
1071 base::Bind(
1072 &ResourcePrefetchPredictorTables::DeleteSingleRedirectDataPoint,
1073 tables_, key, key_type));
1074 } else {
1075 bool is_host = key_type == PREFETCH_KEY_TYPE_HOST;
1076 RedirectData empty_redirect_data;
1077 PrefetchData empty_url_data(PREFETCH_KEY_TYPE_URL, std::string());
1078 PrefetchData empty_host_data(PREFETCH_KEY_TYPE_HOST, std::string());
1079 const RedirectData& host_redirect_data =
1080 is_host ? cache_entry->second : empty_redirect_data;
1081 const RedirectData& url_redirect_data =
1082 is_host ? empty_redirect_data : cache_entry->second;
1083 BrowserThread::PostTask(
1084 BrowserThread::DB, FROM_HERE,
1085 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, tables_,
1086 empty_url_data, empty_host_data, url_redirect_data,
1087 host_redirect_data));
1088 }
1089 }
1090
944 void ResourcePrefetchPredictor::OnURLsDeleted( 1091 void ResourcePrefetchPredictor::OnURLsDeleted(
945 history::HistoryService* history_service, 1092 history::HistoryService* history_service,
946 bool all_history, 1093 bool all_history,
947 bool expired, 1094 bool expired,
948 const history::URLRows& deleted_rows, 1095 const history::URLRows& deleted_rows,
949 const std::set<GURL>& favicon_urls) { 1096 const std::set<GURL>& favicon_urls) {
950 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1097 DCHECK_CURRENTLY_ON(BrowserThread::UI);
951 if (INITIALIZED != initialization_state_) 1098 if (INITIALIZED != initialization_state_)
952 return; 1099 return;
953 1100
(...skipping 27 matching lines...) Expand all
981 // HistoryService is already loaded. Continue with Initialization. 1128 // HistoryService is already loaded. Continue with Initialization.
982 OnHistoryAndCacheLoaded(); 1129 OnHistoryAndCacheLoaded();
983 return; 1130 return;
984 } 1131 }
985 DCHECK(!history_service_observer_.IsObserving(history_service)); 1132 DCHECK(!history_service_observer_.IsObserving(history_service));
986 history_service_observer_.Add(history_service); 1133 history_service_observer_.Add(history_service);
987 return; 1134 return;
988 } 1135 }
989 1136
990 } // namespace predictors 1137 } // namespace predictors
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698