Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/net/predictor.h" | 5 #include "chrome/browser/net/predictor.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 #include <iterator> | 9 #include <iterator> |
| 10 #include <set> | 10 #include <set> |
| 11 #include <sstream> | 11 #include <sstream> |
| 12 #include <utility> | 12 #include <utility> |
| 13 | 13 |
| 14 #include "base/bind.h" | 14 #include "base/bind.h" |
| 15 #include "base/callback.h" | |
| 15 #include "base/compiler_specific.h" | 16 #include "base/compiler_specific.h" |
| 16 #include "base/containers/mru_cache.h" | 17 #include "base/containers/mru_cache.h" |
| 17 #include "base/location.h" | 18 #include "base/location.h" |
| 18 #include "base/logging.h" | 19 #include "base/logging.h" |
| 19 #include "base/macros.h" | 20 #include "base/macros.h" |
| 20 #include "base/memory/ptr_util.h" | 21 #include "base/memory/ptr_util.h" |
| 21 #include "base/metrics/histogram.h" | 22 #include "base/metrics/histogram.h" |
| 22 #include "base/single_thread_task_runner.h" | 23 #include "base/single_thread_task_runner.h" |
| 23 #include "base/stl_util.h" | 24 #include "base/stl_util.h" |
| 24 #include "base/strings/stringprintf.h" | 25 #include "base/strings/stringprintf.h" |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 104 max_dns_queue_delay_( | 105 max_dns_queue_delay_( |
| 105 TimeDelta::FromMilliseconds(g_max_queueing_delay_ms)), | 106 TimeDelta::FromMilliseconds(g_max_queueing_delay_ms)), |
| 106 transport_security_state_(nullptr), | 107 transport_security_state_(nullptr), |
| 107 ssl_config_service_(nullptr), | 108 ssl_config_service_(nullptr), |
| 108 proxy_service_(nullptr), | 109 proxy_service_(nullptr), |
| 109 preconnect_enabled_(preconnect_enabled), | 110 preconnect_enabled_(preconnect_enabled), |
| 110 consecutive_omnibox_preconnect_count_(0), | 111 consecutive_omnibox_preconnect_count_(0), |
| 111 referrers_(kMaxReferrers), | 112 referrers_(kMaxReferrers), |
| 112 observer_(nullptr), | 113 observer_(nullptr), |
| 113 timed_cache_(new TimedCache(base::TimeDelta::FromSeconds( | 114 timed_cache_(new TimedCache(base::TimeDelta::FromSeconds( |
| 114 kMaxUnusedSocketLifetimeSecondsWithoutAGet))) { | 115 kMaxUnusedSocketLifetimeSecondsWithoutAGet))), |
| 116 ui_weak_factory_(new base::WeakPtrFactory<Predictor>(this)) { | |
| 115 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 117 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 116 } | 118 } |
| 117 | 119 |
| 118 Predictor::~Predictor() { | 120 Predictor::~Predictor() { |
| 119 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 121 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 120 DCHECK(shutdown_); | 122 DCHECK(shutdown_); |
| 121 } | 123 } |
| 122 | 124 |
| 123 // static | 125 // static |
| 124 Predictor* Predictor::CreatePredictor(bool preconnect_enabled, | 126 Predictor* Predictor::CreatePredictor(bool preconnect_enabled, |
| 125 bool predictor_enabled, | 127 bool predictor_enabled, |
| 126 bool simple_shutdown) { | 128 bool simple_shutdown) { |
| 127 if (simple_shutdown) | 129 if (simple_shutdown) |
| 128 return new SimplePredictor(preconnect_enabled, predictor_enabled); | 130 return new SimplePredictor(preconnect_enabled, predictor_enabled); |
| 129 return new Predictor(preconnect_enabled, predictor_enabled); | 131 return new Predictor(preconnect_enabled, predictor_enabled); |
| 130 } | 132 } |
| 131 | 133 |
| 132 void Predictor::RegisterProfilePrefs( | 134 void Predictor::RegisterProfilePrefs( |
| 133 user_prefs::PrefRegistrySyncable* registry) { | 135 user_prefs::PrefRegistrySyncable* registry) { |
| 134 registry->RegisterListPref(prefs::kDnsPrefetchingStartupList); | 136 registry->RegisterListPref(prefs::kDnsPrefetchingStartupList, |
| 135 registry->RegisterListPref(prefs::kDnsPrefetchingHostReferralList); | 137 PrefRegistry::LOSSY_PREF); |
| 138 registry->RegisterListPref(prefs::kDnsPrefetchingHostReferralList, | |
| 139 PrefRegistry::LOSSY_PREF); | |
| 136 } | 140 } |
| 137 | 141 |
| 138 // --------------------- Start UI methods. ------------------------------------ | 142 // --------------------- Start UI methods. ------------------------------------ |
| 139 | 143 |
| 140 void Predictor::InitNetworkPredictor(PrefService* user_prefs, | 144 void Predictor::InitNetworkPredictor(PrefService* user_prefs, |
| 141 IOThread* io_thread, | 145 IOThread* io_thread, |
| 142 net::URLRequestContextGetter* getter, | 146 net::URLRequestContextGetter* getter, |
| 143 ProfileIOData* profile_io_data) { | 147 ProfileIOData* profile_io_data) { |
| 144 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 148 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 145 | 149 |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 303 } | 307 } |
| 304 | 308 |
| 305 if (urls.empty()) | 309 if (urls.empty()) |
| 306 urls.push_back(GURL("http://www.google.com:80")); | 310 urls.push_back(GURL("http://www.google.com:80")); |
| 307 | 311 |
| 308 return urls; | 312 return urls; |
| 309 } | 313 } |
| 310 | 314 |
| 311 void Predictor::DiscardAllResultsAndClearPrefsOnUIThread() { | 315 void Predictor::DiscardAllResultsAndClearPrefsOnUIThread() { |
| 312 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 316 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 313 BrowserThread::PostTask( | 317 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 314 BrowserThread::IO, FROM_HERE, | 318 base::Bind(&Predictor::DiscardAllResults, |
| 315 base::Bind(&Predictor::DiscardAllResults, weak_factory_->GetWeakPtr())); | 319 io_weak_factory_->GetWeakPtr())); |
| 316 ClearPrefsOnUIThread(); | 320 ClearPrefsOnUIThread(); |
| 317 } | 321 } |
| 318 | 322 |
| 319 void Predictor::ClearPrefsOnUIThread() { | 323 void Predictor::ClearPrefsOnUIThread() { |
| 320 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 324 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 321 user_prefs_->ClearPref(prefs::kDnsPrefetchingStartupList); | 325 user_prefs_->ClearPref(prefs::kDnsPrefetchingStartupList); |
| 322 user_prefs_->ClearPref(prefs::kDnsPrefetchingHostReferralList); | 326 user_prefs_->ClearPref(prefs::kDnsPrefetchingHostReferralList); |
| 323 } | 327 } |
| 324 | 328 |
| 325 void Predictor::set_max_queueing_delay(int max_queueing_delay_ms) { | 329 void Predictor::set_max_queueing_delay(int max_queueing_delay_ms) { |
| 326 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 330 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 327 g_max_queueing_delay_ms = max_queueing_delay_ms; | 331 g_max_queueing_delay_ms = max_queueing_delay_ms; |
| 328 } | 332 } |
| 329 | 333 |
| 330 void Predictor::set_max_parallel_resolves(size_t max_parallel_resolves) { | 334 void Predictor::set_max_parallel_resolves(size_t max_parallel_resolves) { |
| 331 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 335 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 332 g_max_parallel_resolves = max_parallel_resolves; | 336 g_max_parallel_resolves = max_parallel_resolves; |
| 333 } | 337 } |
| 334 | 338 |
| 335 void Predictor::ShutdownOnUIThread() { | 339 void Predictor::ShutdownOnUIThread() { |
| 336 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 340 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 341 ui_weak_factory_->InvalidateWeakPtrs(); | |
| 337 BrowserThread::PostTask( | 342 BrowserThread::PostTask( |
| 338 BrowserThread::IO, | 343 BrowserThread::IO, |
| 339 FROM_HERE, | 344 FROM_HERE, |
| 340 base::Bind(&Predictor::Shutdown, base::Unretained(this))); | 345 base::Bind(&Predictor::Shutdown, base::Unretained(this))); |
| 341 } | 346 } |
| 342 | 347 |
| 343 // ---------------------- End UI methods. ------------------------------------- | 348 // ---------------------- End UI methods. ------------------------------------- |
| 344 | 349 |
| 345 // --------------------- Start IO methods. ------------------------------------ | 350 // --------------------- Start IO methods. ------------------------------------ |
| 346 | 351 |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 597 profile_io_data_ = profile_io_data; | 602 profile_io_data_ = profile_io_data; |
| 598 initial_observer_.reset(new InitialObserver()); | 603 initial_observer_.reset(new InitialObserver()); |
| 599 | 604 |
| 600 net::URLRequestContext* context = | 605 net::URLRequestContext* context = |
| 601 url_request_context_getter_->GetURLRequestContext(); | 606 url_request_context_getter_->GetURLRequestContext(); |
| 602 transport_security_state_ = context->transport_security_state(); | 607 transport_security_state_ = context->transport_security_state(); |
| 603 ssl_config_service_ = context->ssl_config_service(); | 608 ssl_config_service_ = context->ssl_config_service(); |
| 604 proxy_service_ = context->proxy_service(); | 609 proxy_service_ = context->proxy_service(); |
| 605 | 610 |
| 606 // base::WeakPtrFactory instances need to be created and destroyed | 611 // base::WeakPtrFactory instances need to be created and destroyed |
| 607 // on the same thread. The predictor lives on the IO thread and will die | 612 // on the same thread. Initialize the IO thread weak factory now. |
| 608 // from there so now that we're on the IO thread we need to properly | 613 io_weak_factory_.reset(new base::WeakPtrFactory<Predictor>(this)); |
| 609 // initialize the base::WeakPtrFactory. | |
| 610 // TODO(groby): Check if WeakPtrFactory has the same constraint. | |
| 611 weak_factory_.reset(new base::WeakPtrFactory<Predictor>(this)); | |
| 612 | 614 |
| 613 // Prefetch these hostnames on startup. | 615 // Prefetch these hostnames on startup. |
| 614 DnsPrefetchMotivatedList(startup_urls, UrlInfo::STARTUP_LIST_MOTIVATED); | 616 DnsPrefetchMotivatedList(startup_urls, UrlInfo::STARTUP_LIST_MOTIVATED); |
| 615 | 617 |
| 616 DeserializeReferrers(*referral_list); | 618 DeserializeReferrers(*referral_list); |
| 617 | 619 |
| 618 LogStartupMetrics(); | 620 LogStartupMetrics(); |
| 619 } | 621 } |
| 620 | 622 |
| 621 //----------------------------------------------------------------------------- | 623 //----------------------------------------------------------------------------- |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 669 FROM_HERE, | 671 FROM_HERE, |
| 670 base::Bind(&Predictor::ResolveList, base::Unretained(this), | 672 base::Bind(&Predictor::ResolveList, base::Unretained(this), |
| 671 urls, motivation)); | 673 urls, motivation)); |
| 672 } | 674 } |
| 673 } | 675 } |
| 674 | 676 |
| 675 //----------------------------------------------------------------------------- | 677 //----------------------------------------------------------------------------- |
| 676 // Functions to handle saving of hostnames from one session to the next, to | 678 // Functions to handle saving of hostnames from one session to the next, to |
| 677 // expedite startup times. | 679 // expedite startup times. |
| 678 | 680 |
| 679 static void SaveDnsPrefetchStateForNextStartupOnIOThread( | |
| 680 base::ListValue* startup_list, | |
| 681 base::ListValue* referral_list, | |
| 682 base::WaitableEvent* completion, | |
| 683 Predictor* predictor) { | |
| 684 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 685 | |
| 686 if (nullptr == predictor) { | |
| 687 completion->Signal(); | |
| 688 return; | |
| 689 } | |
| 690 predictor->SaveDnsPrefetchStateForNextStartup(startup_list, referral_list, | |
| 691 completion); | |
| 692 } | |
| 693 | |
| 694 void Predictor::SaveStateForNextStartup() { | 681 void Predictor::SaveStateForNextStartup() { |
| 682 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 695 if (!predictor_enabled_) | 683 if (!predictor_enabled_) |
| 696 return; | 684 return; |
| 697 if (!CanPreresolveAndPreconnect()) | 685 if (!CanPreresolveAndPreconnect()) |
| 698 return; | 686 return; |
| 699 | 687 |
| 700 base::WaitableEvent completion( | 688 std::unique_ptr<base::ListValue> startup_list( |
| 701 base::WaitableEvent::ResetPolicy::MANUAL, | 689 user_prefs_->GetList(prefs::kDnsPrefetchingStartupList)->DeepCopy()); |
|
mmenke
2016/08/01 15:11:20
I'm not following this code. WriteDnsPrefetchStat
Bernhard Bauer
2016/08/01 15:18:52
Huh, you're right! Which makes me wonder why this
Charlie Harrison
2016/08/01 15:20:03
Yeah, good catch Matt. I think we can just initial
mmenke
2016/08/01 15:27:48
Or could just create them on the IO thread. Guess
Charlie Harrison
2016/08/01 15:34:23
Given the double hop, I think I prefer initializin
| |
| 702 base::WaitableEvent::InitialState::NOT_SIGNALED); | 690 std::unique_ptr<base::ListValue> referral_list( |
| 691 user_prefs_->GetList(prefs::kDnsPrefetchingHostReferralList)->DeepCopy()); | |
| 692 // Get raw pointers to pass to the first task. Ownership of the unique_ptrs | |
| 693 // will be passed to the reply task. | |
| 694 base::ListValue* startup_list_raw = startup_list.get(); | |
| 695 base::ListValue* referral_list_raw = referral_list.get(); | |
| 703 | 696 |
| 704 ListPrefUpdate update_startup_list(user_prefs_, | 697 BrowserThread::PostTaskAndReply( |
| 705 prefs::kDnsPrefetchingStartupList); | 698 BrowserThread::IO, FROM_HERE, |
| 706 ListPrefUpdate update_referral_list(user_prefs_, | 699 base::Bind(&Predictor::WriteDnsPrefetchState, |
| 707 prefs::kDnsPrefetchingHostReferralList); | 700 io_weak_factory_->GetWeakPtr(), startup_list_raw, |
| 708 if (BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 701 referral_list_raw), |
| 709 SaveDnsPrefetchStateForNextStartupOnIOThread(update_startup_list.Get(), | 702 base::Bind(&Predictor::UpdatePrefsOnUIThread, |
| 710 update_referral_list.Get(), | 703 ui_weak_factory_->GetWeakPtr(), |
| 711 &completion, this); | 704 base::Passed(std::move(startup_list)), |
| 712 } else { | 705 base::Passed(std::move(referral_list)))); |
| 713 bool posted = BrowserThread::PostTask( | |
| 714 BrowserThread::IO, FROM_HERE, | |
| 715 base::Bind(&SaveDnsPrefetchStateForNextStartupOnIOThread, | |
| 716 update_startup_list.Get(), update_referral_list.Get(), | |
| 717 &completion, this)); | |
| 718 | |
| 719 // TODO(jar): Synchronous waiting for the IO thread is a potential source | |
| 720 // to deadlocks and should be investigated. See http://crbug.com/78451. | |
| 721 DCHECK(posted); | |
| 722 if (posted) { | |
| 723 // http://crbug.com/124954 | |
| 724 base::ThreadRestrictions::ScopedAllowWait allow_wait; | |
| 725 completion.Wait(); | |
| 726 } | |
| 727 } | |
| 728 } | 706 } |
| 729 | 707 |
| 730 void Predictor::SaveDnsPrefetchStateForNextStartup( | 708 void Predictor::UpdatePrefsOnUIThread( |
| 731 base::ListValue* startup_list, | 709 std::unique_ptr<base::ListValue> startup_list, |
| 732 base::ListValue* referral_list, | 710 std::unique_ptr<base::ListValue> referral_list) { |
| 733 base::WaitableEvent* completion) { | 711 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 712 user_prefs_->Set(prefs::kDnsPrefetchingStartupList, *startup_list); | |
| 713 user_prefs_->Set(prefs::kDnsPrefetchingHostReferralList, *referral_list); | |
| 714 } | |
| 715 | |
| 716 void Predictor::WriteDnsPrefetchState(base::ListValue* startup_list, | |
| 717 base::ListValue* referral_list) { | |
| 734 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 718 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 735 if (initial_observer_.get()) | 719 if (initial_observer_.get()) |
| 736 initial_observer_->GetInitialDnsResolutionList(startup_list); | 720 initial_observer_->GetInitialDnsResolutionList(startup_list); |
| 737 | 721 |
| 738 SerializeReferrers(referral_list); | 722 SerializeReferrers(referral_list); |
| 739 | |
| 740 completion->Signal(); | |
| 741 } | 723 } |
| 742 | 724 |
| 743 void Predictor::PreconnectUrl(const GURL& url, | 725 void Predictor::PreconnectUrl(const GURL& url, |
| 744 const GURL& first_party_for_cookies, | 726 const GURL& first_party_for_cookies, |
| 745 UrlInfo::ResolutionMotivation motivation, | 727 UrlInfo::ResolutionMotivation motivation, |
| 746 bool allow_credentials, | 728 bool allow_credentials, |
| 747 int count) { | 729 int count) { |
| 748 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || | 730 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
| 749 BrowserThread::CurrentlyOn(BrowserThread::IO)); | 731 BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 750 | 732 |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1025 info->SetAssignedState(); | 1007 info->SetAssignedState(); |
| 1026 | 1008 |
| 1027 if (CongestionControlPerformed(info)) { | 1009 if (CongestionControlPerformed(info)) { |
| 1028 DCHECK(work_queue_.IsEmpty()); | 1010 DCHECK(work_queue_.IsEmpty()); |
| 1029 return; | 1011 return; |
| 1030 } | 1012 } |
| 1031 | 1013 |
| 1032 int status = | 1014 int status = |
| 1033 content::PreresolveUrl(profile_io_data_->GetResourceContext(), url, | 1015 content::PreresolveUrl(profile_io_data_->GetResourceContext(), url, |
| 1034 base::Bind(&Predictor::OnLookupFinished, | 1016 base::Bind(&Predictor::OnLookupFinished, |
| 1035 weak_factory_->GetWeakPtr(), url)); | 1017 io_weak_factory_->GetWeakPtr(), url)); |
| 1036 if (status == net::ERR_IO_PENDING) { | 1018 if (status == net::ERR_IO_PENDING) { |
| 1037 // Will complete asynchronously. | 1019 // Will complete asynchronously. |
| 1038 num_pending_lookups_++; | 1020 num_pending_lookups_++; |
| 1039 peak_pending_lookups_ = | 1021 peak_pending_lookups_ = |
| 1040 std::max(peak_pending_lookups_, num_pending_lookups_); | 1022 std::max(peak_pending_lookups_, num_pending_lookups_); |
| 1041 } else { | 1023 } else { |
| 1042 // Completed synchronously (was already cached by HostResolver), or else | 1024 // Completed synchronously (was already cached by HostResolver), or else |
| 1043 // there was (equivalently) some network error that prevents us from | 1025 // there was (equivalently) some network error that prevents us from |
| 1044 // finding the name. Status net::OK means it was "found." | 1026 // finding the name. Status net::OK means it was "found." |
| 1045 LookupFinished(url, status == net::OK); | 1027 LookupFinished(url, status == net::OK); |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1222 } | 1204 } |
| 1223 | 1205 |
| 1224 void SimplePredictor::ShutdownOnUIThread() { | 1206 void SimplePredictor::ShutdownOnUIThread() { |
| 1225 SetShutdown(true); | 1207 SetShutdown(true); |
| 1226 } | 1208 } |
| 1227 | 1209 |
| 1228 bool SimplePredictor::CanPrefetchAndPrerender() const { return true; } | 1210 bool SimplePredictor::CanPrefetchAndPrerender() const { return true; } |
| 1229 bool SimplePredictor::CanPreresolveAndPreconnect() const { return true; } | 1211 bool SimplePredictor::CanPreresolveAndPreconnect() const { return true; } |
| 1230 | 1212 |
| 1231 } // namespace chrome_browser_net | 1213 } // namespace chrome_browser_net |
| OLD | NEW |