Chromium Code Reviews| 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 |
| 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" |
| 23 #include "chrome/common/chrome_switches.h" | 24 #include "chrome/common/chrome_switches.h" |
| 24 #include "chrome/common/url_constants.h" | 25 #include "chrome/common/url_constants.h" |
| 25 #include "components/history/core/browser/history_database.h" | 26 #include "components/history/core/browser/history_database.h" |
| 26 #include "components/history/core/browser/history_db_task.h" | |
| 27 #include "components/history/core/browser/history_service.h" | 27 #include "components/history/core/browser/history_service.h" |
| 28 #include "components/mime_util/mime_util.h" | 28 #include "components/mime_util/mime_util.h" |
| 29 #include "content/public/browser/browser_thread.h" | 29 #include "content/public/browser/browser_thread.h" |
| 30 #include "content/public/browser/navigation_controller.h" | 30 #include "content/public/browser/navigation_controller.h" |
| 31 #include "content/public/browser/resource_request_info.h" | 31 #include "content/public/browser/resource_request_info.h" |
| 32 #include "content/public/browser/web_contents.h" | 32 #include "content/public/browser/web_contents.h" |
| 33 #include "net/base/mime_util.h" | 33 #include "net/base/mime_util.h" |
| 34 #include "net/base/network_change_notifier.h" | 34 #include "net/base/network_change_notifier.h" |
| 35 #include "net/http/http_response_headers.h" | 35 #include "net/http/http_response_headers.h" |
| 36 #include "net/url_request/url_request.h" | 36 #include "net/url_request/url_request.h" |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 59 REPORTING_EVENT_ALL_HISTORY_CLEARED = 0, | 59 REPORTING_EVENT_ALL_HISTORY_CLEARED = 0, |
| 60 REPORTING_EVENT_PARTIAL_HISTORY_CLEARED = 1, | 60 REPORTING_EVENT_PARTIAL_HISTORY_CLEARED = 1, |
| 61 REPORTING_EVENT_COUNT = 2 | 61 REPORTING_EVENT_COUNT = 2 |
| 62 }; | 62 }; |
| 63 | 63 |
| 64 } // namespace | 64 } // namespace |
| 65 | 65 |
| 66 namespace predictors { | 66 namespace predictors { |
| 67 | 67 |
| 68 //////////////////////////////////////////////////////////////////////////////// | 68 //////////////////////////////////////////////////////////////////////////////// |
| 69 // History lookup task. | |
| 70 | |
| 71 // Used to fetch the visit count for a URL from the History database. | |
| 72 class GetUrlVisitCountTask : public history::HistoryDBTask { | |
| 73 public: | |
| 74 typedef ResourcePrefetchPredictor::URLRequestSummary URLRequestSummary; | |
| 75 typedef base::Callback<void( | |
| 76 size_t, // Visit count. | |
| 77 const NavigationID&, | |
| 78 const std::vector<URLRequestSummary>&)> VisitInfoCallback; | |
| 79 | |
| 80 GetUrlVisitCountTask( | |
| 81 const NavigationID& navigation_id, | |
| 82 std::vector<URLRequestSummary>* requests, | |
| 83 VisitInfoCallback callback) | |
| 84 : visit_count_(0), | |
| 85 navigation_id_(navigation_id), | |
| 86 requests_(requests), | |
| 87 callback_(callback) { | |
| 88 DCHECK(requests_.get()); | |
| 89 } | |
| 90 | |
| 91 bool RunOnDBThread(history::HistoryBackend* backend, | |
| 92 history::HistoryDatabase* db) override { | |
| 93 history::URLRow url_row; | |
| 94 if (db->GetRowForURL(navigation_id_.main_frame_url, &url_row)) | |
| 95 visit_count_ = url_row.visit_count(); | |
| 96 return true; | |
| 97 } | |
| 98 | |
| 99 void DoneRunOnMainThread() override { | |
| 100 callback_.Run(visit_count_, navigation_id_, *requests_); | |
| 101 } | |
| 102 | |
| 103 private: | |
| 104 ~GetUrlVisitCountTask() override {} | |
| 105 | |
| 106 int visit_count_; | |
| 107 NavigationID navigation_id_; | |
| 108 std::unique_ptr<std::vector<URLRequestSummary>> requests_; | |
| 109 VisitInfoCallback callback_; | |
| 110 | |
| 111 DISALLOW_COPY_AND_ASSIGN(GetUrlVisitCountTask); | |
| 112 }; | |
| 113 | |
| 114 //////////////////////////////////////////////////////////////////////////////// | |
| 115 // ResourcePrefetchPredictor static functions. | 69 // ResourcePrefetchPredictor static functions. |
| 116 | 70 |
| 117 // static | 71 // static |
| 118 bool ResourcePrefetchPredictor::ShouldRecordRequest( | 72 bool ResourcePrefetchPredictor::ShouldRecordRequest( |
| 119 net::URLRequest* request, | 73 net::URLRequest* request, |
| 120 content::ResourceType resource_type) { | 74 content::ResourceType resource_type) { |
| 121 const content::ResourceRequestInfo* request_info = | 75 const content::ResourceRequestInfo* request_info = |
| 122 content::ResourceRequestInfo::ForRequest(request); | 76 content::ResourceRequestInfo::ForRequest(request); |
| 123 if (!request_info) | 77 if (!request_info) |
| 124 return false; | 78 return false; |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 250 [&mime_type](const std::string& mime) { | 204 [&mime_type](const std::string& mime) { |
| 251 return net::MatchesMimeType(mime, mime_type); | 205 return net::MatchesMimeType(mime, mime_type); |
| 252 }); | 206 }); |
| 253 if (found) | 207 if (found) |
| 254 return content::RESOURCE_TYPE_FONT_RESOURCE; | 208 return content::RESOURCE_TYPE_FONT_RESOURCE; |
| 255 } | 209 } |
| 256 return fallback; | 210 return fallback; |
| 257 } | 211 } |
| 258 | 212 |
| 259 //////////////////////////////////////////////////////////////////////////////// | 213 //////////////////////////////////////////////////////////////////////////////// |
| 260 // ResourcePrefetchPredictor structs. | 214 // ResourcePrefetchPredictor nested types. |
| 261 | 215 |
| 262 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary() | 216 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary() |
| 263 : resource_type(content::RESOURCE_TYPE_LAST_TYPE), | 217 : resource_type(content::RESOURCE_TYPE_LAST_TYPE), |
| 264 priority(net::IDLE), | 218 priority(net::IDLE), |
| 265 was_cached(false), | 219 was_cached(false), |
| 266 has_validators(false), | 220 has_validators(false), |
| 267 always_revalidate(false) {} | 221 always_revalidate(false) {} |
| 268 | 222 |
| 269 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary( | 223 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary( |
| 270 const URLRequestSummary& other) | 224 const URLRequestSummary& other) |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 311 summary->has_validators = headers->HasValidators(); | 265 summary->has_validators = headers->HasValidators(); |
| 312 // RFC 2616, section 14.9. | 266 // RFC 2616, section 14.9. |
| 313 summary->always_revalidate = | 267 summary->always_revalidate = |
| 314 headers->HasHeaderValue("cache-control", "no-cache") || | 268 headers->HasHeaderValue("cache-control", "no-cache") || |
| 315 headers->HasHeaderValue("pragma", "no-cache") || | 269 headers->HasHeaderValue("pragma", "no-cache") || |
| 316 headers->HasHeaderValue("vary", "*"); | 270 headers->HasHeaderValue("vary", "*"); |
| 317 } | 271 } |
| 318 return true; | 272 return true; |
| 319 } | 273 } |
| 320 | 274 |
| 275 ResourcePrefetchPredictor::GetUrlVisitCountTask::GetUrlVisitCountTask( | |
| 276 const NavigationID& navigation_id, | |
| 277 std::unique_ptr<PageRequestSummary> summary, | |
| 278 VisitInfoCallback callback) | |
| 279 : visit_count_(0), | |
| 280 navigation_id_(navigation_id), | |
| 281 summary_(std::move(summary)), | |
| 282 callback_(callback) { | |
| 283 DCHECK(summary_.get()); | |
| 284 } | |
| 285 | |
| 286 bool ResourcePrefetchPredictor::GetUrlVisitCountTask::RunOnDBThread( | |
| 287 history::HistoryBackend* backend, | |
| 288 history::HistoryDatabase* db) { | |
| 289 history::URLRow url_row; | |
| 290 if (db->GetRowForURL(navigation_id_.main_frame_url, &url_row)) | |
| 291 visit_count_ = url_row.visit_count(); | |
| 292 return true; | |
| 293 } | |
| 294 | |
| 295 void ResourcePrefetchPredictor::GetUrlVisitCountTask::DoneRunOnMainThread() { | |
| 296 callback_.Run(visit_count_, navigation_id_, *summary_); | |
| 297 } | |
| 298 | |
| 299 ResourcePrefetchPredictor::GetUrlVisitCountTask::~GetUrlVisitCountTask() {} | |
| 300 | |
| 301 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary( | |
| 302 const GURL& i_initial_url) | |
| 303 : initial_url(i_initial_url) {} | |
| 304 | |
| 305 ResourcePrefetchPredictor::PageRequestSummary::~PageRequestSummary() {} | |
| 306 | |
| 321 //////////////////////////////////////////////////////////////////////////////// | 307 //////////////////////////////////////////////////////////////////////////////// |
| 322 // ResourcePrefetchPredictor. | 308 // ResourcePrefetchPredictor. |
| 323 | 309 |
| 324 ResourcePrefetchPredictor::ResourcePrefetchPredictor( | 310 ResourcePrefetchPredictor::ResourcePrefetchPredictor( |
| 325 const ResourcePrefetchPredictorConfig& config, | 311 const ResourcePrefetchPredictorConfig& config, |
| 326 Profile* profile) | 312 Profile* profile) |
| 327 : profile_(profile), | 313 : profile_(profile), |
| 328 config_(config), | 314 config_(config), |
| 329 initialization_state_(NOT_INITIALIZED), | 315 initialization_state_(NOT_INITIALIZED), |
| 330 tables_(PredictorDatabaseFactory::GetForProfile(profile) | 316 tables_(PredictorDatabaseFactory::GetForProfile(profile) |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 407 const URLRequestSummary& request) { | 393 const URLRequestSummary& request) { |
| 408 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 394 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 409 DCHECK_EQ(INITIALIZED, initialization_state_); | 395 DCHECK_EQ(INITIALIZED, initialization_state_); |
| 410 | 396 |
| 411 StartPrefetching(request.navigation_id); | 397 StartPrefetching(request.navigation_id); |
| 412 | 398 |
| 413 // Cleanup older navigations. | 399 // Cleanup older navigations. |
| 414 CleanupAbandonedNavigations(request.navigation_id); | 400 CleanupAbandonedNavigations(request.navigation_id); |
| 415 | 401 |
| 416 // New empty navigation entry. | 402 // New empty navigation entry. |
| 417 inflight_navigations_.insert(std::make_pair( | 403 const GURL& initial_url = request.navigation_id.main_frame_url; |
| 418 request.navigation_id, | 404 inflight_navigations_.insert( |
| 419 make_linked_ptr(new std::vector<URLRequestSummary>()))); | 405 std::make_pair(request.navigation_id, |
| 406 base::MakeUnique<PageRequestSummary>(initial_url))); | |
| 420 } | 407 } |
| 421 | 408 |
| 422 void ResourcePrefetchPredictor::OnMainFrameResponse( | 409 void ResourcePrefetchPredictor::OnMainFrameResponse( |
| 423 const URLRequestSummary& response) { | 410 const URLRequestSummary& response) { |
| 424 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 411 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 425 if (initialization_state_ != INITIALIZED) | 412 if (initialization_state_ != INITIALIZED) |
| 426 return; | 413 return; |
| 427 | 414 |
| 428 StopPrefetching(response.navigation_id); | 415 StopPrefetching(response.navigation_id); |
| 429 } | 416 } |
| 430 | 417 |
| 431 void ResourcePrefetchPredictor::OnMainFrameRedirect( | 418 void ResourcePrefetchPredictor::OnMainFrameRedirect( |
| 432 const URLRequestSummary& response) { | 419 const URLRequestSummary& response) { |
| 433 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 420 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 434 | 421 |
| 435 // TODO(shishir): There are significant gains to be had here if we can use the | |
| 436 // start URL in a redirect chain as the key to start prefetching. We can save | |
| 437 // of redirect times considerably assuming that the redirect chains do not | |
| 438 // change. | |
| 439 | |
| 440 // Stop any inflight prefetching. Remove the older navigation. | 422 // Stop any inflight prefetching. Remove the older navigation. |
| 441 StopPrefetching(response.navigation_id); | 423 StopPrefetching(response.navigation_id); |
| 442 inflight_navigations_.erase(response.navigation_id); | |
| 443 | 424 |
| 444 // A redirect will not lead to another OnMainFrameRequest call, so record the | 425 std::unique_ptr<PageRequestSummary> summary; |
| 445 // redirect url as a new navigation. | 426 NavigationMap::iterator nav_it = |
| 427 inflight_navigations_.find(response.navigation_id); | |
| 428 if (nav_it != inflight_navigations_.end()) { | |
| 429 summary.reset(nav_it->second.release()); | |
| 430 inflight_navigations_.erase(nav_it); | |
| 431 } | |
| 446 | 432 |
| 447 // The redirect url may be empty if the URL was invalid. | 433 // The redirect url may be empty if the URL was invalid. |
| 448 if (response.redirect_url.is_empty()) | 434 if (response.redirect_url.is_empty()) |
| 449 return; | 435 return; |
| 450 | 436 |
| 437 // If we lost the information about the first hop for some reason. | |
| 438 if (!summary) { | |
| 439 const GURL& initial_url = response.navigation_id.main_frame_url; | |
| 440 summary = base::MakeUnique<PageRequestSummary>(initial_url); | |
| 441 } | |
| 442 | |
| 443 // A redirect will not lead to another OnMainFrameRequest call, so record the | |
| 444 // redirect url as a new navigation id and save the initial url. | |
| 451 NavigationID navigation_id(response.navigation_id); | 445 NavigationID navigation_id(response.navigation_id); |
| 452 navigation_id.main_frame_url = response.redirect_url; | 446 navigation_id.main_frame_url = response.redirect_url; |
| 453 inflight_navigations_.insert(std::make_pair( | 447 inflight_navigations_.insert( |
| 454 navigation_id, | 448 std::make_pair(navigation_id, std::move(summary))); |
| 455 make_linked_ptr(new std::vector<URLRequestSummary>()))); | |
| 456 } | 449 } |
| 457 | 450 |
| 458 void ResourcePrefetchPredictor::OnSubresourceResponse( | 451 void ResourcePrefetchPredictor::OnSubresourceResponse( |
| 459 const URLRequestSummary& response) { | 452 const URLRequestSummary& response) { |
| 460 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 453 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 461 | 454 |
| 462 NavigationMap::const_iterator nav_it = | 455 NavigationMap::const_iterator nav_it = |
| 463 inflight_navigations_.find(response.navigation_id); | 456 inflight_navigations_.find(response.navigation_id); |
| 464 if (nav_it == inflight_navigations_.end()) { | 457 if (nav_it == inflight_navigations_.end()) { |
| 465 return; | 458 return; |
| 466 } | 459 } |
| 467 | 460 |
| 468 nav_it->second->push_back(response); | 461 nav_it->second->subresource_requests.push_back(response); |
| 469 } | 462 } |
| 470 | 463 |
| 471 void ResourcePrefetchPredictor::OnNavigationComplete( | 464 void ResourcePrefetchPredictor::OnNavigationComplete( |
| 472 const NavigationID& nav_id_without_timing_info) { | 465 const NavigationID& nav_id_without_timing_info) { |
| 473 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 466 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 474 | 467 |
| 475 NavigationMap::iterator nav_it = | 468 NavigationMap::iterator nav_it = |
| 476 inflight_navigations_.find(nav_id_without_timing_info); | 469 inflight_navigations_.find(nav_id_without_timing_info); |
| 477 if (nav_it == inflight_navigations_.end()) | 470 if (nav_it == inflight_navigations_.end()) |
| 478 return; | 471 return; |
| 479 | 472 |
| 480 const NavigationID navigation_id(nav_it->first); | 473 const NavigationID navigation_id(nav_it->first); |
| 481 | 474 |
| 482 // Remove the navigation from the inflight navigations. | 475 // Remove the navigation from the inflight navigations. |
| 483 std::vector<URLRequestSummary>* requests = (nav_it->second).release(); | 476 std::unique_ptr<PageRequestSummary> summary = std::move(nav_it->second); |
| 484 inflight_navigations_.erase(nav_it); | 477 inflight_navigations_.erase(nav_it); |
| 485 | 478 |
| 486 // Kick off history lookup to determine if we should record the URL. | 479 // Kick off history lookup to determine if we should record the URL. |
| 487 history::HistoryService* history_service = | 480 history::HistoryService* history_service = |
| 488 HistoryServiceFactory::GetForProfile(profile_, | 481 HistoryServiceFactory::GetForProfile(profile_, |
| 489 ServiceAccessType::EXPLICIT_ACCESS); | 482 ServiceAccessType::EXPLICIT_ACCESS); |
| 490 DCHECK(history_service); | 483 DCHECK(history_service); |
| 491 history_service->ScheduleDBTask( | 484 history_service->ScheduleDBTask( |
| 492 std::unique_ptr<history::HistoryDBTask>(new GetUrlVisitCountTask( | 485 std::unique_ptr<history::HistoryDBTask>(new GetUrlVisitCountTask( |
| 493 navigation_id, requests, | 486 navigation_id, std::move(summary), |
| 494 base::Bind(&ResourcePrefetchPredictor::OnVisitCountLookup, | 487 base::Bind(&ResourcePrefetchPredictor::OnVisitCountLookup, |
| 495 AsWeakPtr()))), | 488 AsWeakPtr()))), |
| 496 &history_lookup_consumer_); | 489 &history_lookup_consumer_); |
| 497 } | 490 } |
| 498 | 491 |
| 499 bool ResourcePrefetchPredictor::GetPrefetchData( | 492 bool ResourcePrefetchPredictor::GetPrefetchData( |
| 500 const NavigationID& navigation_id, | 493 const NavigationID& navigation_id, |
| 501 std::vector<GURL>* urls, | 494 std::vector<GURL>* urls, |
| 502 PrefetchKeyType* key_type) { | 495 PrefetchKeyType* key_type) { |
| 503 DCHECK(urls); | 496 DCHECK(urls); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 579 navigation_id)); | 572 navigation_id)); |
| 580 } | 573 } |
| 581 | 574 |
| 582 void ResourcePrefetchPredictor::StartInitialization() { | 575 void ResourcePrefetchPredictor::StartInitialization() { |
| 583 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 576 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 584 | 577 |
| 585 DCHECK_EQ(NOT_INITIALIZED, initialization_state_); | 578 DCHECK_EQ(NOT_INITIALIZED, initialization_state_); |
| 586 initialization_state_ = INITIALIZING; | 579 initialization_state_ = INITIALIZING; |
| 587 | 580 |
| 588 // Create local caches using the database as loaded. | 581 // Create local caches using the database as loaded. |
| 589 std::unique_ptr<PrefetchDataMap> url_data_map(new PrefetchDataMap()); | 582 auto url_data_map = base::MakeUnique<PrefetchDataMap>(); |
| 590 std::unique_ptr<PrefetchDataMap> host_data_map(new PrefetchDataMap()); | 583 auto host_data_map = base::MakeUnique<PrefetchDataMap>(); |
| 591 PrefetchDataMap* url_data_ptr = url_data_map.get(); | 584 auto url_redirect_data_map = base::MakeUnique<RedirectDataMap>(); |
| 592 PrefetchDataMap* host_data_ptr = host_data_map.get(); | 585 auto host_redirect_data_map = base::MakeUnique<RedirectDataMap>(); |
|
Reid Kleckner
2016/09/29 23:42:23
Removing the raw pointer local variables here is w
| |
| 593 | 586 |
| 594 BrowserThread::PostTaskAndReply( | 587 BrowserThread::PostTaskAndReply( |
| 595 BrowserThread::DB, FROM_HERE, | 588 BrowserThread::DB, FROM_HERE, |
| 596 base::Bind(&ResourcePrefetchPredictorTables::GetAllData, | 589 base::Bind(&ResourcePrefetchPredictorTables::GetAllData, tables_, |
| 597 tables_, url_data_ptr, host_data_ptr), | 590 url_data_map.get(), host_data_map.get(), |
| 591 url_redirect_data_map.get(), host_redirect_data_map.get()), | |
| 598 base::Bind(&ResourcePrefetchPredictor::CreateCaches, AsWeakPtr(), | 592 base::Bind(&ResourcePrefetchPredictor::CreateCaches, AsWeakPtr(), |
| 599 base::Passed(&url_data_map), base::Passed(&host_data_map))); | 593 base::Passed(&url_data_map), base::Passed(&host_data_map), |
| 594 base::Passed(&url_redirect_data_map), | |
| 595 base::Passed(&host_redirect_data_map))); | |
| 600 } | 596 } |
| 601 | 597 |
| 602 void ResourcePrefetchPredictor::CreateCaches( | 598 void ResourcePrefetchPredictor::CreateCaches( |
| 603 std::unique_ptr<PrefetchDataMap> url_data_map, | 599 std::unique_ptr<PrefetchDataMap> url_data_map, |
| 604 std::unique_ptr<PrefetchDataMap> host_data_map) { | 600 std::unique_ptr<PrefetchDataMap> host_data_map, |
| 601 std::unique_ptr<RedirectDataMap> url_redirect_data_map, | |
| 602 std::unique_ptr<RedirectDataMap> host_redirect_data_map) { | |
| 605 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 603 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 606 | 604 |
| 607 DCHECK_EQ(INITIALIZING, initialization_state_); | 605 DCHECK_EQ(INITIALIZING, initialization_state_); |
| 608 DCHECK(!url_table_cache_); | 606 DCHECK(!url_table_cache_); |
| 609 DCHECK(!host_table_cache_); | 607 DCHECK(!host_table_cache_); |
| 608 DCHECK(!url_redirect_table_cache_); | |
| 609 DCHECK(!host_redirect_table_cache_); | |
| 610 DCHECK(inflight_navigations_.empty()); | 610 DCHECK(inflight_navigations_.empty()); |
| 611 | 611 |
| 612 url_table_cache_ = std::move(url_data_map); | 612 url_table_cache_ = std::move(url_data_map); |
| 613 host_table_cache_ = std::move(host_data_map); | 613 host_table_cache_ = std::move(host_data_map); |
| 614 url_redirect_table_cache_ = std::move(url_redirect_data_map); | |
| 615 host_redirect_table_cache_ = std::move(host_redirect_data_map); | |
| 614 | 616 |
| 615 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.UrlTableMainFrameUrlCount", | 617 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.UrlTableMainFrameUrlCount", |
| 616 url_table_cache_->size()); | 618 url_table_cache_->size()); |
| 617 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.HostTableHostCount", | 619 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.HostTableHostCount", |
| 618 host_table_cache_->size()); | 620 host_table_cache_->size()); |
| 619 | 621 |
| 620 ConnectToHistoryService(); | 622 ConnectToHistoryService(); |
| 621 } | 623 } |
| 622 | 624 |
| 623 void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() { | 625 void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 646 } else { | 648 } else { |
| 647 ++it; | 649 ++it; |
| 648 } | 650 } |
| 649 } | 651 } |
| 650 } | 652 } |
| 651 | 653 |
| 652 void ResourcePrefetchPredictor::DeleteAllUrls() { | 654 void ResourcePrefetchPredictor::DeleteAllUrls() { |
| 653 inflight_navigations_.clear(); | 655 inflight_navigations_.clear(); |
| 654 url_table_cache_->clear(); | 656 url_table_cache_->clear(); |
| 655 host_table_cache_->clear(); | 657 host_table_cache_->clear(); |
| 658 url_redirect_table_cache_->clear(); | |
| 659 host_redirect_table_cache_->clear(); | |
| 656 | 660 |
| 657 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 661 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, |
| 658 base::Bind(&ResourcePrefetchPredictorTables::DeleteAllData, tables_)); | 662 base::Bind(&ResourcePrefetchPredictorTables::DeleteAllData, tables_)); |
| 659 } | 663 } |
| 660 | 664 |
| 661 void ResourcePrefetchPredictor::DeleteUrls(const history::URLRows& urls) { | 665 void ResourcePrefetchPredictor::DeleteUrls(const history::URLRows& urls) { |
| 662 // Check all the urls in the database and pick out the ones that are present | 666 // Check all the urls in the database and pick out the ones that are present |
| 663 // in the cache. | 667 // in the cache. |
| 664 std::vector<std::string> urls_to_delete, hosts_to_delete; | 668 std::vector<std::string> urls_to_delete, hosts_to_delete; |
| 669 std::vector<std::string> url_redirects_to_delete, host_redirects_to_delete; | |
| 665 | 670 |
| 666 for (const auto& it : urls) { | 671 for (const auto& it : urls) { |
| 667 const std::string& url_spec = it.url().spec(); | 672 const std::string& url_spec = it.url().spec(); |
| 668 if (url_table_cache_->find(url_spec) != url_table_cache_->end()) { | 673 if (url_table_cache_->find(url_spec) != url_table_cache_->end()) { |
| 669 urls_to_delete.push_back(url_spec); | 674 urls_to_delete.push_back(url_spec); |
| 670 url_table_cache_->erase(url_spec); | 675 url_table_cache_->erase(url_spec); |
| 671 } | 676 } |
| 672 | 677 |
| 678 if (url_redirect_table_cache_->find(url_spec) != | |
| 679 url_redirect_table_cache_->end()) { | |
| 680 url_redirects_to_delete.push_back(url_spec); | |
| 681 url_redirect_table_cache_->erase(url_spec); | |
| 682 } | |
| 683 | |
| 673 const std::string& host = it.url().host(); | 684 const std::string& host = it.url().host(); |
| 674 if (host_table_cache_->find(host) != host_table_cache_->end()) { | 685 if (host_table_cache_->find(host) != host_table_cache_->end()) { |
| 675 hosts_to_delete.push_back(host); | 686 hosts_to_delete.push_back(host); |
| 676 host_table_cache_->erase(host); | 687 host_table_cache_->erase(host); |
| 677 } | 688 } |
| 689 | |
| 690 if (host_redirect_table_cache_->find(host) != | |
| 691 host_redirect_table_cache_->end()) { | |
| 692 host_redirects_to_delete.push_back(host); | |
| 693 host_redirect_table_cache_->erase(host); | |
| 694 } | |
| 678 } | 695 } |
| 679 | 696 |
| 680 if (!urls_to_delete.empty() || !hosts_to_delete.empty()) { | 697 if (!urls_to_delete.empty() || !hosts_to_delete.empty()) { |
| 681 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 698 BrowserThread::PostTask( |
| 682 base::Bind(&ResourcePrefetchPredictorTables::DeleteData, | 699 BrowserThread::DB, FROM_HERE, |
| 683 tables_, | 700 base::Bind(&ResourcePrefetchPredictorTables::DeleteResourceData, |
| 684 urls_to_delete, | 701 tables_, urls_to_delete, hosts_to_delete)); |
| 685 hosts_to_delete)); | 702 } |
| 703 | |
| 704 if (!url_redirects_to_delete.empty() || !host_redirects_to_delete.empty()) { | |
| 705 BrowserThread::PostTask( | |
| 706 BrowserThread::DB, FROM_HERE, | |
| 707 base::Bind(&ResourcePrefetchPredictorTables::DeleteRedirectData, | |
| 708 tables_, url_redirects_to_delete, host_redirects_to_delete)); | |
| 686 } | 709 } |
| 687 } | 710 } |
| 688 | 711 |
| 689 void ResourcePrefetchPredictor::RemoveOldestEntryInPrefetchDataMap( | 712 void ResourcePrefetchPredictor::RemoveOldestEntryInPrefetchDataMap( |
| 690 PrefetchKeyType key_type, | 713 PrefetchKeyType key_type, |
| 691 PrefetchDataMap* data_map) { | 714 PrefetchDataMap* data_map) { |
| 692 if (data_map->empty()) | 715 if (data_map->empty()) |
| 693 return; | 716 return; |
| 694 | 717 |
| 695 base::Time oldest_time; | 718 base::Time oldest_time; |
| 696 std::string key_to_delete; | 719 std::string key_to_delete; |
| 697 for (PrefetchDataMap::iterator it = data_map->begin(); | 720 for (PrefetchDataMap::iterator it = data_map->begin(); |
| 698 it != data_map->end(); ++it) { | 721 it != data_map->end(); ++it) { |
| 699 if (key_to_delete.empty() || it->second.last_visit < oldest_time) { | 722 if (key_to_delete.empty() || it->second.last_visit < oldest_time) { |
| 700 key_to_delete = it->first; | 723 key_to_delete = it->first; |
| 701 oldest_time = it->second.last_visit; | 724 oldest_time = it->second.last_visit; |
| 702 } | 725 } |
| 703 } | 726 } |
| 704 | 727 |
| 705 data_map->erase(key_to_delete); | 728 data_map->erase(key_to_delete); |
| 706 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 729 BrowserThread::PostTask( |
| 707 base::Bind(&ResourcePrefetchPredictorTables::DeleteSingleDataPoint, | 730 BrowserThread::DB, FROM_HERE, |
| 708 tables_, | 731 base::Bind( |
| 709 key_to_delete, | 732 &ResourcePrefetchPredictorTables::DeleteSingleResourceDataPoint, |
| 710 key_type)); | 733 tables_, key_to_delete, key_type)); |
| 734 } | |
| 735 | |
| 736 void ResourcePrefetchPredictor::RemoveOldestEntryInRedirectDataMap( | |
| 737 PrefetchKeyType key_type, | |
| 738 RedirectDataMap* data_map) { | |
| 739 if (data_map->empty()) | |
| 740 return; | |
| 741 | |
| 742 uint64_t oldest_time = UINT64_MAX; | |
| 743 std::string key_to_delete; | |
| 744 for (const auto& kv : *data_map) { | |
| 745 const RedirectData& data = kv.second; | |
| 746 if (key_to_delete.empty() || data.last_visit_time() < oldest_time) { | |
| 747 key_to_delete = data.primary_key(); | |
| 748 oldest_time = data.last_visit_time(); | |
| 749 } | |
| 750 } | |
| 751 | |
| 752 data_map->erase(key_to_delete); | |
| 753 BrowserThread::PostTask( | |
| 754 BrowserThread::DB, FROM_HERE, | |
| 755 base::Bind( | |
| 756 &ResourcePrefetchPredictorTables::DeleteSingleRedirectDataPoint, | |
| 757 tables_, key_to_delete, key_type)); | |
| 711 } | 758 } |
| 712 | 759 |
| 713 void ResourcePrefetchPredictor::OnVisitCountLookup( | 760 void ResourcePrefetchPredictor::OnVisitCountLookup( |
| 714 size_t visit_count, | 761 size_t visit_count, |
| 715 const NavigationID& navigation_id, | 762 const NavigationID& navigation_id, |
| 716 const std::vector<URLRequestSummary>& requests) { | 763 const PageRequestSummary& summary) { |
| 717 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 764 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 718 | 765 |
| 719 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.HistoryVisitCountForUrl", | 766 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.HistoryVisitCountForUrl", |
| 720 visit_count); | 767 visit_count); |
| 721 | 768 |
| 722 // URL level data - merge only if we are already saving the data, or we it | 769 // TODO(alexilin): make only one request to DB thread. |
| 770 | |
| 771 // URL level data - merge only if we already saved the data, or it | |
| 723 // meets the cutoff requirement. | 772 // meets the cutoff requirement. |
| 724 const std::string url_spec = navigation_id.main_frame_url.spec(); | 773 const std::string url_spec = navigation_id.main_frame_url.spec(); |
| 725 bool already_tracking = url_table_cache_->find(url_spec) != | 774 bool already_tracking = url_table_cache_->find(url_spec) != |
| 726 url_table_cache_->end(); | 775 url_table_cache_->end(); |
| 727 bool should_track_url = already_tracking || | 776 bool should_track_url = already_tracking || |
| 728 (visit_count >= config_.min_url_visit_count); | 777 (visit_count >= config_.min_url_visit_count); |
| 729 | 778 |
| 730 if (should_track_url && config_.IsURLLearningEnabled()) { | 779 if (should_track_url && config_.IsURLLearningEnabled()) { |
| 731 LearnNavigation(url_spec, PREFETCH_KEY_TYPE_URL, requests, | 780 LearnNavigation(url_spec, PREFETCH_KEY_TYPE_URL, |
| 732 config_.max_urls_to_track, url_table_cache_.get()); | 781 summary.subresource_requests, config_.max_urls_to_track, |
| 782 url_table_cache_.get(), summary.initial_url.spec(), | |
| 783 url_redirect_table_cache_.get()); | |
| 733 } | 784 } |
| 734 | 785 |
| 735 // Host level data - no cutoff, always learn the navigation if enabled. | 786 // Host level data - no cutoff, always learn the navigation if enabled. |
| 736 if (config_.IsHostLearningEnabled()) { | 787 if (config_.IsHostLearningEnabled()) { |
| 737 LearnNavigation(navigation_id.main_frame_url.host(), | 788 const std::string host = navigation_id.main_frame_url.host(); |
| 738 PREFETCH_KEY_TYPE_HOST, | 789 LearnNavigation(host, PREFETCH_KEY_TYPE_HOST, summary.subresource_requests, |
| 739 requests, | 790 config_.max_hosts_to_track, host_table_cache_.get(), |
| 740 config_.max_hosts_to_track, | 791 summary.initial_url.host(), |
| 741 host_table_cache_.get()); | 792 host_redirect_table_cache_.get()); |
| 742 } | 793 } |
| 743 } | 794 } |
| 744 | 795 |
| 745 void ResourcePrefetchPredictor::LearnNavigation( | 796 void ResourcePrefetchPredictor::LearnNavigation( |
| 746 const std::string& key, | 797 const std::string& key, |
| 747 PrefetchKeyType key_type, | 798 PrefetchKeyType key_type, |
| 748 const std::vector<URLRequestSummary>& new_resources, | 799 const std::vector<URLRequestSummary>& new_resources, |
| 749 size_t max_data_map_size, | 800 size_t max_data_map_size, |
| 750 PrefetchDataMap* data_map) { | 801 PrefetchDataMap* data_map, |
| 802 const std::string& key_before_redirects, | |
| 803 RedirectDataMap* redirect_map) { | |
| 751 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 804 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 752 | 805 |
| 753 // If the primary key is too long reject it. | 806 // If the primary key is too long reject it. |
| 754 if (key.length() > ResourcePrefetchPredictorTables::kMaxStringLength) | 807 if (key.length() > ResourcePrefetchPredictorTables::kMaxStringLength) |
| 755 return; | 808 return; |
| 756 | 809 |
| 757 PrefetchDataMap::iterator cache_entry = data_map->find(key); | 810 PrefetchDataMap::iterator cache_entry = data_map->find(key); |
| 758 if (cache_entry == data_map->end()) { | 811 if (cache_entry == data_map->end()) { |
| 759 if (data_map->size() >= max_data_map_size) { | 812 // If the table is full, delete an entry. |
| 760 // The table is full, delete an entry. | 813 if (data_map->size() >= max_data_map_size) |
| 761 RemoveOldestEntryInPrefetchDataMap(key_type, data_map); | 814 RemoveOldestEntryInPrefetchDataMap(key_type, data_map); |
| 762 } | |
| 763 | 815 |
| 764 cache_entry = data_map->insert(std::make_pair( | 816 cache_entry = data_map->insert(std::make_pair( |
| 765 key, PrefetchData(key_type, key))).first; | 817 key, PrefetchData(key_type, key))).first; |
| 766 cache_entry->second.last_visit = base::Time::Now(); | 818 cache_entry->second.last_visit = base::Time::Now(); |
| 767 size_t new_resources_size = new_resources.size(); | 819 size_t new_resources_size = new_resources.size(); |
| 768 std::set<GURL> resources_seen; | 820 std::set<GURL> resources_seen; |
| 769 for (size_t i = 0; i < new_resources_size; ++i) { | 821 for (size_t i = 0; i < new_resources_size; ++i) { |
| 770 if (resources_seen.find(new_resources[i].resource_url) != | 822 if (resources_seen.find(new_resources[i].resource_url) != |
| 771 resources_seen.end()) { | 823 resources_seen.end()) { |
| 772 continue; | 824 continue; |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 872 ResourcePrefetchPredictorTables::SortResources(&resources); | 924 ResourcePrefetchPredictorTables::SortResources(&resources); |
| 873 if (resources.size() > config_.max_resources_per_entry) | 925 if (resources.size() > config_.max_resources_per_entry) |
| 874 resources.resize(config_.max_resources_per_entry); | 926 resources.resize(config_.max_resources_per_entry); |
| 875 | 927 |
| 876 // If the row has no resources, remove it from the cache and delete the | 928 // If the row has no resources, remove it from the cache and delete the |
| 877 // entry in the database. Else update the database. | 929 // entry in the database. Else update the database. |
| 878 if (resources.empty()) { | 930 if (resources.empty()) { |
| 879 data_map->erase(key); | 931 data_map->erase(key); |
| 880 BrowserThread::PostTask( | 932 BrowserThread::PostTask( |
| 881 BrowserThread::DB, FROM_HERE, | 933 BrowserThread::DB, FROM_HERE, |
| 882 base::Bind(&ResourcePrefetchPredictorTables::DeleteSingleDataPoint, | 934 base::Bind( |
| 883 tables_, | 935 &ResourcePrefetchPredictorTables::DeleteSingleResourceDataPoint, |
| 884 key, | 936 tables_, key, key_type)); |
| 885 key_type)); | |
| 886 } else { | 937 } else { |
| 887 bool is_host = key_type == PREFETCH_KEY_TYPE_HOST; | 938 bool is_host = key_type == PREFETCH_KEY_TYPE_HOST; |
| 888 PrefetchData empty_data( | 939 PrefetchData empty_data( |
| 889 !is_host ? PREFETCH_KEY_TYPE_HOST : PREFETCH_KEY_TYPE_URL, | 940 !is_host ? PREFETCH_KEY_TYPE_HOST : PREFETCH_KEY_TYPE_URL, |
| 890 std::string()); | 941 std::string()); |
| 942 RedirectData empty_redirect_data; | |
| 891 const PrefetchData& host_data = is_host ? cache_entry->second : empty_data; | 943 const PrefetchData& host_data = is_host ? cache_entry->second : empty_data; |
| 892 const PrefetchData& url_data = is_host ? empty_data : cache_entry->second; | 944 const PrefetchData& url_data = is_host ? empty_data : cache_entry->second; |
| 893 BrowserThread::PostTask( | 945 BrowserThread::PostTask( |
| 894 BrowserThread::DB, FROM_HERE, | 946 BrowserThread::DB, FROM_HERE, |
| 895 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, | 947 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, tables_, |
| 896 tables_, | 948 url_data, host_data, empty_redirect_data, |
| 897 url_data, | 949 empty_redirect_data)); |
| 898 host_data)); | 950 } |
| 951 | |
| 952 if (key != key_before_redirects) { | |
| 953 LearnRedirect(key_before_redirects, key_type, key, max_data_map_size, | |
| 954 redirect_map); | |
| 899 } | 955 } |
| 900 } | 956 } |
| 901 | 957 |
| 958 void ResourcePrefetchPredictor::LearnRedirect(const std::string& key, | |
| 959 PrefetchKeyType key_type, | |
| 960 const std::string& final_redirect, | |
| 961 size_t max_redirect_map_size, | |
| 962 RedirectDataMap* redirect_map) { | |
| 963 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 964 | |
| 965 RedirectDataMap::iterator cache_entry = redirect_map->find(key); | |
| 966 if (cache_entry == redirect_map->end()) { | |
| 967 if (redirect_map->size() >= max_redirect_map_size) | |
| 968 RemoveOldestEntryInRedirectDataMap(key_type, redirect_map); | |
| 969 | |
| 970 RedirectData new_data; | |
| 971 new_data.set_primary_key(key); | |
| 972 cache_entry = redirect_map->insert(std::make_pair(key, new_data)).first; | |
| 973 cache_entry->second.set_last_visit_time( | |
| 974 base::Time::Now().ToInternalValue()); | |
| 975 RedirectStat* redirect_to_add = | |
| 976 cache_entry->second.add_redirect_endpoints(); | |
| 977 redirect_to_add->set_url(final_redirect); | |
| 978 redirect_to_add->set_number_of_hits(1); | |
| 979 } else { | |
| 980 bool need_to_add = true; | |
| 981 cache_entry->second.set_last_visit_time( | |
| 982 base::Time::Now().ToInternalValue()); | |
| 983 | |
| 984 for (RedirectStat& redirect : | |
| 985 *(cache_entry->second.mutable_redirect_endpoints())) { | |
| 986 if (redirect.url() == final_redirect) { | |
| 987 need_to_add = false; | |
| 988 redirect.set_number_of_hits(redirect.number_of_hits() + 1); | |
| 989 redirect.set_consecutive_misses(0); | |
| 990 } else { | |
| 991 redirect.set_number_of_misses(redirect.number_of_misses() + 1); | |
| 992 redirect.set_consecutive_misses(redirect.consecutive_misses() + 1); | |
| 993 } | |
| 994 } | |
| 995 | |
| 996 if (need_to_add) { | |
| 997 RedirectStat* redirect_to_add = | |
| 998 cache_entry->second.add_redirect_endpoints(); | |
| 999 redirect_to_add->set_url(final_redirect); | |
| 1000 redirect_to_add->set_number_of_hits(1); | |
| 1001 } | |
| 1002 } | |
| 1003 | |
| 1004 // Trim and sort redirects after update. | |
| 1005 std::vector<RedirectStat> redirects; | |
| 1006 redirects.reserve(cache_entry->second.redirect_endpoints_size()); | |
| 1007 for (const RedirectStat& redirect : | |
| 1008 cache_entry->second.redirect_endpoints()) { | |
| 1009 if (redirect.consecutive_misses() < config_.max_consecutive_misses) | |
| 1010 redirects.push_back(redirect); | |
| 1011 } | |
| 1012 ResourcePrefetchPredictorTables::SortRedirects(&redirects); | |
| 1013 | |
| 1014 cache_entry->second.clear_redirect_endpoints(); | |
| 1015 for (const RedirectStat& redirect : redirects) | |
| 1016 cache_entry->second.add_redirect_endpoints()->CopyFrom(redirect); | |
| 1017 | |
| 1018 if (redirects.empty()) { | |
| 1019 redirect_map->erase(cache_entry); | |
| 1020 BrowserThread::PostTask( | |
| 1021 BrowserThread::DB, FROM_HERE, | |
| 1022 base::Bind( | |
| 1023 &ResourcePrefetchPredictorTables::DeleteSingleRedirectDataPoint, | |
| 1024 tables_, key, key_type)); | |
| 1025 } else { | |
| 1026 bool is_host = key_type == PREFETCH_KEY_TYPE_HOST; | |
| 1027 RedirectData empty_redirect_data; | |
| 1028 PrefetchData empty_url_data(PREFETCH_KEY_TYPE_URL, std::string()); | |
| 1029 PrefetchData empty_host_data(PREFETCH_KEY_TYPE_HOST, std::string()); | |
| 1030 const RedirectData& host_redirect_data = | |
| 1031 is_host ? cache_entry->second : empty_redirect_data; | |
| 1032 const RedirectData& url_redirect_data = | |
| 1033 is_host ? empty_redirect_data : cache_entry->second; | |
| 1034 BrowserThread::PostTask( | |
| 1035 BrowserThread::DB, FROM_HERE, | |
| 1036 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, tables_, | |
| 1037 empty_url_data, empty_host_data, url_redirect_data, | |
| 1038 host_redirect_data)); | |
| 1039 } | |
| 1040 } | |
| 1041 | |
| 902 void ResourcePrefetchPredictor::OnURLsDeleted( | 1042 void ResourcePrefetchPredictor::OnURLsDeleted( |
| 903 history::HistoryService* history_service, | 1043 history::HistoryService* history_service, |
| 904 bool all_history, | 1044 bool all_history, |
| 905 bool expired, | 1045 bool expired, |
| 906 const history::URLRows& deleted_rows, | 1046 const history::URLRows& deleted_rows, |
| 907 const std::set<GURL>& favicon_urls) { | 1047 const std::set<GURL>& favicon_urls) { |
| 908 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1048 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 909 if (INITIALIZED != initialization_state_) | 1049 if (INITIALIZED != initialization_state_) |
| 910 return; | 1050 return; |
| 911 | 1051 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 939 // HistoryService is already loaded. Continue with Initialization. | 1079 // HistoryService is already loaded. Continue with Initialization. |
| 940 OnHistoryAndCacheLoaded(); | 1080 OnHistoryAndCacheLoaded(); |
| 941 return; | 1081 return; |
| 942 } | 1082 } |
| 943 DCHECK(!history_service_observer_.IsObserving(history_service)); | 1083 DCHECK(!history_service_observer_.IsObserving(history_service)); |
| 944 history_service_observer_.Add(history_service); | 1084 history_service_observer_.Add(history_service); |
| 945 return; | 1085 return; |
| 946 } | 1086 } |
| 947 | 1087 |
| 948 } // namespace predictors | 1088 } // namespace predictors |
| OLD | NEW |