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

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

Issue 2440723002: predictors: Make ResourcePrefetchPredictor observable. (Closed)
Patch Set: Tests for observer. Created 4 years, 1 month 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
(...skipping 21 matching lines...) Expand all
32 #include "content/public/browser/resource_request_info.h" 32 #include "content/public/browser/resource_request_info.h"
33 #include "content/public/browser/web_contents.h" 33 #include "content/public/browser/web_contents.h"
34 #include "net/base/mime_util.h" 34 #include "net/base/mime_util.h"
35 #include "net/base/network_change_notifier.h" 35 #include "net/base/network_change_notifier.h"
36 #include "net/http/http_response_headers.h" 36 #include "net/http/http_response_headers.h"
37 #include "net/url_request/url_request.h" 37 #include "net/url_request/url_request.h"
38 #include "net/url_request/url_request_context_getter.h" 38 #include "net/url_request/url_request_context_getter.h"
39 39
40 using content::BrowserThread; 40 using content::BrowserThread;
41 41
42 namespace predictors {
43
42 namespace { 44 namespace {
43 45
44 // Sorted by decreasing likelihood according to HTTP archive. 46 // Sorted by decreasing likelihood according to HTTP archive.
45 const char* kFontMimeTypes[] = {"font/woff2", 47 const char* kFontMimeTypes[] = {"font/woff2",
46 "application/x-font-woff", 48 "application/x-font-woff",
47 "application/font-woff", 49 "application/font-woff",
48 "application/font-woff2", 50 "application/font-woff2",
49 "font/x-woff", 51 "font/x-woff",
50 "application/x-font-ttf", 52 "application/x-font-ttf",
51 "font/woff", 53 "font/woff",
52 "font/ttf", 54 "font/ttf",
53 "application/x-font-otf", 55 "application/x-font-otf",
54 "x-font/woff", 56 "x-font/woff",
55 "application/font-sfnt", 57 "application/font-sfnt",
56 "application/font-ttf"}; 58 "application/font-ttf"};
57 59
58 // For reporting events of interest that are not tied to any navigation. 60 // For reporting events of interest that are not tied to any navigation.
59 enum ReportingEvent { 61 enum ReportingEvent {
60 REPORTING_EVENT_ALL_HISTORY_CLEARED = 0, 62 REPORTING_EVENT_ALL_HISTORY_CLEARED = 0,
61 REPORTING_EVENT_PARTIAL_HISTORY_CLEARED = 1, 63 REPORTING_EVENT_PARTIAL_HISTORY_CLEARED = 1,
62 REPORTING_EVENT_COUNT = 2 64 REPORTING_EVENT_COUNT = 2
63 }; 65 };
64 66
65 float ComputeRedirectConfidence(const predictors::RedirectStat& redirect) { 67 float ComputeRedirectConfidence(const predictors::RedirectStat& redirect) {
66 return (redirect.number_of_hits() + 0.0) / 68 return (redirect.number_of_hits() + 0.0) /
67 (redirect.number_of_hits() + redirect.number_of_misses()); 69 (redirect.number_of_hits() + redirect.number_of_misses());
68 } 70 }
69 71
72 // Used to fetch the visit count for a URL from the History database.
73 class GetUrlVisitCountTask : public history::HistoryDBTask {
74 public:
75 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary;
76 using PageRequestSummary = ResourcePrefetchPredictor::PageRequestSummary;
77 typedef base::Callback<void(size_t, // URL visit count.
78 const PageRequestSummary&)>
79 VisitInfoCallback;
80
81 GetUrlVisitCountTask(std::unique_ptr<PageRequestSummary> summary,
82 VisitInfoCallback callback);
83
84 bool RunOnDBThread(history::HistoryBackend* backend,
85 history::HistoryDatabase* db) override;
86
87 void DoneRunOnMainThread() override;
88
89 private:
90 ~GetUrlVisitCountTask() override;
91
92 int visit_count_;
93 std::unique_ptr<PageRequestSummary> summary_;
94 VisitInfoCallback callback_;
95
96 DISALLOW_COPY_AND_ASSIGN(GetUrlVisitCountTask);
97 };
98
99 GetUrlVisitCountTask::GetUrlVisitCountTask(
100 std::unique_ptr<PageRequestSummary> summary,
101 VisitInfoCallback callback)
102 : visit_count_(0), summary_(std::move(summary)), callback_(callback) {
103 DCHECK(summary_.get());
104 }
105
106 bool GetUrlVisitCountTask::RunOnDBThread(history::HistoryBackend* backend,
107 history::HistoryDatabase* db) {
108 history::URLRow url_row;
109 if (db->GetRowForURL(summary_->main_frame_url, &url_row))
110 visit_count_ = url_row.visit_count();
111 return true;
112 }
113
114 void GetUrlVisitCountTask::DoneRunOnMainThread() {
115 callback_.Run(visit_count_, *summary_);
116 }
117
118 GetUrlVisitCountTask::~GetUrlVisitCountTask() {}
119
70 } // namespace 120 } // namespace
71 121
72 namespace predictors {
73
74 //////////////////////////////////////////////////////////////////////////////// 122 ////////////////////////////////////////////////////////////////////////////////
75 // ResourcePrefetchPredictor static functions. 123 // ResourcePrefetchPredictor static functions.
76 124
77 // static 125 // static
78 bool ResourcePrefetchPredictor::ShouldRecordRequest( 126 bool ResourcePrefetchPredictor::ShouldRecordRequest(
79 net::URLRequest* request, 127 net::URLRequest* request,
80 content::ResourceType resource_type) { 128 content::ResourceType resource_type) {
81 const content::ResourceRequestInfo* request_info = 129 const content::ResourceRequestInfo* request_info =
82 content::ResourceRequestInfo::ForRequest(request); 130 content::ResourceRequestInfo::ForRequest(request);
83 if (!request_info) 131 if (!request_info)
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 summary->has_validators = headers->HasValidators(); 351 summary->has_validators = headers->HasValidators();
304 // RFC 2616, section 14.9. 352 // RFC 2616, section 14.9.
305 summary->always_revalidate = 353 summary->always_revalidate =
306 headers->HasHeaderValue("cache-control", "no-cache") || 354 headers->HasHeaderValue("cache-control", "no-cache") ||
307 headers->HasHeaderValue("pragma", "no-cache") || 355 headers->HasHeaderValue("pragma", "no-cache") ||
308 headers->HasHeaderValue("vary", "*"); 356 headers->HasHeaderValue("vary", "*");
309 } 357 }
310 return true; 358 return true;
311 } 359 }
312 360
313 ResourcePrefetchPredictor::GetUrlVisitCountTask::GetUrlVisitCountTask( 361 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary(
314 const NavigationID& navigation_id, 362 const GURL& i_main_frame_url)
315 std::unique_ptr<PageRequestSummary> summary, 363 : main_frame_url(i_main_frame_url), initial_url(i_main_frame_url) {}
316 VisitInfoCallback callback)
317 : visit_count_(0),
318 navigation_id_(navigation_id),
319 summary_(std::move(summary)),
320 callback_(callback) {
321 DCHECK(summary_.get());
322 }
323
324 bool ResourcePrefetchPredictor::GetUrlVisitCountTask::RunOnDBThread(
325 history::HistoryBackend* backend,
326 history::HistoryDatabase* db) {
327 history::URLRow url_row;
328 if (db->GetRowForURL(navigation_id_.main_frame_url, &url_row))
329 visit_count_ = url_row.visit_count();
330 return true;
331 }
332
333 void ResourcePrefetchPredictor::GetUrlVisitCountTask::DoneRunOnMainThread() {
334 callback_.Run(visit_count_, navigation_id_, *summary_);
335 }
336
337 ResourcePrefetchPredictor::GetUrlVisitCountTask::~GetUrlVisitCountTask() {}
338 364
339 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary( 365 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary(
340 const GURL& i_initial_url) 366 const PageRequestSummary& other)
341 : initial_url(i_initial_url) {} 367 : main_frame_url(other.main_frame_url),
368 initial_url(other.initial_url),
369 subresource_requests(other.subresource_requests) {}
342 370
343 ResourcePrefetchPredictor::PageRequestSummary::~PageRequestSummary() {} 371 ResourcePrefetchPredictor::PageRequestSummary::~PageRequestSummary() {}
344 372
373 ResourcePrefetchPredictor::TestObserver::~TestObserver() {
374 ResetResourcePrefetchPredictor();
375 }
376
377 ResourcePrefetchPredictor::TestObserver::TestObserver(
378 ResourcePrefetchPredictor* predictor)
379 : predictor_(predictor) {
380 predictor_->SetObserverForTesting(this);
381 }
382
383 void ResourcePrefetchPredictor::TestObserver::ResetResourcePrefetchPredictor() {
384 if (predictor_) {
385 predictor_->observer_ = nullptr;
pasko 2016/10/24 17:59:38 yuck! does this compile because the inner class is
alexilin 2016/10/25 11:38:09 Then we have to make SetObserverForTesting method
pasko 2016/10/25 14:05:40 I believe this is how it is usually done in Chromi
alexilin 2016/10/25 15:10:58 Acknowledged.
386 predictor_ = nullptr;
387 }
388 }
389
345 //////////////////////////////////////////////////////////////////////////////// 390 ////////////////////////////////////////////////////////////////////////////////
346 // ResourcePrefetchPredictor. 391 // ResourcePrefetchPredictor.
347 392
348 ResourcePrefetchPredictor::ResourcePrefetchPredictor( 393 ResourcePrefetchPredictor::ResourcePrefetchPredictor(
349 const ResourcePrefetchPredictorConfig& config, 394 const ResourcePrefetchPredictorConfig& config,
350 Profile* profile) 395 Profile* profile)
351 : profile_(profile), 396 : profile_(profile),
397 observer_(nullptr),
352 config_(config), 398 config_(config),
353 initialization_state_(NOT_INITIALIZED), 399 initialization_state_(NOT_INITIALIZED),
354 tables_(PredictorDatabaseFactory::GetForProfile(profile) 400 tables_(PredictorDatabaseFactory::GetForProfile(profile)
355 ->resource_prefetch_tables()), 401 ->resource_prefetch_tables()),
356 history_service_observer_(this) { 402 history_service_observer_(this) {
357 DCHECK_CURRENTLY_ON(BrowserThread::UI); 403 DCHECK_CURRENTLY_ON(BrowserThread::UI);
358 404
359 // Some form of learning has to be enabled. 405 // Some form of learning has to be enabled.
360 DCHECK(config_.IsLearningEnabled()); 406 DCHECK(config_.IsLearningEnabled());
361 if (config_.IsURLPrefetchingEnabled(profile_)) 407 if (config_.IsURLPrefetchingEnabled(profile_))
362 DCHECK(config_.IsURLLearningEnabled()); 408 DCHECK(config_.IsURLLearningEnabled());
363 if (config_.IsHostPrefetchingEnabled(profile_)) 409 if (config_.IsHostPrefetchingEnabled(profile_))
364 DCHECK(config_.IsHostLearningEnabled()); 410 DCHECK(config_.IsHostLearningEnabled());
365 } 411 }
366 412
367 ResourcePrefetchPredictor::~ResourcePrefetchPredictor() { 413 ResourcePrefetchPredictor::~ResourcePrefetchPredictor() {
414 if (observer_)
415 observer_->ResetResourcePrefetchPredictor();
368 } 416 }
369 417
370 void ResourcePrefetchPredictor::RecordURLRequest( 418 void ResourcePrefetchPredictor::RecordURLRequest(
371 const URLRequestSummary& request) { 419 const URLRequestSummary& request) {
372 DCHECK_CURRENTLY_ON(BrowserThread::UI); 420 DCHECK_CURRENTLY_ON(BrowserThread::UI);
373 if (initialization_state_ != INITIALIZED) 421 if (initialization_state_ != INITIALIZED)
374 return; 422 return;
375 423
376 CHECK_EQ(request.resource_type, content::RESOURCE_TYPE_MAIN_FRAME); 424 CHECK_EQ(request.resource_type, content::RESOURCE_TYPE_MAIN_FRAME);
377 OnMainFrameRequest(request); 425 OnMainFrameRequest(request);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 // corresponding to the navigation has not been created yet. 460 // corresponding to the navigation has not been created yet.
413 if (!navigation_id.main_frame_url.is_empty()) 461 if (!navigation_id.main_frame_url.is_empty())
414 OnNavigationComplete(navigation_id); 462 OnNavigationComplete(navigation_id);
415 break; 463 break;
416 default: 464 default:
417 NOTREACHED() << "Unexpected initialization_state_: " 465 NOTREACHED() << "Unexpected initialization_state_: "
418 << initialization_state_; 466 << initialization_state_;
419 } 467 }
420 } 468 }
421 469
470 void ResourcePrefetchPredictor::StartPrefetching(const GURL& url) {
471 TRACE_EVENT1("browser", "ResourcePrefetchPredictor::StartPrefetching", "url",
472 url.spec());
473 if (!prefetch_manager_.get()) // Prefetching not enabled.
474 return;
475
476 std::vector<GURL> subresource_urls;
477 if (!GetPrefetchData(url, &subresource_urls)) {
478 // No prefetching data at host or URL level.
479 return;
480 }
481
482 BrowserThread::PostTask(
483 BrowserThread::IO, FROM_HERE,
484 base::Bind(&ResourcePrefetcherManager::MaybeAddPrefetch,
485 prefetch_manager_, url, subresource_urls));
486 }
487
488 void ResourcePrefetchPredictor::StopPrefetching(const GURL& url) {
489 TRACE_EVENT1("browser", "ResourcePrefetchPredictor::StopPrefetching", "url",
490 url.spec());
491 if (!prefetch_manager_.get()) // Not enabled.
492 return;
493
494 BrowserThread::PostTask(
495 BrowserThread::IO, FROM_HERE,
496 base::Bind(&ResourcePrefetcherManager::MaybeRemovePrefetch,
497 prefetch_manager_, url));
498 }
499
422 void ResourcePrefetchPredictor::Shutdown() { 500 void ResourcePrefetchPredictor::Shutdown() {
423 if (prefetch_manager_.get()) { 501 if (prefetch_manager_.get()) {
424 prefetch_manager_->ShutdownOnUIThread(); 502 prefetch_manager_->ShutdownOnUIThread();
425 prefetch_manager_ = NULL; 503 prefetch_manager_ = NULL;
426 } 504 }
427 history_service_observer_.RemoveAll(); 505 history_service_observer_.RemoveAll();
428 } 506 }
429 507
430 void ResourcePrefetchPredictor::OnMainFrameRequest( 508 void ResourcePrefetchPredictor::OnMainFrameRequest(
431 const URLRequestSummary& request) { 509 const URLRequestSummary& request) {
432 DCHECK_CURRENTLY_ON(BrowserThread::UI); 510 DCHECK_CURRENTLY_ON(BrowserThread::UI);
433 DCHECK_EQ(INITIALIZED, initialization_state_); 511 DCHECK_EQ(INITIALIZED, initialization_state_);
434 512
435 StartPrefetching(request.navigation_id.main_frame_url); 513 const GURL& main_frame_url = request.navigation_id.main_frame_url;
514 StartPrefetching(main_frame_url);
436 515
437 // Cleanup older navigations. 516 // Cleanup older navigations.
438 CleanupAbandonedNavigations(request.navigation_id); 517 CleanupAbandonedNavigations(request.navigation_id);
439 518
440 // New empty navigation entry. 519 // New empty navigation entry.
441 const GURL& initial_url = request.navigation_id.main_frame_url;
442 inflight_navigations_.insert( 520 inflight_navigations_.insert(
443 std::make_pair(request.navigation_id, 521 std::make_pair(request.navigation_id,
444 base::MakeUnique<PageRequestSummary>(initial_url))); 522 base::MakeUnique<PageRequestSummary>(main_frame_url)));
445 } 523 }
446 524
447 void ResourcePrefetchPredictor::OnMainFrameResponse( 525 void ResourcePrefetchPredictor::OnMainFrameResponse(
448 const URLRequestSummary& response) { 526 const URLRequestSummary& response) {
449 DCHECK_CURRENTLY_ON(BrowserThread::UI); 527 DCHECK_CURRENTLY_ON(BrowserThread::UI);
450 if (initialization_state_ != INITIALIZED) 528 if (initialization_state_ != INITIALIZED)
451 return; 529 return;
452 530
453 StopPrefetching(response.navigation_id.main_frame_url); 531 StopPrefetching(response.navigation_id.main_frame_url);
454 } 532 }
455 533
456 void ResourcePrefetchPredictor::OnMainFrameRedirect( 534 void ResourcePrefetchPredictor::OnMainFrameRedirect(
457 const URLRequestSummary& response) { 535 const URLRequestSummary& response) {
458 DCHECK_CURRENTLY_ON(BrowserThread::UI); 536 DCHECK_CURRENTLY_ON(BrowserThread::UI);
459 537
538 const GURL& main_frame_url = response.navigation_id.main_frame_url;
460 std::unique_ptr<PageRequestSummary> summary; 539 std::unique_ptr<PageRequestSummary> summary;
461 NavigationMap::iterator nav_it = 540 NavigationMap::iterator nav_it =
462 inflight_navigations_.find(response.navigation_id); 541 inflight_navigations_.find(response.navigation_id);
463 if (nav_it != inflight_navigations_.end()) { 542 if (nav_it != inflight_navigations_.end()) {
464 summary.reset(nav_it->second.release()); 543 summary.reset(nav_it->second.release());
465 inflight_navigations_.erase(nav_it); 544 inflight_navigations_.erase(nav_it);
466 } 545 }
467 546
468 // The redirect url may be empty if the URL was invalid. 547 // The redirect url may be empty if the URL was invalid.
469 if (response.redirect_url.is_empty()) 548 if (response.redirect_url.is_empty())
470 return; 549 return;
471 550
472 // If we lost the information about the first hop for some reason. 551 // If we lost the information about the first hop for some reason.
473 if (!summary) { 552 if (!summary) {
474 const GURL& initial_url = response.navigation_id.main_frame_url; 553 summary = base::MakeUnique<PageRequestSummary>(main_frame_url);
475 summary = base::MakeUnique<PageRequestSummary>(initial_url);
476 } 554 }
477 555
478 // A redirect will not lead to another OnMainFrameRequest call, so record the 556 // A redirect will not lead to another OnMainFrameRequest call, so record the
479 // redirect url as a new navigation id and save the initial url. 557 // redirect url as a new navigation id and save the initial url.
480 NavigationID navigation_id(response.navigation_id); 558 NavigationID navigation_id(response.navigation_id);
481 navigation_id.main_frame_url = response.redirect_url; 559 navigation_id.main_frame_url = response.redirect_url;
560 summary->main_frame_url = response.redirect_url;
482 inflight_navigations_.insert( 561 inflight_navigations_.insert(
483 std::make_pair(navigation_id, std::move(summary))); 562 std::make_pair(navigation_id, std::move(summary)));
484 } 563 }
485 564
486 void ResourcePrefetchPredictor::OnSubresourceResponse( 565 void ResourcePrefetchPredictor::OnSubresourceResponse(
487 const URLRequestSummary& response) { 566 const URLRequestSummary& response) {
488 DCHECK_CURRENTLY_ON(BrowserThread::UI); 567 DCHECK_CURRENTLY_ON(BrowserThread::UI);
489 568
490 NavigationMap::const_iterator nav_it = 569 NavigationMap::const_iterator nav_it =
491 inflight_navigations_.find(response.navigation_id); 570 inflight_navigations_.find(response.navigation_id);
492 if (nav_it == inflight_navigations_.end()) { 571 if (nav_it == inflight_navigations_.end()) {
493 return; 572 return;
494 } 573 }
495 574
496 nav_it->second->subresource_requests.push_back(response); 575 nav_it->second->subresource_requests.push_back(response);
497 } 576 }
498 577
499 void ResourcePrefetchPredictor::OnNavigationComplete( 578 void ResourcePrefetchPredictor::OnNavigationComplete(
500 const NavigationID& nav_id_without_timing_info) { 579 const NavigationID& nav_id_without_timing_info) {
501 DCHECK_CURRENTLY_ON(BrowserThread::UI); 580 DCHECK_CURRENTLY_ON(BrowserThread::UI);
502 581
503 NavigationMap::iterator nav_it = 582 NavigationMap::iterator nav_it =
504 inflight_navigations_.find(nav_id_without_timing_info); 583 inflight_navigations_.find(nav_id_without_timing_info);
505 if (nav_it == inflight_navigations_.end()) 584 if (nav_it == inflight_navigations_.end())
506 return; 585 return;
507 586
508 const NavigationID navigation_id(nav_it->first);
509
510 // Remove the navigation from the inflight navigations. 587 // Remove the navigation from the inflight navigations.
511 std::unique_ptr<PageRequestSummary> summary = std::move(nav_it->second); 588 std::unique_ptr<PageRequestSummary> summary = std::move(nav_it->second);
512 inflight_navigations_.erase(nav_it); 589 inflight_navigations_.erase(nav_it);
513 590
514 // Kick off history lookup to determine if we should record the URL. 591 // Kick off history lookup to determine if we should record the URL.
515 history::HistoryService* history_service = 592 history::HistoryService* history_service =
516 HistoryServiceFactory::GetForProfile(profile_, 593 HistoryServiceFactory::GetForProfile(profile_,
517 ServiceAccessType::EXPLICIT_ACCESS); 594 ServiceAccessType::EXPLICIT_ACCESS);
518 DCHECK(history_service); 595 DCHECK(history_service);
519 history_service->ScheduleDBTask( 596 history_service->ScheduleDBTask(
520 std::unique_ptr<history::HistoryDBTask>(new GetUrlVisitCountTask( 597 std::unique_ptr<history::HistoryDBTask>(new GetUrlVisitCountTask(
521 navigation_id, std::move(summary), 598 std::move(summary),
522 base::Bind(&ResourcePrefetchPredictor::OnVisitCountLookup, 599 base::Bind(&ResourcePrefetchPredictor::OnVisitCountLookup,
523 AsWeakPtr()))), 600 AsWeakPtr()))),
524 &history_lookup_consumer_); 601 &history_lookup_consumer_);
525 } 602 }
526 603
527 bool ResourcePrefetchPredictor::GetPrefetchData(const GURL& main_frame_url, 604 bool ResourcePrefetchPredictor::GetPrefetchData(const GURL& main_frame_url,
528 std::vector<GURL>* urls) { 605 std::vector<GURL>* urls) {
529 DCHECK(urls); 606 DCHECK(urls);
530 DCHECK(urls->empty()); 607 DCHECK(urls->empty());
531 bool use_url_data = config_.IsPrefetchingEnabled(profile_) ? 608 bool use_url_data = config_.IsPrefetchingEnabled(profile_) ?
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
579 resource.number_of_hits() < 656 resource.number_of_hits() <
580 config_.min_resource_hits_to_trigger_prefetch) 657 config_.min_resource_hits_to_trigger_prefetch)
581 continue; 658 continue;
582 659
583 urls->push_back(GURL(resource.resource_url())); 660 urls->push_back(GURL(resource.resource_url()));
584 } 661 }
585 662
586 return urls->size() > initial_size; 663 return urls->size() > initial_size;
587 } 664 }
588 665
589 void ResourcePrefetchPredictor::StartPrefetching(const GURL& url) {
590 TRACE_EVENT1("browser", "ResourcePrefetchPredictor::StartPrefetching", "url",
591 url.spec());
592 if (!prefetch_manager_.get()) // Prefetching not enabled.
593 return;
594
595 std::vector<GURL> subresource_urls;
596 if (!GetPrefetchData(url, &subresource_urls)) {
597 // No prefetching data at host or URL level.
598 return;
599 }
600
601 BrowserThread::PostTask(
602 BrowserThread::IO, FROM_HERE,
603 base::Bind(&ResourcePrefetcherManager::MaybeAddPrefetch,
604 prefetch_manager_, url, subresource_urls));
605 }
606
607 void ResourcePrefetchPredictor::StopPrefetching(const GURL& url) {
608 TRACE_EVENT1("browser", "ResourcePrefetchPredictor::StopPrefetching", "url",
609 url.spec());
610 if (!prefetch_manager_.get()) // Not enabled.
611 return;
612
613 BrowserThread::PostTask(
614 BrowserThread::IO, FROM_HERE,
615 base::Bind(&ResourcePrefetcherManager::MaybeRemovePrefetch,
616 prefetch_manager_, url));
617 }
618
619 void ResourcePrefetchPredictor::StartInitialization() { 666 void ResourcePrefetchPredictor::StartInitialization() {
620 DCHECK_CURRENTLY_ON(BrowserThread::UI); 667 DCHECK_CURRENTLY_ON(BrowserThread::UI);
621 668
622 DCHECK_EQ(NOT_INITIALIZED, initialization_state_); 669 DCHECK_EQ(NOT_INITIALIZED, initialization_state_);
623 initialization_state_ = INITIALIZING; 670 initialization_state_ = INITIALIZING;
624 671
625 // Create local caches using the database as loaded. 672 // Create local caches using the database as loaded.
626 auto url_data_map = base::MakeUnique<PrefetchDataMap>(); 673 auto url_data_map = base::MakeUnique<PrefetchDataMap>();
627 auto host_data_map = base::MakeUnique<PrefetchDataMap>(); 674 auto host_data_map = base::MakeUnique<PrefetchDataMap>();
628 auto url_redirect_data_map = base::MakeUnique<RedirectDataMap>(); 675 auto url_redirect_data_map = base::MakeUnique<RedirectDataMap>();
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 849
803 data_map->erase(key_to_delete); 850 data_map->erase(key_to_delete);
804 BrowserThread::PostTask( 851 BrowserThread::PostTask(
805 BrowserThread::DB, FROM_HERE, 852 BrowserThread::DB, FROM_HERE,
806 base::Bind( 853 base::Bind(
807 &ResourcePrefetchPredictorTables::DeleteSingleRedirectDataPoint, 854 &ResourcePrefetchPredictorTables::DeleteSingleRedirectDataPoint,
808 tables_, key_to_delete, key_type)); 855 tables_, key_to_delete, key_type));
809 } 856 }
810 857
811 void ResourcePrefetchPredictor::OnVisitCountLookup( 858 void ResourcePrefetchPredictor::OnVisitCountLookup(
812 size_t visit_count, 859 size_t url_visit_count,
813 const NavigationID& navigation_id,
814 const PageRequestSummary& summary) { 860 const PageRequestSummary& summary) {
815 DCHECK_CURRENTLY_ON(BrowserThread::UI); 861 DCHECK_CURRENTLY_ON(BrowserThread::UI);
816 862
817 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.HistoryVisitCountForUrl", 863 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.HistoryVisitCountForUrl",
818 visit_count); 864 url_visit_count);
819 865
820 // TODO(alexilin): make only one request to DB thread. 866 // TODO(alexilin): make only one request to DB thread.
821 867
822 // URL level data - merge only if we already saved the data, or it 868 // URL level data - merge only if we already saved the data, or it
823 // meets the cutoff requirement. 869 // meets the cutoff requirement.
824 const std::string url_spec = navigation_id.main_frame_url.spec(); 870 const std::string url_spec = summary.main_frame_url.spec();
825 bool already_tracking = url_table_cache_->find(url_spec) != 871 bool already_tracking = url_table_cache_->find(url_spec) !=
826 url_table_cache_->end(); 872 url_table_cache_->end();
827 bool should_track_url = already_tracking || 873 bool should_track_url =
828 (visit_count >= config_.min_url_visit_count); 874 already_tracking || (url_visit_count >= config_.min_url_visit_count);
829 875
830 if (should_track_url && config_.IsURLLearningEnabled()) { 876 if (should_track_url && config_.IsURLLearningEnabled()) {
831 LearnNavigation(url_spec, PREFETCH_KEY_TYPE_URL, 877 LearnNavigation(url_spec, PREFETCH_KEY_TYPE_URL,
832 summary.subresource_requests, config_.max_urls_to_track, 878 summary.subresource_requests, config_.max_urls_to_track,
833 url_table_cache_.get(), summary.initial_url.spec(), 879 url_table_cache_.get(), summary.initial_url.spec(),
834 url_redirect_table_cache_.get()); 880 url_redirect_table_cache_.get());
835 } 881 }
836 882
837 // Host level data - no cutoff, always learn the navigation if enabled. 883 // Host level data - no cutoff, always learn the navigation if enabled.
838 if (config_.IsHostLearningEnabled()) { 884 if (config_.IsHostLearningEnabled()) {
839 const std::string host = navigation_id.main_frame_url.host(); 885 const std::string host = summary.main_frame_url.host();
840 LearnNavigation(host, PREFETCH_KEY_TYPE_HOST, summary.subresource_requests, 886 LearnNavigation(host, PREFETCH_KEY_TYPE_HOST, summary.subresource_requests,
841 config_.max_hosts_to_track, host_table_cache_.get(), 887 config_.max_hosts_to_track, host_table_cache_.get(),
842 summary.initial_url.host(), 888 summary.initial_url.host(),
843 host_redirect_table_cache_.get()); 889 host_redirect_table_cache_.get());
844 } 890 }
891
892 if (observer_)
893 observer_->OnNavigationLearned(url_visit_count, summary);
845 } 894 }
846 895
847 void ResourcePrefetchPredictor::LearnNavigation( 896 void ResourcePrefetchPredictor::LearnNavigation(
848 const std::string& key, 897 const std::string& key,
849 PrefetchKeyType key_type, 898 PrefetchKeyType key_type,
850 const std::vector<URLRequestSummary>& new_resources, 899 const std::vector<URLRequestSummary>& new_resources,
851 size_t max_data_map_size, 900 size_t max_data_map_size,
852 PrefetchDataMap* data_map, 901 PrefetchDataMap* data_map,
853 const std::string& key_before_redirects, 902 const std::string& key_before_redirects,
854 RedirectDataMap* redirect_map) { 903 RedirectDataMap* redirect_map) {
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
1123 if (history_service->BackendLoaded()) { 1172 if (history_service->BackendLoaded()) {
1124 // HistoryService is already loaded. Continue with Initialization. 1173 // HistoryService is already loaded. Continue with Initialization.
1125 OnHistoryAndCacheLoaded(); 1174 OnHistoryAndCacheLoaded();
1126 return; 1175 return;
1127 } 1176 }
1128 DCHECK(!history_service_observer_.IsObserving(history_service)); 1177 DCHECK(!history_service_observer_.IsObserving(history_service));
1129 history_service_observer_.Add(history_service); 1178 history_service_observer_.Add(history_service);
1130 return; 1179 return;
1131 } 1180 }
1132 1181
1182 void ResourcePrefetchPredictor::SetObserverForTesting(TestObserver* observer) {
1183 if (observer_)
1184 observer_->ResetResourcePrefetchPredictor();
1185
1186 DCHECK(!observer_);
1187 DCHECK(observer->predictor_ == this);
pasko 2016/10/24 17:59:38 DCHECKs in tests should be avoided. Also, this che
alexilin 2016/10/25 11:38:09 What's wrong with DCHECKs in tests? It's one way t
pasko 2016/10/25 14:05:40 Style guide: Don't use these macros in tests, as t
alexilin 2016/10/25 15:10:58 Yes, you are right. Although I can't say that thi
pasko 2016/10/26 12:05:40 This is not too bad, but bad :) Within 4 lines of
alexilin 2016/10/26 13:09:59 Acknowledged.
1188 observer_ = observer;
1189 }
1190
1133 } // namespace predictors 1191 } // namespace predictors
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698