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 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 124 Predictor* Predictor::CreatePredictor(bool preconnect_enabled, | 125 Predictor* Predictor::CreatePredictor(bool preconnect_enabled, |
| 125 bool predictor_enabled, | 126 bool predictor_enabled, |
| 126 bool simple_shutdown) { | 127 bool simple_shutdown) { |
| 127 if (simple_shutdown) | 128 if (simple_shutdown) |
| 128 return new SimplePredictor(preconnect_enabled, predictor_enabled); | 129 return new SimplePredictor(preconnect_enabled, predictor_enabled); |
| 129 return new Predictor(preconnect_enabled, predictor_enabled); | 130 return new Predictor(preconnect_enabled, predictor_enabled); |
| 130 } | 131 } |
| 131 | 132 |
| 132 void Predictor::RegisterProfilePrefs( | 133 void Predictor::RegisterProfilePrefs( |
| 133 user_prefs::PrefRegistrySyncable* registry) { | 134 user_prefs::PrefRegistrySyncable* registry) { |
| 134 registry->RegisterListPref(prefs::kDnsPrefetchingStartupList); | 135 registry->RegisterListPref(prefs::kDnsPrefetchingStartupList, |
| 135 registry->RegisterListPref(prefs::kDnsPrefetchingHostReferralList); | 136 PrefRegistry::LOSSY_PREF); |
| 137 registry->RegisterListPref(prefs::kDnsPrefetchingHostReferralList, | |
| 138 PrefRegistry::LOSSY_PREF); | |
| 136 } | 139 } |
| 137 | 140 |
| 138 // --------------------- Start UI methods. ------------------------------------ | 141 // --------------------- Start UI methods. ------------------------------------ |
| 139 | 142 |
| 140 void Predictor::InitNetworkPredictor(PrefService* user_prefs, | 143 void Predictor::InitNetworkPredictor(PrefService* user_prefs, |
| 141 IOThread* io_thread, | 144 IOThread* io_thread, |
| 142 net::URLRequestContextGetter* getter, | 145 net::URLRequestContextGetter* getter, |
| 143 ProfileIOData* profile_io_data) { | 146 ProfileIOData* profile_io_data) { |
| 144 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 147 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 145 | 148 |
| 146 user_prefs_ = user_prefs; | 149 user_prefs_ = user_prefs; |
| 147 url_request_context_getter_ = getter; | 150 url_request_context_getter_ = getter; |
| 148 | 151 |
| 152 // base::WeakPtrFactory instances need to be created and destroyed | |
| 153 // on the same thread. Initialize the UI thread weak factory now. | |
| 154 ui_weak_factory_.reset(new base::WeakPtrFactory<Predictor>(this)); | |
|
Bernhard Bauer
2016/08/01 09:06:24
You could just initialize this in the constructor.
Charlie Harrison
2016/08/01 12:38:24
Done.
| |
| 155 | |
| 149 // Gather the list of hostnames to prefetch on startup. | 156 // Gather the list of hostnames to prefetch on startup. |
| 150 std::vector<GURL> urls = GetPredictedUrlListAtStartup(user_prefs); | 157 std::vector<GURL> urls = GetPredictedUrlListAtStartup(user_prefs); |
| 151 | 158 |
| 152 std::unique_ptr<base::ListValue> referral_list = base::WrapUnique( | 159 std::unique_ptr<base::ListValue> referral_list = base::WrapUnique( |
| 153 user_prefs->GetList(prefs::kDnsPrefetchingHostReferralList)->DeepCopy()); | 160 user_prefs->GetList(prefs::kDnsPrefetchingHostReferralList)->DeepCopy()); |
| 154 | 161 |
| 155 BrowserThread::PostTask( | 162 BrowserThread::PostTask( |
| 156 BrowserThread::IO, FROM_HERE, | 163 BrowserThread::IO, FROM_HERE, |
| 157 base::Bind(&Predictor::FinalizeInitializationOnIOThread, | 164 base::Bind(&Predictor::FinalizeInitializationOnIOThread, |
| 158 base::Unretained(this), urls, | 165 base::Unretained(this), urls, |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 303 } | 310 } |
| 304 | 311 |
| 305 if (urls.empty()) | 312 if (urls.empty()) |
| 306 urls.push_back(GURL("http://www.google.com:80")); | 313 urls.push_back(GURL("http://www.google.com:80")); |
| 307 | 314 |
| 308 return urls; | 315 return urls; |
| 309 } | 316 } |
| 310 | 317 |
| 311 void Predictor::DiscardAllResultsAndClearPrefsOnUIThread() { | 318 void Predictor::DiscardAllResultsAndClearPrefsOnUIThread() { |
| 312 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 319 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 313 BrowserThread::PostTask( | 320 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 314 BrowserThread::IO, FROM_HERE, | 321 base::Bind(&Predictor::DiscardAllResults, |
| 315 base::Bind(&Predictor::DiscardAllResults, weak_factory_->GetWeakPtr())); | 322 io_weak_factory_->GetWeakPtr())); |
| 316 ClearPrefsOnUIThread(); | 323 ClearPrefsOnUIThread(); |
| 317 } | 324 } |
| 318 | 325 |
| 319 void Predictor::ClearPrefsOnUIThread() { | 326 void Predictor::ClearPrefsOnUIThread() { |
| 320 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 327 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 321 user_prefs_->ClearPref(prefs::kDnsPrefetchingStartupList); | 328 user_prefs_->ClearPref(prefs::kDnsPrefetchingStartupList); |
| 322 user_prefs_->ClearPref(prefs::kDnsPrefetchingHostReferralList); | 329 user_prefs_->ClearPref(prefs::kDnsPrefetchingHostReferralList); |
| 323 } | 330 } |
| 324 | 331 |
| 325 void Predictor::set_max_queueing_delay(int max_queueing_delay_ms) { | 332 void Predictor::set_max_queueing_delay(int max_queueing_delay_ms) { |
| 326 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 333 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 327 g_max_queueing_delay_ms = max_queueing_delay_ms; | 334 g_max_queueing_delay_ms = max_queueing_delay_ms; |
| 328 } | 335 } |
| 329 | 336 |
| 330 void Predictor::set_max_parallel_resolves(size_t max_parallel_resolves) { | 337 void Predictor::set_max_parallel_resolves(size_t max_parallel_resolves) { |
| 331 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 338 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 332 g_max_parallel_resolves = max_parallel_resolves; | 339 g_max_parallel_resolves = max_parallel_resolves; |
| 333 } | 340 } |
| 334 | 341 |
| 335 void Predictor::ShutdownOnUIThread() { | 342 void Predictor::ShutdownOnUIThread() { |
| 336 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 343 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 344 ui_weak_factory_->InvalidateWeakPtrs(); | |
| 337 BrowserThread::PostTask( | 345 BrowserThread::PostTask( |
| 338 BrowserThread::IO, | 346 BrowserThread::IO, |
| 339 FROM_HERE, | 347 FROM_HERE, |
| 340 base::Bind(&Predictor::Shutdown, base::Unretained(this))); | 348 base::Bind(&Predictor::Shutdown, base::Unretained(this))); |
| 341 } | 349 } |
| 342 | 350 |
| 343 // ---------------------- End UI methods. ------------------------------------- | 351 // ---------------------- End UI methods. ------------------------------------- |
| 344 | 352 |
| 345 // --------------------- Start IO methods. ------------------------------------ | 353 // --------------------- Start IO methods. ------------------------------------ |
| 346 | 354 |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 597 profile_io_data_ = profile_io_data; | 605 profile_io_data_ = profile_io_data; |
| 598 initial_observer_.reset(new InitialObserver()); | 606 initial_observer_.reset(new InitialObserver()); |
| 599 | 607 |
| 600 net::URLRequestContext* context = | 608 net::URLRequestContext* context = |
| 601 url_request_context_getter_->GetURLRequestContext(); | 609 url_request_context_getter_->GetURLRequestContext(); |
| 602 transport_security_state_ = context->transport_security_state(); | 610 transport_security_state_ = context->transport_security_state(); |
| 603 ssl_config_service_ = context->ssl_config_service(); | 611 ssl_config_service_ = context->ssl_config_service(); |
| 604 proxy_service_ = context->proxy_service(); | 612 proxy_service_ = context->proxy_service(); |
| 605 | 613 |
| 606 // base::WeakPtrFactory instances need to be created and destroyed | 614 // base::WeakPtrFactory instances need to be created and destroyed |
| 607 // on the same thread. The predictor lives on the IO thread and will die | 615 // 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 | 616 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 | 617 |
| 613 // Prefetch these hostnames on startup. | 618 // Prefetch these hostnames on startup. |
| 614 DnsPrefetchMotivatedList(startup_urls, UrlInfo::STARTUP_LIST_MOTIVATED); | 619 DnsPrefetchMotivatedList(startup_urls, UrlInfo::STARTUP_LIST_MOTIVATED); |
| 615 | 620 |
| 616 DeserializeReferrers(*referral_list); | 621 DeserializeReferrers(*referral_list); |
| 617 | 622 |
| 618 LogStartupMetrics(); | 623 LogStartupMetrics(); |
| 619 } | 624 } |
| 620 | 625 |
| 621 //----------------------------------------------------------------------------- | 626 //----------------------------------------------------------------------------- |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 669 FROM_HERE, | 674 FROM_HERE, |
| 670 base::Bind(&Predictor::ResolveList, base::Unretained(this), | 675 base::Bind(&Predictor::ResolveList, base::Unretained(this), |
| 671 urls, motivation)); | 676 urls, motivation)); |
| 672 } | 677 } |
| 673 } | 678 } |
| 674 | 679 |
| 675 //----------------------------------------------------------------------------- | 680 //----------------------------------------------------------------------------- |
| 676 // Functions to handle saving of hostnames from one session to the next, to | 681 // Functions to handle saving of hostnames from one session to the next, to |
| 677 // expedite startup times. | 682 // expedite startup times. |
| 678 | 683 |
| 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() { | 684 void Predictor::SaveStateForNextStartup() { |
| 685 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 695 if (!predictor_enabled_) | 686 if (!predictor_enabled_) |
| 696 return; | 687 return; |
| 697 if (!CanPreresolveAndPreconnect()) | 688 if (!CanPreresolveAndPreconnect()) |
| 698 return; | 689 return; |
| 699 | 690 |
| 700 base::WaitableEvent completion( | 691 std::unique_ptr<base::ListValue> startup_list = base::WrapUnique( |
|
Bernhard Bauer
2016/08/01 09:06:24
You can just initialize the unique_ptr with the ra
Charlie Harrison
2016/08/01 12:38:24
Done.
| |
| 701 base::WaitableEvent::ResetPolicy::MANUAL, | 692 user_prefs_->GetList(prefs::kDnsPrefetchingStartupList)->DeepCopy()); |
| 702 base::WaitableEvent::InitialState::NOT_SIGNALED); | 693 std::unique_ptr<base::ListValue> referral_list = base::WrapUnique( |
| 694 user_prefs_->GetList(prefs::kDnsPrefetchingHostReferralList)->DeepCopy()); | |
| 695 // Get raw pointers to pass to the first task. Ownership of the unique_ptrs | |
| 696 // will be passed to the reply task. | |
| 697 base::ListValue* startup_list_raw = startup_list.get(); | |
| 698 base::ListValue* referral_list_raw = referral_list.get(); | |
| 703 | 699 |
| 704 ListPrefUpdate update_startup_list(user_prefs_, | 700 // It is safe to use unretained to the task on the IO thread, because this |
|
Bernhard Bauer
2016/08/01 09:06:24
If you still have the |io_weak_factory_|, you coul
Charlie Harrison
2016/08/01 12:38:24
No, that makes the code much clearer (+robust). No
| |
| 705 prefs::kDnsPrefetchingStartupList); | 701 // method is guaranteed to be called before ShutdownOnUIThread, which posts a |
| 706 ListPrefUpdate update_referral_list(user_prefs_, | 702 // task to shutdown on the IO thread. So WriteDnsPrefetchState is guaranteed |
| 707 prefs::kDnsPrefetchingHostReferralList); | 703 // to have access to valid data, because it will be called before Shutdown. |
| 708 if (BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 704 BrowserThread::PostTaskAndReply( |
| 709 SaveDnsPrefetchStateForNextStartupOnIOThread(update_startup_list.Get(), | 705 BrowserThread::IO, FROM_HERE, |
| 710 update_referral_list.Get(), | 706 base::Bind(&Predictor::WriteDnsPrefetchState, base::Unretained(this), |
| 711 &completion, this); | 707 startup_list_raw, referral_list_raw), |
| 712 } else { | 708 base::Bind(&Predictor::UpdatePrefsOnUIThread, |
| 713 bool posted = BrowserThread::PostTask( | 709 ui_weak_factory_->GetWeakPtr(), |
| 714 BrowserThread::IO, FROM_HERE, | 710 base::Passed(std::move(startup_list)), |
| 715 base::Bind(&SaveDnsPrefetchStateForNextStartupOnIOThread, | 711 base::Passed(std::move(referral_list)))); |
| 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 } | 712 } |
| 729 | 713 |
| 730 void Predictor::SaveDnsPrefetchStateForNextStartup( | 714 void Predictor::UpdatePrefsOnUIThread( |
| 731 base::ListValue* startup_list, | 715 std::unique_ptr<base::ListValue> startup_list, |
| 732 base::ListValue* referral_list, | 716 std::unique_ptr<base::ListValue> referral_list) { |
| 733 base::WaitableEvent* completion) { | 717 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 718 user_prefs_->Set(prefs::kDnsPrefetchingStartupList, *startup_list); | |
| 719 user_prefs_->Set(prefs::kDnsPrefetchingHostReferralList, *referral_list); | |
| 720 } | |
| 721 | |
| 722 void Predictor::WriteDnsPrefetchState(base::ListValue* startup_list, | |
| 723 base::ListValue* referral_list) { | |
| 734 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 724 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 735 if (initial_observer_.get()) | 725 if (initial_observer_.get()) |
| 736 initial_observer_->GetInitialDnsResolutionList(startup_list); | 726 initial_observer_->GetInitialDnsResolutionList(startup_list); |
| 737 | 727 |
| 738 SerializeReferrers(referral_list); | 728 SerializeReferrers(referral_list); |
| 739 | |
| 740 completion->Signal(); | |
| 741 } | 729 } |
| 742 | 730 |
| 743 void Predictor::PreconnectUrl(const GURL& url, | 731 void Predictor::PreconnectUrl(const GURL& url, |
| 744 const GURL& first_party_for_cookies, | 732 const GURL& first_party_for_cookies, |
| 745 UrlInfo::ResolutionMotivation motivation, | 733 UrlInfo::ResolutionMotivation motivation, |
| 746 bool allow_credentials, | 734 bool allow_credentials, |
| 747 int count) { | 735 int count) { |
| 748 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || | 736 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
| 749 BrowserThread::CurrentlyOn(BrowserThread::IO)); | 737 BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 750 | 738 |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1025 info->SetAssignedState(); | 1013 info->SetAssignedState(); |
| 1026 | 1014 |
| 1027 if (CongestionControlPerformed(info)) { | 1015 if (CongestionControlPerformed(info)) { |
| 1028 DCHECK(work_queue_.IsEmpty()); | 1016 DCHECK(work_queue_.IsEmpty()); |
| 1029 return; | 1017 return; |
| 1030 } | 1018 } |
| 1031 | 1019 |
| 1032 int status = | 1020 int status = |
| 1033 content::PreresolveUrl(profile_io_data_->GetResourceContext(), url, | 1021 content::PreresolveUrl(profile_io_data_->GetResourceContext(), url, |
| 1034 base::Bind(&Predictor::OnLookupFinished, | 1022 base::Bind(&Predictor::OnLookupFinished, |
| 1035 weak_factory_->GetWeakPtr(), url)); | 1023 io_weak_factory_->GetWeakPtr(), url)); |
| 1036 if (status == net::ERR_IO_PENDING) { | 1024 if (status == net::ERR_IO_PENDING) { |
| 1037 // Will complete asynchronously. | 1025 // Will complete asynchronously. |
| 1038 num_pending_lookups_++; | 1026 num_pending_lookups_++; |
| 1039 peak_pending_lookups_ = | 1027 peak_pending_lookups_ = |
| 1040 std::max(peak_pending_lookups_, num_pending_lookups_); | 1028 std::max(peak_pending_lookups_, num_pending_lookups_); |
| 1041 } else { | 1029 } else { |
| 1042 // Completed synchronously (was already cached by HostResolver), or else | 1030 // Completed synchronously (was already cached by HostResolver), or else |
| 1043 // there was (equivalently) some network error that prevents us from | 1031 // there was (equivalently) some network error that prevents us from |
| 1044 // finding the name. Status net::OK means it was "found." | 1032 // finding the name. Status net::OK means it was "found." |
| 1045 LookupFinished(url, status == net::OK); | 1033 LookupFinished(url, status == net::OK); |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1222 } | 1210 } |
| 1223 | 1211 |
| 1224 void SimplePredictor::ShutdownOnUIThread() { | 1212 void SimplePredictor::ShutdownOnUIThread() { |
| 1225 SetShutdown(true); | 1213 SetShutdown(true); |
| 1226 } | 1214 } |
| 1227 | 1215 |
| 1228 bool SimplePredictor::CanPrefetchAndPrerender() const { return true; } | 1216 bool SimplePredictor::CanPrefetchAndPrerender() const { return true; } |
| 1229 bool SimplePredictor::CanPreresolveAndPreconnect() const { return true; } | 1217 bool SimplePredictor::CanPreresolveAndPreconnect() const { return true; } |
| 1230 | 1218 |
| 1231 } // namespace chrome_browser_net | 1219 } // namespace chrome_browser_net |
| OLD | NEW |