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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 "application/font-woff2", | 47 "application/font-woff2", |
48 "font/x-woff", | 48 "font/x-woff", |
49 "application/x-font-ttf", | 49 "application/x-font-ttf", |
50 "font/woff", | 50 "font/woff", |
51 "font/ttf", | 51 "font/ttf", |
52 "application/x-font-otf", | 52 "application/x-font-otf", |
53 "x-font/woff", | 53 "x-font/woff", |
54 "application/font-sfnt", | 54 "application/font-sfnt", |
55 "application/font-ttf"}; | 55 "application/font-ttf"}; |
56 | 56 |
57 // For reporting whether a subresource is handled or not, and for what reasons. | |
58 enum ResourceStatus { | |
59 RESOURCE_STATUS_HANDLED = 0, | |
60 RESOURCE_STATUS_NOT_HTTP_OR_HTTPS_PAGE = 1, | |
61 RESOURCE_STATUS_NOT_HTTP_OR_HTTPS_RESOURCE = 2, | |
62 RESOURCE_STATUS_UNSUPPORTED_RESOURCE_TYPE = 4, | |
63 RESOURCE_STATUS_NOT_GET = 8, | |
64 RESOURCE_STATUS_URL_TOO_LONG = 16, | |
65 RESOURCE_STATUS_NO_STORE = 32, | |
66 RESOURCE_STATUS_HEADERS_MISSING = 64, | |
67 RESOURCE_STATUS_MAX = 128, | |
68 }; | |
69 | |
70 // For reporting various interesting events that occur during the loading of a | |
71 // single main frame. | |
72 enum NavigationEvent { | |
73 NAVIGATION_EVENT_REQUEST_STARTED = 0, | |
74 NAVIGATION_EVENT_REQUEST_REDIRECTED = 1, | |
75 NAVIGATION_EVENT_REQUEST_REDIRECTED_EMPTY_URL = 2, | |
76 NAVIGATION_EVENT_REQUEST_EXPIRED = 3, | |
77 NAVIGATION_EVENT_RESPONSE_STARTED = 4, | |
78 NAVIGATION_EVENT_ONLOAD = 5, | |
79 NAVIGATION_EVENT_ONLOAD_EMPTY_URL = 6, | |
80 NAVIGATION_EVENT_ONLOAD_UNTRACKED_URL = 7, | |
81 NAVIGATION_EVENT_ONLOAD_TRACKED_URL = 8, | |
82 NAVIGATION_EVENT_SHOULD_TRACK_URL = 9, | |
83 NAVIGATION_EVENT_SHOULD_NOT_TRACK_URL = 10, | |
84 NAVIGATION_EVENT_URL_TABLE_FULL = 11, | |
85 NAVIGATION_EVENT_HAVE_PREDICTIONS_FOR_URL = 12, | |
86 NAVIGATION_EVENT_NO_PREDICTIONS_FOR_URL = 13, | |
87 NAVIGATION_EVENT_MAIN_FRAME_URL_TOO_LONG = 14, | |
88 NAVIGATION_EVENT_HOST_TOO_LONG = 15, | |
89 NAVIGATION_EVENT_COUNT = 16, | |
90 }; | |
91 | |
92 // For reporting events of interest that are not tied to any navigation. | 57 // For reporting events of interest that are not tied to any navigation. |
93 enum ReportingEvent { | 58 enum ReportingEvent { |
94 REPORTING_EVENT_ALL_HISTORY_CLEARED = 0, | 59 REPORTING_EVENT_ALL_HISTORY_CLEARED = 0, |
95 REPORTING_EVENT_PARTIAL_HISTORY_CLEARED = 1, | 60 REPORTING_EVENT_PARTIAL_HISTORY_CLEARED = 1, |
96 REPORTING_EVENT_COUNT = 2 | 61 REPORTING_EVENT_COUNT = 2 |
97 }; | 62 }; |
98 | 63 |
99 void RecordNavigationEvent(NavigationEvent event) { | |
100 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationEvent", | |
101 event, | |
102 NAVIGATION_EVENT_COUNT); | |
103 } | |
104 | |
105 // These are additional connection types for | |
106 // net::NetworkChangeNotifier::ConnectionType. They have negative values in case | |
107 // the original network connection types expand. | |
108 enum AdditionalConnectionType { | |
109 CONNECTION_ALL = -2, | |
110 CONNECTION_CELLULAR = -1 | |
111 }; | |
112 | |
113 std::string GetNetTypeStr() { | |
114 switch (net::NetworkChangeNotifier::GetConnectionType()) { | |
115 case net::NetworkChangeNotifier::CONNECTION_ETHERNET: | |
116 return "Ethernet"; | |
117 case net::NetworkChangeNotifier::CONNECTION_WIFI: | |
118 return "WiFi"; | |
119 case net::NetworkChangeNotifier::CONNECTION_2G: | |
120 return "2G"; | |
121 case net::NetworkChangeNotifier::CONNECTION_3G: | |
122 return "3G"; | |
123 case net::NetworkChangeNotifier::CONNECTION_4G: | |
124 return "4G"; | |
125 case net::NetworkChangeNotifier::CONNECTION_NONE: | |
126 return "None"; | |
127 case net::NetworkChangeNotifier::CONNECTION_BLUETOOTH: | |
128 return "Bluetooth"; | |
129 case net::NetworkChangeNotifier::CONNECTION_UNKNOWN: | |
130 default: | |
131 break; | |
132 } | |
133 return "Unknown"; | |
134 } | |
135 | |
136 void ReportPrefetchedNetworkType(int type) { | |
137 UMA_HISTOGRAM_SPARSE_SLOWLY( | |
138 "ResourcePrefetchPredictor.NetworkType.Prefetched", | |
139 type); | |
140 } | |
141 | |
142 void ReportNotPrefetchedNetworkType(int type) { | |
143 UMA_HISTOGRAM_SPARSE_SLOWLY( | |
144 "ResourcePrefetchPredictor.NetworkType.NotPrefetched", | |
145 type); | |
146 } | |
147 | |
148 } // namespace | 64 } // namespace |
149 | 65 |
150 namespace predictors { | 66 namespace predictors { |
151 | 67 |
152 //////////////////////////////////////////////////////////////////////////////// | 68 //////////////////////////////////////////////////////////////////////////////// |
153 // History lookup task. | 69 // History lookup task. |
154 | 70 |
155 // Used to fetch the visit count for a URL from the History database. | 71 // Used to fetch the visit count for a URL from the History database. |
156 class GetUrlVisitCountTask : public history::HistoryDBTask { | 72 class GetUrlVisitCountTask : public history::HistoryDBTask { |
157 public: | 73 public: |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 | 164 |
249 // static | 165 // static |
250 bool ResourcePrefetchPredictor::IsHandledMainPage(net::URLRequest* request) { | 166 bool ResourcePrefetchPredictor::IsHandledMainPage(net::URLRequest* request) { |
251 return request->url().SchemeIsHTTPOrHTTPS(); | 167 return request->url().SchemeIsHTTPOrHTTPS(); |
252 } | 168 } |
253 | 169 |
254 // static | 170 // static |
255 bool ResourcePrefetchPredictor::IsHandledSubresource( | 171 bool ResourcePrefetchPredictor::IsHandledSubresource( |
256 net::URLRequest* response, | 172 net::URLRequest* response, |
257 content::ResourceType resource_type) { | 173 content::ResourceType resource_type) { |
258 int resource_status = 0; | 174 if (!response->first_party_for_cookies().SchemeIsHTTPOrHTTPS() || |
259 | 175 !response->url().SchemeIsHTTPOrHTTPS()) |
260 if (!response->first_party_for_cookies().SchemeIsHTTPOrHTTPS()) | 176 return false; |
261 resource_status |= RESOURCE_STATUS_NOT_HTTP_OR_HTTPS_PAGE; | |
262 | |
263 if (!response->url().SchemeIsHTTPOrHTTPS()) | |
264 resource_status |= RESOURCE_STATUS_NOT_HTTP_OR_HTTPS_RESOURCE; | |
265 | 177 |
266 std::string mime_type; | 178 std::string mime_type; |
267 response->GetMimeType(&mime_type); | 179 response->GetMimeType(&mime_type); |
268 if (!IsHandledResourceType(resource_type, mime_type)) | 180 if (!IsHandledResourceType(resource_type, mime_type)) |
269 resource_status |= RESOURCE_STATUS_UNSUPPORTED_RESOURCE_TYPE; | 181 return false; |
270 | 182 |
271 if (response->method() != "GET") | 183 if (response->method() != "GET") |
272 resource_status |= RESOURCE_STATUS_NOT_GET; | 184 return false; |
273 | 185 |
274 if (response->original_url().spec().length() > | 186 if (response->original_url().spec().length() > |
275 ResourcePrefetchPredictorTables::kMaxStringLength) { | 187 ResourcePrefetchPredictorTables::kMaxStringLength) { |
276 resource_status |= RESOURCE_STATUS_URL_TOO_LONG; | 188 return false; |
277 } | 189 } |
278 | 190 |
279 if (!response->response_info().headers.get()) | 191 if (!response->response_info().headers.get() || IsNoStore(response)) |
280 resource_status |= RESOURCE_STATUS_HEADERS_MISSING; | 192 return false; |
281 | 193 |
282 if (IsNoStore(response)) | 194 return true; |
283 resource_status |= RESOURCE_STATUS_NO_STORE; | |
284 | |
285 return resource_status == 0; | |
286 } | 195 } |
287 | 196 |
288 // static | 197 // static |
289 bool ResourcePrefetchPredictor::IsHandledResourceType( | 198 bool ResourcePrefetchPredictor::IsHandledResourceType( |
290 content::ResourceType resource_type, | 199 content::ResourceType resource_type, |
291 const std::string& mime_type) { | 200 const std::string& mime_type) { |
292 content::ResourceType actual_resource_type = | 201 content::ResourceType actual_resource_type = |
293 GetResourceType(resource_type, mime_type); | 202 GetResourceType(resource_type, mime_type); |
294 return actual_resource_type == content::RESOURCE_TYPE_STYLESHEET || | 203 return actual_resource_type == content::RESOURCE_TYPE_STYLESHEET || |
295 actual_resource_type == content::RESOURCE_TYPE_SCRIPT || | 204 actual_resource_type == content::RESOURCE_TYPE_SCRIPT || |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
477 } | 386 } |
478 | 387 |
479 void ResourcePrefetchPredictor::RecordMainFrameLoadComplete( | 388 void ResourcePrefetchPredictor::RecordMainFrameLoadComplete( |
480 const NavigationID& navigation_id) { | 389 const NavigationID& navigation_id) { |
481 switch (initialization_state_) { | 390 switch (initialization_state_) { |
482 case NOT_INITIALIZED: | 391 case NOT_INITIALIZED: |
483 StartInitialization(); | 392 StartInitialization(); |
484 break; | 393 break; |
485 case INITIALIZING: | 394 case INITIALIZING: |
486 break; | 395 break; |
487 case INITIALIZED: { | 396 case INITIALIZED: |
488 RecordNavigationEvent(NAVIGATION_EVENT_ONLOAD); | |
489 // WebContents can return an empty URL if the navigation entry | 397 // WebContents can return an empty URL if the navigation entry |
490 // corresponding to the navigation has not been created yet. | 398 // corresponding to the navigation has not been created yet. |
491 if (navigation_id.main_frame_url.is_empty()) | 399 if (!navigation_id.main_frame_url.is_empty()) |
492 RecordNavigationEvent(NAVIGATION_EVENT_ONLOAD_EMPTY_URL); | |
493 else | |
494 OnNavigationComplete(navigation_id); | 400 OnNavigationComplete(navigation_id); |
495 break; | 401 break; |
496 } | |
497 default: | 402 default: |
498 NOTREACHED() << "Unexpected initialization_state_: " | 403 NOTREACHED() << "Unexpected initialization_state_: " |
499 << initialization_state_; | 404 << initialization_state_; |
500 } | 405 } |
501 } | 406 } |
502 | 407 |
503 void ResourcePrefetchPredictor::FinishedPrefetchForNavigation( | 408 void ResourcePrefetchPredictor::FinishedPrefetchForNavigation( |
504 const NavigationID& navigation_id, | 409 const NavigationID& navigation_id, |
505 PrefetchKeyType key_type, | 410 PrefetchKeyType key_type, |
506 ResourcePrefetcher::RequestVector* requests) { | 411 ResourcePrefetcher::RequestVector* requests) { |
(...skipping 12 matching lines...) Expand all Loading... |
519 prefetch_manager_ = NULL; | 424 prefetch_manager_ = NULL; |
520 } | 425 } |
521 history_service_observer_.RemoveAll(); | 426 history_service_observer_.RemoveAll(); |
522 } | 427 } |
523 | 428 |
524 void ResourcePrefetchPredictor::OnMainFrameRequest( | 429 void ResourcePrefetchPredictor::OnMainFrameRequest( |
525 const URLRequestSummary& request) { | 430 const URLRequestSummary& request) { |
526 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 431 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
527 DCHECK_EQ(INITIALIZED, initialization_state_); | 432 DCHECK_EQ(INITIALIZED, initialization_state_); |
528 | 433 |
529 RecordNavigationEvent(NAVIGATION_EVENT_REQUEST_STARTED); | |
530 | |
531 StartPrefetching(request.navigation_id); | 434 StartPrefetching(request.navigation_id); |
532 | 435 |
533 // Cleanup older navigations. | 436 // Cleanup older navigations. |
534 CleanupAbandonedNavigations(request.navigation_id); | 437 CleanupAbandonedNavigations(request.navigation_id); |
535 | 438 |
536 // New empty navigation entry. | 439 // New empty navigation entry. |
537 inflight_navigations_.insert(std::make_pair( | 440 inflight_navigations_.insert(std::make_pair( |
538 request.navigation_id, | 441 request.navigation_id, |
539 make_linked_ptr(new std::vector<URLRequestSummary>()))); | 442 make_linked_ptr(new std::vector<URLRequestSummary>()))); |
540 } | 443 } |
541 | 444 |
542 void ResourcePrefetchPredictor::OnMainFrameResponse( | 445 void ResourcePrefetchPredictor::OnMainFrameResponse( |
543 const URLRequestSummary& response) { | 446 const URLRequestSummary& response) { |
544 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 447 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
545 if (initialization_state_ != INITIALIZED) | 448 if (initialization_state_ != INITIALIZED) |
546 return; | 449 return; |
547 | 450 |
548 RecordNavigationEvent(NAVIGATION_EVENT_RESPONSE_STARTED); | |
549 | |
550 StopPrefetching(response.navigation_id); | 451 StopPrefetching(response.navigation_id); |
551 } | 452 } |
552 | 453 |
553 void ResourcePrefetchPredictor::OnMainFrameRedirect( | 454 void ResourcePrefetchPredictor::OnMainFrameRedirect( |
554 const URLRequestSummary& response) { | 455 const URLRequestSummary& response) { |
555 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 456 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
556 | 457 |
557 RecordNavigationEvent(NAVIGATION_EVENT_REQUEST_REDIRECTED); | |
558 | |
559 // TODO(shishir): There are significant gains to be had here if we can use the | 458 // TODO(shishir): There are significant gains to be had here if we can use the |
560 // start URL in a redirect chain as the key to start prefetching. We can save | 459 // start URL in a redirect chain as the key to start prefetching. We can save |
561 // of redirect times considerably assuming that the redirect chains do not | 460 // of redirect times considerably assuming that the redirect chains do not |
562 // change. | 461 // change. |
563 | 462 |
564 // Stop any inflight prefetching. Remove the older navigation. | 463 // Stop any inflight prefetching. Remove the older navigation. |
565 StopPrefetching(response.navigation_id); | 464 StopPrefetching(response.navigation_id); |
566 inflight_navigations_.erase(response.navigation_id); | 465 inflight_navigations_.erase(response.navigation_id); |
567 | 466 |
568 // A redirect will not lead to another OnMainFrameRequest call, so record the | 467 // A redirect will not lead to another OnMainFrameRequest call, so record the |
569 // redirect url as a new navigation. | 468 // redirect url as a new navigation. |
570 | 469 |
571 // The redirect url may be empty if the url was invalid. | 470 // The redirect url may be empty if the URL was invalid. |
572 if (response.redirect_url.is_empty()) { | 471 if (response.redirect_url.is_empty()) |
573 RecordNavigationEvent(NAVIGATION_EVENT_REQUEST_REDIRECTED_EMPTY_URL); | |
574 return; | 472 return; |
575 } | |
576 | 473 |
577 NavigationID navigation_id(response.navigation_id); | 474 NavigationID navigation_id(response.navigation_id); |
578 navigation_id.main_frame_url = response.redirect_url; | 475 navigation_id.main_frame_url = response.redirect_url; |
579 inflight_navigations_.insert(std::make_pair( | 476 inflight_navigations_.insert(std::make_pair( |
580 navigation_id, | 477 navigation_id, |
581 make_linked_ptr(new std::vector<URLRequestSummary>()))); | 478 make_linked_ptr(new std::vector<URLRequestSummary>()))); |
582 } | 479 } |
583 | 480 |
584 void ResourcePrefetchPredictor::OnSubresourceResponse( | 481 void ResourcePrefetchPredictor::OnSubresourceResponse( |
585 const URLRequestSummary& response) { | 482 const URLRequestSummary& response) { |
586 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 483 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
587 | 484 |
588 NavigationMap::const_iterator nav_it = | 485 NavigationMap::const_iterator nav_it = |
589 inflight_navigations_.find(response.navigation_id); | 486 inflight_navigations_.find(response.navigation_id); |
590 if (nav_it == inflight_navigations_.end()) { | 487 if (nav_it == inflight_navigations_.end()) { |
591 return; | 488 return; |
592 } | 489 } |
593 | 490 |
594 nav_it->second->push_back(response); | 491 nav_it->second->push_back(response); |
595 } | 492 } |
596 | 493 |
597 base::TimeDelta ResourcePrefetchPredictor::OnNavigationComplete( | 494 void ResourcePrefetchPredictor::OnNavigationComplete( |
598 const NavigationID& nav_id_without_timing_info) { | 495 const NavigationID& nav_id_without_timing_info) { |
599 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 496 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
600 | 497 |
601 NavigationMap::iterator nav_it = | 498 NavigationMap::iterator nav_it = |
602 inflight_navigations_.find(nav_id_without_timing_info); | 499 inflight_navigations_.find(nav_id_without_timing_info); |
603 if (nav_it == inflight_navigations_.end()) { | 500 if (nav_it == inflight_navigations_.end()) |
604 RecordNavigationEvent(NAVIGATION_EVENT_ONLOAD_UNTRACKED_URL); | 501 return; |
605 return base::TimeDelta(); | |
606 } | |
607 RecordNavigationEvent(NAVIGATION_EVENT_ONLOAD_TRACKED_URL); | |
608 | 502 |
609 // Get and use the navigation ID stored in |inflight_navigations_| because it | |
610 // has the timing infomation. | |
611 const NavigationID navigation_id(nav_it->first); | 503 const NavigationID navigation_id(nav_it->first); |
612 | 504 |
613 // Report any stats. | |
614 base::TimeDelta plt = base::TimeTicks::Now() - navigation_id.creation_time; | |
615 ReportPageLoadTimeStats(plt); | |
616 if (prefetch_manager_.get()) { | |
617 ResultsMap::const_iterator results_it = results_map_.find(navigation_id); | |
618 bool have_prefetch_results = results_it != results_map_.end(); | |
619 UMA_HISTOGRAM_BOOLEAN("ResourcePrefetchPredictor.HavePrefetchResults", | |
620 have_prefetch_results); | |
621 if (have_prefetch_results) { | |
622 ReportAccuracyStats(results_it->second->key_type, | |
623 *(nav_it->second), | |
624 results_it->second->requests.get()); | |
625 ReportPageLoadTimePrefetchStats( | |
626 plt, | |
627 true, | |
628 base::Bind(&ReportPrefetchedNetworkType), | |
629 results_it->second->key_type); | |
630 } else { | |
631 ReportPageLoadTimePrefetchStats( | |
632 plt, | |
633 false, | |
634 base::Bind(&ReportNotPrefetchedNetworkType), | |
635 PREFETCH_KEY_TYPE_URL); | |
636 } | |
637 } else { | |
638 std::unique_ptr<ResourcePrefetcher::RequestVector> requests( | |
639 new ResourcePrefetcher::RequestVector); | |
640 PrefetchKeyType key_type; | |
641 if (GetPrefetchData(navigation_id, requests.get(), &key_type)) { | |
642 RecordNavigationEvent(NAVIGATION_EVENT_HAVE_PREDICTIONS_FOR_URL); | |
643 ReportPredictedAccuracyStats(key_type, | |
644 *(nav_it->second), | |
645 *requests); | |
646 } else { | |
647 RecordNavigationEvent(NAVIGATION_EVENT_NO_PREDICTIONS_FOR_URL); | |
648 } | |
649 } | |
650 | |
651 // Remove the navigation from the inflight navigations. | 505 // Remove the navigation from the inflight navigations. |
652 std::vector<URLRequestSummary>* requests = (nav_it->second).release(); | 506 std::vector<URLRequestSummary>* requests = (nav_it->second).release(); |
653 inflight_navigations_.erase(nav_it); | 507 inflight_navigations_.erase(nav_it); |
654 | 508 |
655 // Kick off history lookup to determine if we should record the URL. | 509 // Kick off history lookup to determine if we should record the URL. |
656 history::HistoryService* history_service = | 510 history::HistoryService* history_service = |
657 HistoryServiceFactory::GetForProfile(profile_, | 511 HistoryServiceFactory::GetForProfile(profile_, |
658 ServiceAccessType::EXPLICIT_ACCESS); | 512 ServiceAccessType::EXPLICIT_ACCESS); |
659 DCHECK(history_service); | 513 DCHECK(history_service); |
660 history_service->ScheduleDBTask( | 514 history_service->ScheduleDBTask( |
661 std::unique_ptr<history::HistoryDBTask>(new GetUrlVisitCountTask( | 515 std::unique_ptr<history::HistoryDBTask>(new GetUrlVisitCountTask( |
662 navigation_id, requests, | 516 navigation_id, requests, |
663 base::Bind(&ResourcePrefetchPredictor::OnVisitCountLookup, | 517 base::Bind(&ResourcePrefetchPredictor::OnVisitCountLookup, |
664 AsWeakPtr()))), | 518 AsWeakPtr()))), |
665 &history_lookup_consumer_); | 519 &history_lookup_consumer_); |
666 | |
667 return plt; | |
668 } | 520 } |
669 | 521 |
670 bool ResourcePrefetchPredictor::GetPrefetchData( | 522 bool ResourcePrefetchPredictor::GetPrefetchData( |
671 const NavigationID& navigation_id, | 523 const NavigationID& navigation_id, |
672 ResourcePrefetcher::RequestVector* prefetch_requests, | 524 ResourcePrefetcher::RequestVector* prefetch_requests, |
673 PrefetchKeyType* key_type) { | 525 PrefetchKeyType* key_type) { |
674 DCHECK(prefetch_requests); | 526 DCHECK(prefetch_requests); |
675 DCHECK(key_type); | 527 DCHECK(key_type); |
676 | 528 |
677 *key_type = PREFETCH_KEY_TYPE_URL; | 529 *key_type = PREFETCH_KEY_TYPE_URL; |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
812 const NavigationID& navigation_id) { | 664 const NavigationID& navigation_id) { |
813 static const base::TimeDelta max_navigation_age = | 665 static const base::TimeDelta max_navigation_age = |
814 base::TimeDelta::FromSeconds(config_.max_navigation_lifetime_seconds); | 666 base::TimeDelta::FromSeconds(config_.max_navigation_lifetime_seconds); |
815 | 667 |
816 base::TimeTicks time_now = base::TimeTicks::Now(); | 668 base::TimeTicks time_now = base::TimeTicks::Now(); |
817 for (NavigationMap::iterator it = inflight_navigations_.begin(); | 669 for (NavigationMap::iterator it = inflight_navigations_.begin(); |
818 it != inflight_navigations_.end();) { | 670 it != inflight_navigations_.end();) { |
819 if (it->first.IsSameRenderer(navigation_id) || | 671 if (it->first.IsSameRenderer(navigation_id) || |
820 (time_now - it->first.creation_time > max_navigation_age)) { | 672 (time_now - it->first.creation_time > max_navigation_age)) { |
821 inflight_navigations_.erase(it++); | 673 inflight_navigations_.erase(it++); |
822 RecordNavigationEvent(NAVIGATION_EVENT_REQUEST_EXPIRED); | |
823 } else { | 674 } else { |
824 ++it; | 675 ++it; |
825 } | 676 } |
826 } | 677 } |
827 for (ResultsMap::const_iterator it = results_map_.begin(); | 678 for (ResultsMap::const_iterator it = results_map_.begin(); |
828 it != results_map_.end();) { | 679 it != results_map_.end();) { |
829 if (it->first.IsSameRenderer(navigation_id) || | 680 if (it->first.IsSameRenderer(navigation_id) || |
830 (time_now - it->first.creation_time > max_navigation_age)) { | 681 (time_now - it->first.creation_time > max_navigation_age)) { |
831 results_map_.erase(it++); | 682 results_map_.erase(it++); |
832 } else { | 683 } else { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
906 visit_count); | 757 visit_count); |
907 | 758 |
908 // URL level data - merge only if we are already saving the data, or we it | 759 // URL level data - merge only if we are already saving the data, or we it |
909 // meets the cutoff requirement. | 760 // meets the cutoff requirement. |
910 const std::string url_spec = navigation_id.main_frame_url.spec(); | 761 const std::string url_spec = navigation_id.main_frame_url.spec(); |
911 bool already_tracking = url_table_cache_->find(url_spec) != | 762 bool already_tracking = url_table_cache_->find(url_spec) != |
912 url_table_cache_->end(); | 763 url_table_cache_->end(); |
913 bool should_track_url = already_tracking || | 764 bool should_track_url = already_tracking || |
914 (visit_count >= config_.min_url_visit_count); | 765 (visit_count >= config_.min_url_visit_count); |
915 | 766 |
916 if (should_track_url) { | 767 if (should_track_url && config_.IsURLLearningEnabled()) { |
917 RecordNavigationEvent(NAVIGATION_EVENT_SHOULD_TRACK_URL); | 768 LearnNavigation(url_spec, PREFETCH_KEY_TYPE_URL, requests, |
918 | 769 config_.max_urls_to_track, url_table_cache_.get()); |
919 if (config_.IsURLLearningEnabled()) { | |
920 LearnNavigation(url_spec, PREFETCH_KEY_TYPE_URL, requests, | |
921 config_.max_urls_to_track, url_table_cache_.get()); | |
922 } | |
923 } else { | |
924 RecordNavigationEvent(NAVIGATION_EVENT_SHOULD_NOT_TRACK_URL); | |
925 } | 770 } |
926 | 771 |
927 // Host level data - no cutoff, always learn the navigation if enabled. | 772 // Host level data - no cutoff, always learn the navigation if enabled. |
928 if (config_.IsHostLearningEnabled()) { | 773 if (config_.IsHostLearningEnabled()) { |
929 LearnNavigation(navigation_id.main_frame_url.host(), | 774 LearnNavigation(navigation_id.main_frame_url.host(), |
930 PREFETCH_KEY_TYPE_HOST, | 775 PREFETCH_KEY_TYPE_HOST, |
931 requests, | 776 requests, |
932 config_.max_hosts_to_track, | 777 config_.max_hosts_to_track, |
933 host_table_cache_.get()); | 778 host_table_cache_.get()); |
934 } | 779 } |
935 | 780 |
936 // Remove the navigation from the results map. | 781 // Remove the navigation from the results map. |
937 results_map_.erase(navigation_id); | 782 results_map_.erase(navigation_id); |
938 } | 783 } |
939 | 784 |
940 void ResourcePrefetchPredictor::LearnNavigation( | 785 void ResourcePrefetchPredictor::LearnNavigation( |
941 const std::string& key, | 786 const std::string& key, |
942 PrefetchKeyType key_type, | 787 PrefetchKeyType key_type, |
943 const std::vector<URLRequestSummary>& new_resources, | 788 const std::vector<URLRequestSummary>& new_resources, |
944 size_t max_data_map_size, | 789 size_t max_data_map_size, |
945 PrefetchDataMap* data_map) { | 790 PrefetchDataMap* data_map) { |
946 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 791 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
947 | 792 |
948 // If the primary key is too long reject it. | 793 // If the primary key is too long reject it. |
949 if (key.length() > ResourcePrefetchPredictorTables::kMaxStringLength) { | 794 if (key.length() > ResourcePrefetchPredictorTables::kMaxStringLength) |
950 if (key_type == PREFETCH_KEY_TYPE_HOST) | |
951 RecordNavigationEvent(NAVIGATION_EVENT_HOST_TOO_LONG); | |
952 else | |
953 RecordNavigationEvent(NAVIGATION_EVENT_MAIN_FRAME_URL_TOO_LONG); | |
954 return; | 795 return; |
955 } | |
956 | 796 |
957 PrefetchDataMap::iterator cache_entry = data_map->find(key); | 797 PrefetchDataMap::iterator cache_entry = data_map->find(key); |
958 if (cache_entry == data_map->end()) { | 798 if (cache_entry == data_map->end()) { |
959 if (data_map->size() >= max_data_map_size) { | 799 if (data_map->size() >= max_data_map_size) { |
960 // The table is full, delete an entry. | 800 // The table is full, delete an entry. |
961 RemoveOldestEntryInPrefetchDataMap(key_type, data_map); | 801 RemoveOldestEntryInPrefetchDataMap(key_type, data_map); |
962 } | 802 } |
963 | 803 |
964 cache_entry = data_map->insert(std::make_pair( | 804 cache_entry = data_map->insert(std::make_pair( |
965 key, PrefetchData(key_type, key))).first; | 805 key, PrefetchData(key_type, key))).first; |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1082 const PrefetchData& url_data = is_host ? empty_data : cache_entry->second; | 922 const PrefetchData& url_data = is_host ? empty_data : cache_entry->second; |
1083 BrowserThread::PostTask( | 923 BrowserThread::PostTask( |
1084 BrowserThread::DB, FROM_HERE, | 924 BrowserThread::DB, FROM_HERE, |
1085 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, | 925 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, |
1086 tables_, | 926 tables_, |
1087 url_data, | 927 url_data, |
1088 host_data)); | 928 host_data)); |
1089 } | 929 } |
1090 } | 930 } |
1091 | 931 |
1092 //////////////////////////////////////////////////////////////////////////////// | |
1093 // Page load time and accuracy measurement. | |
1094 | |
1095 // This is essentially UMA_HISTOGRAM_MEDIUM_TIMES, but it avoids using the | |
1096 // STATIC_HISTOGRAM_POINTER_BLOCK in UMA_HISTOGRAM definitions. | |
1097 #define RPP_HISTOGRAM_MEDIUM_TIMES(name, page_load_time) \ | |
1098 do { \ | |
1099 base::HistogramBase* histogram = base::Histogram::FactoryTimeGet( \ | |
1100 name, \ | |
1101 base::TimeDelta::FromMilliseconds(10), \ | |
1102 base::TimeDelta::FromMinutes(3), \ | |
1103 50, \ | |
1104 base::HistogramBase::kUmaTargetedHistogramFlag); \ | |
1105 histogram->AddTime(page_load_time); \ | |
1106 } while (0) | |
1107 | |
1108 void ResourcePrefetchPredictor::ReportPageLoadTimeStats( | |
1109 base::TimeDelta plt) const { | |
1110 net::NetworkChangeNotifier::ConnectionType connection_type = | |
1111 net::NetworkChangeNotifier::GetConnectionType(); | |
1112 | |
1113 RPP_HISTOGRAM_MEDIUM_TIMES("ResourcePrefetchPredictor.PLT", plt); | |
1114 RPP_HISTOGRAM_MEDIUM_TIMES( | |
1115 "ResourcePrefetchPredictor.PLT_" + GetNetTypeStr(), plt); | |
1116 if (net::NetworkChangeNotifier::IsConnectionCellular(connection_type)) | |
1117 RPP_HISTOGRAM_MEDIUM_TIMES("ResourcePrefetchPredictor.PLT_Cellular", plt); | |
1118 } | |
1119 | |
1120 void ResourcePrefetchPredictor::ReportPageLoadTimePrefetchStats( | |
1121 base::TimeDelta plt, | |
1122 bool prefetched, | |
1123 base::Callback<void(int)> report_network_type_callback, | |
1124 PrefetchKeyType key_type) const { | |
1125 net::NetworkChangeNotifier::ConnectionType connection_type = | |
1126 net::NetworkChangeNotifier::GetConnectionType(); | |
1127 bool on_cellular = | |
1128 net::NetworkChangeNotifier::IsConnectionCellular(connection_type); | |
1129 | |
1130 report_network_type_callback.Run(CONNECTION_ALL); | |
1131 report_network_type_callback.Run(connection_type); | |
1132 if (on_cellular) | |
1133 report_network_type_callback.Run(CONNECTION_CELLULAR); | |
1134 | |
1135 std::string prefetched_str; | |
1136 if (prefetched) | |
1137 prefetched_str = "Prefetched"; | |
1138 else | |
1139 prefetched_str = "NotPrefetched"; | |
1140 | |
1141 RPP_HISTOGRAM_MEDIUM_TIMES( | |
1142 "ResourcePrefetchPredictor.PLT." + prefetched_str, plt); | |
1143 RPP_HISTOGRAM_MEDIUM_TIMES( | |
1144 "ResourcePrefetchPredictor.PLT." + prefetched_str + "_" + GetNetTypeStr(), | |
1145 plt); | |
1146 if (on_cellular) { | |
1147 RPP_HISTOGRAM_MEDIUM_TIMES( | |
1148 "ResourcePrefetchPredictor.PLT." + prefetched_str + "_Cellular", plt); | |
1149 } | |
1150 | |
1151 if (!prefetched) | |
1152 return; | |
1153 | |
1154 std::string type = | |
1155 key_type == PREFETCH_KEY_TYPE_HOST ? "Host" : "Url"; | |
1156 RPP_HISTOGRAM_MEDIUM_TIMES( | |
1157 "ResourcePrefetchPredictor.PLT.Prefetched." + type, plt); | |
1158 RPP_HISTOGRAM_MEDIUM_TIMES( | |
1159 "ResourcePrefetchPredictor.PLT.Prefetched." + type + "_" | |
1160 + GetNetTypeStr(), | |
1161 plt); | |
1162 if (on_cellular) { | |
1163 RPP_HISTOGRAM_MEDIUM_TIMES( | |
1164 "ResourcePrefetchPredictor.PLT.Prefetched." + type + "_Cellular", | |
1165 plt); | |
1166 } | |
1167 } | |
1168 | |
1169 void ResourcePrefetchPredictor::ReportAccuracyStats( | |
1170 PrefetchKeyType key_type, | |
1171 const std::vector<URLRequestSummary>& actual, | |
1172 ResourcePrefetcher::RequestVector* prefetched) const { | |
1173 // Annotate the results. | |
1174 std::map<GURL, bool> actual_resources; | |
1175 for (std::vector<URLRequestSummary>::const_iterator it = actual.begin(); | |
1176 it != actual.end(); ++it) { | |
1177 actual_resources[it->resource_url] = it->was_cached; | |
1178 } | |
1179 | |
1180 int prefetch_cancelled = 0, prefetch_failed = 0, prefetch_not_started = 0; | |
1181 // 'a_' -> actual, 'p_' -> predicted. | |
1182 int p_cache_a_cache = 0, p_cache_a_network = 0, p_cache_a_notused = 0, | |
1183 p_network_a_cache = 0, p_network_a_network = 0, p_network_a_notused = 0; | |
1184 | |
1185 for (ResourcePrefetcher::RequestVector::iterator it = prefetched->begin(); | |
1186 it != prefetched->end(); ++it) { | |
1187 ResourcePrefetcher::Request* req = *it; | |
1188 | |
1189 // Set the usage states if the resource was actually used. | |
1190 std::map<GURL, bool>::const_iterator actual_it = | |
1191 actual_resources.find(req->resource_url); | |
1192 if (actual_it != actual_resources.end()) { | |
1193 if (actual_it->second) { | |
1194 req->usage_status = | |
1195 ResourcePrefetcher::Request::USAGE_STATUS_FROM_CACHE; | |
1196 } else { | |
1197 req->usage_status = | |
1198 ResourcePrefetcher::Request::USAGE_STATUS_FROM_NETWORK; | |
1199 } | |
1200 } | |
1201 | |
1202 switch (req->prefetch_status) { | |
1203 // TODO(shishir): Add histogram for each cancellation reason. | |
1204 case ResourcePrefetcher::Request::PREFETCH_STATUS_REDIRECTED: | |
1205 case ResourcePrefetcher::Request::PREFETCH_STATUS_AUTH_REQUIRED: | |
1206 case ResourcePrefetcher::Request::PREFETCH_STATUS_CERT_REQUIRED: | |
1207 case ResourcePrefetcher::Request::PREFETCH_STATUS_CERT_ERROR: | |
1208 case ResourcePrefetcher::Request::PREFETCH_STATUS_CANCELLED: | |
1209 ++prefetch_cancelled; | |
1210 break; | |
1211 | |
1212 case ResourcePrefetcher::Request::PREFETCH_STATUS_FAILED: | |
1213 ++prefetch_failed; | |
1214 break; | |
1215 | |
1216 case ResourcePrefetcher::Request::PREFETCH_STATUS_FROM_CACHE: | |
1217 if (req->usage_status == | |
1218 ResourcePrefetcher::Request::USAGE_STATUS_FROM_CACHE) | |
1219 ++p_cache_a_cache; | |
1220 else if (req->usage_status == | |
1221 ResourcePrefetcher::Request::USAGE_STATUS_FROM_NETWORK) | |
1222 ++p_cache_a_network; | |
1223 else | |
1224 ++p_cache_a_notused; | |
1225 break; | |
1226 | |
1227 case ResourcePrefetcher::Request::PREFETCH_STATUS_FROM_NETWORK: | |
1228 if (req->usage_status == | |
1229 ResourcePrefetcher::Request::USAGE_STATUS_FROM_CACHE) | |
1230 ++p_network_a_cache; | |
1231 else if (req->usage_status == | |
1232 ResourcePrefetcher::Request::USAGE_STATUS_FROM_NETWORK) | |
1233 ++p_network_a_network; | |
1234 else | |
1235 ++p_network_a_notused; | |
1236 break; | |
1237 | |
1238 case ResourcePrefetcher::Request::PREFETCH_STATUS_NOT_STARTED: | |
1239 ++prefetch_not_started; | |
1240 break; | |
1241 | |
1242 case ResourcePrefetcher::Request::PREFETCH_STATUS_STARTED: | |
1243 DLOG(FATAL) << "Invalid prefetch status"; | |
1244 break; | |
1245 } | |
1246 } | |
1247 | |
1248 int total_prefetched = p_cache_a_cache + p_cache_a_network + p_cache_a_notused | |
1249 + p_network_a_cache + p_network_a_network + p_network_a_notused; | |
1250 | |
1251 std::string histogram_type = key_type == PREFETCH_KEY_TYPE_HOST ? "Host." : | |
1252 "Url."; | |
1253 | |
1254 // Macros to avoid using the STATIC_HISTOGRAM_POINTER_BLOCK in UMA_HISTOGRAM | |
1255 // definitions. | |
1256 #define RPP_HISTOGRAM_PERCENTAGE(suffix, value) \ | |
1257 { \ | |
1258 std::string name = "ResourcePrefetchPredictor." + histogram_type + suffix; \ | |
1259 std::string g_name = "ResourcePrefetchPredictor." + std::string(suffix); \ | |
1260 base::HistogramBase* histogram = base::LinearHistogram::FactoryGet( \ | |
1261 name, 1, 101, 102, base::Histogram::kUmaTargetedHistogramFlag); \ | |
1262 histogram->Add(value); \ | |
1263 UMA_HISTOGRAM_PERCENTAGE(g_name, value); \ | |
1264 } | |
1265 | |
1266 RPP_HISTOGRAM_PERCENTAGE("PrefetchCancelled", | |
1267 prefetch_cancelled * 100.0 / total_prefetched); | |
1268 RPP_HISTOGRAM_PERCENTAGE("PrefetchFailed", | |
1269 prefetch_failed * 100.0 / total_prefetched); | |
1270 RPP_HISTOGRAM_PERCENTAGE("PrefetchFromCacheUsedFromCache", | |
1271 p_cache_a_cache * 100.0 / total_prefetched); | |
1272 RPP_HISTOGRAM_PERCENTAGE("PrefetchFromCacheUsedFromNetwork", | |
1273 p_cache_a_network * 100.0 / total_prefetched); | |
1274 RPP_HISTOGRAM_PERCENTAGE("PrefetchFromCacheNotUsed", | |
1275 p_cache_a_notused * 100.0 / total_prefetched); | |
1276 RPP_HISTOGRAM_PERCENTAGE("PrefetchFromNetworkUsedFromCache", | |
1277 p_network_a_cache * 100.0 / total_prefetched); | |
1278 RPP_HISTOGRAM_PERCENTAGE("PrefetchFromNetworkUsedFromNetwork", | |
1279 p_network_a_network * 100.0 / total_prefetched); | |
1280 RPP_HISTOGRAM_PERCENTAGE("PrefetchFromNetworkNotUsed", | |
1281 p_network_a_notused * 100.0 / total_prefetched); | |
1282 | |
1283 RPP_HISTOGRAM_PERCENTAGE( | |
1284 "PrefetchNotStarted", | |
1285 prefetch_not_started * 100.0 / (prefetch_not_started + total_prefetched)); | |
1286 | |
1287 #undef RPP_HISTOGRAM_PERCENTAGE | |
1288 } | |
1289 | |
1290 void ResourcePrefetchPredictor::ReportPredictedAccuracyStats( | |
1291 PrefetchKeyType key_type, | |
1292 const std::vector<URLRequestSummary>& actual, | |
1293 const ResourcePrefetcher::RequestVector& predicted) const { | |
1294 std::map<GURL, bool> actual_resources; | |
1295 int from_network = 0; | |
1296 for (std::vector<URLRequestSummary>::const_iterator it = actual.begin(); | |
1297 it != actual.end(); ++it) { | |
1298 actual_resources[it->resource_url] = it->was_cached; | |
1299 if (!it->was_cached) | |
1300 ++from_network; | |
1301 } | |
1302 | |
1303 // Measure the accuracy at 25, 50 predicted resources. | |
1304 ReportPredictedAccuracyStatsHelper(key_type, predicted, actual_resources, | |
1305 from_network, 25); | |
1306 ReportPredictedAccuracyStatsHelper(key_type, predicted, actual_resources, | |
1307 from_network, 50); | |
1308 } | |
1309 | |
1310 void ResourcePrefetchPredictor::ReportPredictedAccuracyStatsHelper( | |
1311 PrefetchKeyType key_type, | |
1312 const ResourcePrefetcher::RequestVector& predicted, | |
1313 const std::map<GURL, bool>& actual, | |
1314 size_t total_resources_fetched_from_network, | |
1315 size_t max_assumed_prefetched) const { | |
1316 int prefetch_cached = 0, prefetch_network = 0, prefetch_missed = 0; | |
1317 int num_assumed_prefetched = std::min(predicted.size(), | |
1318 max_assumed_prefetched); | |
1319 if (num_assumed_prefetched == 0) | |
1320 return; | |
1321 | |
1322 for (int i = 0; i < num_assumed_prefetched; ++i) { | |
1323 const ResourcePrefetcher::Request& row = *(predicted[i]); | |
1324 std::map<GURL, bool>::const_iterator it = actual.find(row.resource_url); | |
1325 if (it == actual.end()) { | |
1326 ++prefetch_missed; | |
1327 } else if (it->second) { | |
1328 ++prefetch_cached; | |
1329 } else { | |
1330 ++prefetch_network; | |
1331 } | |
1332 } | |
1333 | |
1334 std::string prefix = key_type == PREFETCH_KEY_TYPE_HOST ? | |
1335 "ResourcePrefetchPredictor.Host.Predicted" : | |
1336 "ResourcePrefetchPredictor.Url.Predicted"; | |
1337 std::string suffix = "_" + base::SizeTToString(max_assumed_prefetched); | |
1338 | |
1339 // Macros to avoid using the STATIC_HISTOGRAM_POINTER_BLOCK in UMA_HISTOGRAM | |
1340 // definitions. | |
1341 #define RPP_PREDICTED_HISTOGRAM_COUNTS(name, value) \ | |
1342 { \ | |
1343 std::string full_name = prefix + name + suffix; \ | |
1344 base::HistogramBase* histogram = base::Histogram::FactoryGet( \ | |
1345 full_name, 1, 1000000, 50, \ | |
1346 base::Histogram::kUmaTargetedHistogramFlag); \ | |
1347 histogram->Add(value); \ | |
1348 } | |
1349 | |
1350 #define RPP_PREDICTED_HISTOGRAM_PERCENTAGE(name, value) \ | |
1351 { \ | |
1352 std::string full_name = prefix + name + suffix; \ | |
1353 base::HistogramBase* histogram = base::LinearHistogram::FactoryGet( \ | |
1354 full_name, 1, 101, 102, base::Histogram::kUmaTargetedHistogramFlag); \ | |
1355 histogram->Add(value); \ | |
1356 } | |
1357 | |
1358 RPP_PREDICTED_HISTOGRAM_COUNTS("PrefetchCount", num_assumed_prefetched); | |
1359 RPP_PREDICTED_HISTOGRAM_COUNTS("PrefetchMisses_Count", prefetch_missed); | |
1360 RPP_PREDICTED_HISTOGRAM_COUNTS("PrefetchFromCache_Count", prefetch_cached); | |
1361 RPP_PREDICTED_HISTOGRAM_COUNTS("PrefetchFromNetwork_Count", prefetch_network); | |
1362 | |
1363 RPP_PREDICTED_HISTOGRAM_PERCENTAGE( | |
1364 "PrefetchMisses_PercentOfTotalPrefetched", | |
1365 prefetch_missed * 100.0 / num_assumed_prefetched); | |
1366 RPP_PREDICTED_HISTOGRAM_PERCENTAGE( | |
1367 "PrefetchFromCache_PercentOfTotalPrefetched", | |
1368 prefetch_cached * 100.0 / num_assumed_prefetched); | |
1369 RPP_PREDICTED_HISTOGRAM_PERCENTAGE( | |
1370 "PrefetchFromNetwork_PercentOfTotalPrefetched", | |
1371 prefetch_network * 100.0 / num_assumed_prefetched); | |
1372 | |
1373 // Measure the ratio of total number of resources prefetched from network vs | |
1374 // the total number of resources fetched by the page from the network. | |
1375 if (total_resources_fetched_from_network > 0) { | |
1376 RPP_PREDICTED_HISTOGRAM_PERCENTAGE( | |
1377 "PrefetchFromNetworkPercentOfTotalFromNetwork", | |
1378 prefetch_network * 100.0 / total_resources_fetched_from_network); | |
1379 } | |
1380 | |
1381 #undef RPP_HISTOGRAM_MEDIUM_TIMES | |
1382 #undef RPP_PREDICTED_HISTOGRAM_PERCENTAGE | |
1383 #undef RPP_PREDICTED_HISTOGRAM_COUNTS | |
1384 } | |
1385 | |
1386 void ResourcePrefetchPredictor::OnURLsDeleted( | 932 void ResourcePrefetchPredictor::OnURLsDeleted( |
1387 history::HistoryService* history_service, | 933 history::HistoryService* history_service, |
1388 bool all_history, | 934 bool all_history, |
1389 bool expired, | 935 bool expired, |
1390 const history::URLRows& deleted_rows, | 936 const history::URLRows& deleted_rows, |
1391 const std::set<GURL>& favicon_urls) { | 937 const std::set<GURL>& favicon_urls) { |
1392 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 938 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
1393 if (INITIALIZED != initialization_state_) | 939 if (INITIALIZED != initialization_state_) |
1394 return; | 940 return; |
1395 | 941 |
(...skipping 27 matching lines...) Expand all Loading... |
1423 // HistoryService is already loaded. Continue with Initialization. | 969 // HistoryService is already loaded. Continue with Initialization. |
1424 OnHistoryAndCacheLoaded(); | 970 OnHistoryAndCacheLoaded(); |
1425 return; | 971 return; |
1426 } | 972 } |
1427 DCHECK(!history_service_observer_.IsObserving(history_service)); | 973 DCHECK(!history_service_observer_.IsObserving(history_service)); |
1428 history_service_observer_.Add(history_service); | 974 history_service_observer_.Add(history_service); |
1429 return; | 975 return; |
1430 } | 976 } |
1431 | 977 |
1432 } // namespace predictors | 978 } // namespace predictors |
OLD | NEW |