| 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 <set> | 9 #include <set> |
| 10 #include <sstream> | 10 #include <sstream> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/compiler_specific.h" | 13 #include "base/compiler_specific.h" |
| 14 #include "base/containers/mru_cache.h" | 14 #include "base/containers/mru_cache.h" |
| 15 #include "base/feature_list.h" | 15 #include "base/feature_list.h" |
| 16 #include "base/location.h" | 16 #include "base/location.h" |
| 17 #include "base/logging.h" | 17 #include "base/logging.h" |
| 18 #include "base/macros.h" | 18 #include "base/macros.h" |
| 19 #include "base/metrics/histogram.h" | 19 #include "base/metrics/histogram.h" |
| 20 #include "base/single_thread_task_runner.h" | 20 #include "base/single_thread_task_runner.h" |
| 21 #include "base/stl_util.h" | 21 #include "base/stl_util.h" |
| 22 #include "base/strings/string_split.h" | 22 #include "base/strings/string_split.h" |
| 23 #include "base/strings/string_util.h" | 23 #include "base/strings/string_util.h" |
| 24 #include "base/strings/stringprintf.h" | |
| 25 #include "base/synchronization/waitable_event.h" | 24 #include "base/synchronization/waitable_event.h" |
| 26 #include "base/threading/thread_restrictions.h" | 25 #include "base/threading/thread_restrictions.h" |
| 27 #include "base/threading/thread_task_runner_handle.h" | 26 #include "base/threading/thread_task_runner_handle.h" |
| 28 #include "base/time/time.h" | 27 #include "base/time/time.h" |
| 29 #include "base/values.h" | 28 #include "base/values.h" |
| 30 #include "chrome/browser/io_thread.h" | 29 #include "chrome/browser/io_thread.h" |
| 31 #include "chrome/browser/prefs/session_startup_pref.h" | 30 #include "chrome/browser/prefs/session_startup_pref.h" |
| 32 #include "chrome/browser/profiles/profile_io_data.h" | 31 #include "chrome/browser/profiles/profile_io_data.h" |
| 33 #include "chrome/common/chrome_switches.h" | 32 #include "chrome/common/chrome_switches.h" |
| 34 #include "chrome/common/pref_names.h" | 33 #include "chrome/common/pref_names.h" |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 | 96 |
| 98 static int g_max_queueing_delay_ms = | 97 static int g_max_queueing_delay_ms = |
| 99 Predictor::kMaxSpeculativeResolveQueueDelayMs; | 98 Predictor::kMaxSpeculativeResolveQueueDelayMs; |
| 100 static size_t g_max_parallel_resolves = | 99 static size_t g_max_parallel_resolves = |
| 101 Predictor::kMaxSpeculativeParallelResolves; | 100 Predictor::kMaxSpeculativeParallelResolves; |
| 102 | 101 |
| 103 // A version number for prefs that are saved. This should be incremented when | 102 // A version number for prefs that are saved. This should be incremented when |
| 104 // we change the format so that we discard old data. | 103 // we change the format so that we discard old data. |
| 105 static const int kPredictorStartupFormatVersion = 1; | 104 static const int kPredictorStartupFormatVersion = 1; |
| 106 | 105 |
| 107 class Predictor::LookupRequest { | |
| 108 public: | |
| 109 LookupRequest(Predictor* predictor, | |
| 110 net::HostResolver* host_resolver, | |
| 111 const GURL& url) | |
| 112 : predictor_(predictor), | |
| 113 url_(url), | |
| 114 resolver_(host_resolver) { | |
| 115 } | |
| 116 | |
| 117 // Return underlying network resolver status. | |
| 118 // net::OK ==> Host was found synchronously. | |
| 119 // net:ERR_IO_PENDING ==> Network will callback later with result. | |
| 120 // anything else ==> Host was not found synchronously. | |
| 121 int Start() { | |
| 122 net::HostResolver::RequestInfo resolve_info( | |
| 123 net::HostPortPair::FromURL(url_)); | |
| 124 | |
| 125 // Make a note that this is a speculative resolve request. This allows us | |
| 126 // to separate it from real navigations in the observer's callback, and | |
| 127 // lets the HostResolver know it can de-prioritize it. | |
| 128 resolve_info.set_is_speculative(true); | |
| 129 return resolver_.Resolve( | |
| 130 resolve_info, | |
| 131 net::DEFAULT_PRIORITY, | |
| 132 &addresses_, | |
| 133 base::Bind(&LookupRequest::OnLookupFinished, base::Unretained(this)), | |
| 134 net::BoundNetLog()); | |
| 135 } | |
| 136 | |
| 137 private: | |
| 138 void OnLookupFinished(int result) { | |
| 139 predictor_->OnLookupFinished(this, url_, result == net::OK); | |
| 140 } | |
| 141 | |
| 142 Predictor* predictor_; // The predictor which started us. | |
| 143 | |
| 144 const GURL url_; // Hostname to resolve. | |
| 145 net::SingleRequestHostResolver resolver_; | |
| 146 net::AddressList addresses_; | |
| 147 | |
| 148 DISALLOW_COPY_AND_ASSIGN(LookupRequest); | |
| 149 }; | |
| 150 | |
| 151 Predictor::Predictor(bool preconnect_enabled, bool predictor_enabled) | 106 Predictor::Predictor(bool preconnect_enabled, bool predictor_enabled) |
| 152 : url_request_context_getter_(NULL), | 107 : url_request_context_getter_(NULL), |
| 153 predictor_enabled_(predictor_enabled), | 108 predictor_enabled_(predictor_enabled), |
| 154 user_prefs_(NULL), | 109 user_prefs_(NULL), |
| 155 profile_io_data_(NULL), | 110 profile_io_data_(NULL), |
| 111 num_pending_lookups_(0), |
| 156 peak_pending_lookups_(0), | 112 peak_pending_lookups_(0), |
| 157 shutdown_(false), | 113 shutdown_(false), |
| 158 max_concurrent_dns_lookups_(g_max_parallel_resolves), | 114 max_concurrent_dns_lookups_(g_max_parallel_resolves), |
| 159 max_dns_queue_delay_( | 115 max_dns_queue_delay_( |
| 160 TimeDelta::FromMilliseconds(g_max_queueing_delay_ms)), | 116 TimeDelta::FromMilliseconds(g_max_queueing_delay_ms)), |
| 161 host_resolver_(NULL), | |
| 162 transport_security_state_(NULL), | 117 transport_security_state_(NULL), |
| 163 ssl_config_service_(NULL), | 118 ssl_config_service_(NULL), |
| 164 proxy_service_(NULL), | 119 proxy_service_(NULL), |
| 165 preconnect_enabled_(preconnect_enabled), | 120 preconnect_enabled_(preconnect_enabled), |
| 166 consecutive_omnibox_preconnect_count_(0), | 121 consecutive_omnibox_preconnect_count_(0), |
| 167 next_trim_time_(base::TimeTicks::Now() + | 122 next_trim_time_(base::TimeTicks::Now() + |
| 168 TimeDelta::FromHours(kDurationBetweenTrimmingsHours)), | 123 TimeDelta::FromHours(kDurationBetweenTrimmingsHours)), |
| 169 observer_(NULL) { | 124 observer_(NULL) { |
| 170 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 125 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 171 } | 126 } |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 } | 346 } |
| 392 | 347 |
| 393 // ---------------------- End UI methods. ------------------------------------- | 348 // ---------------------- End UI methods. ------------------------------------- |
| 394 | 349 |
| 395 // --------------------- Start IO methods. ------------------------------------ | 350 // --------------------- Start IO methods. ------------------------------------ |
| 396 | 351 |
| 397 void Predictor::Shutdown() { | 352 void Predictor::Shutdown() { |
| 398 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 353 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 399 DCHECK(!shutdown_); | 354 DCHECK(!shutdown_); |
| 400 shutdown_ = true; | 355 shutdown_ = true; |
| 401 | |
| 402 STLDeleteElements(&pending_lookups_); | |
| 403 } | 356 } |
| 404 | 357 |
| 405 void Predictor::DiscardAllResults() { | 358 void Predictor::DiscardAllResults() { |
| 406 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 359 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 407 // Delete anything listed so far in this session that shows in about:dns. | 360 // Delete anything listed so far in this session that shows in about:dns. |
| 408 referrers_.clear(); | 361 referrers_.clear(); |
| 409 | 362 |
| 410 | 363 |
| 411 // Try to delete anything in our work queue. | 364 // Try to delete anything in our work queue. |
| 412 while (!work_queue_.IsEmpty()) { | 365 while (!work_queue_.IsEmpty()) { |
| 413 // Emulate processing cycle as though host was not found. | 366 // Emulate processing cycle as though host was not found. |
| 414 GURL url = work_queue_.Pop(); | 367 GURL url = work_queue_.Pop(); |
| 415 UrlInfo* info = &results_[url]; | 368 UrlInfo* info = &results_[url]; |
| 416 DCHECK(info->HasUrl(url)); | 369 DCHECK(info->HasUrl(url)); |
| 417 info->SetAssignedState(); | 370 info->SetAssignedState(); |
| 418 info->SetNoSuchNameState(); | 371 info->SetNoSuchNameState(); |
| 419 } | 372 } |
| 420 // Now every result_ is either resolved, or is being resolved | 373 // Now every result_ is either resolved, or is being resolved. |
| 421 // (see LookupRequest). | |
| 422 | 374 |
| 423 // Step through result_, recording names of all hosts that can't be erased. | 375 // Step through result_, recording names of all hosts that can't be erased. |
| 424 // We can't erase anything being worked on. | 376 // We can't erase anything being worked on. |
| 425 Results assignees; | 377 Results assignees; |
| 426 for (Results::iterator it = results_.begin(); results_.end() != it; ++it) { | 378 for (Results::iterator it = results_.begin(); results_.end() != it; ++it) { |
| 427 GURL url(it->first); | 379 GURL url(it->first); |
| 428 UrlInfo* info = &it->second; | 380 UrlInfo* info = &it->second; |
| 429 DCHECK(info->HasUrl(url)); | 381 DCHECK(info->HasUrl(url)); |
| 430 if (info->is_assigned()) { | 382 if (info->is_assigned()) { |
| 431 info->SetPendingDeleteState(); | 383 info->SetPendingDeleteState(); |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 686 | 638 |
| 687 void Predictor::FinalizeInitializationOnIOThread( | 639 void Predictor::FinalizeInitializationOnIOThread( |
| 688 const UrlList& startup_urls, | 640 const UrlList& startup_urls, |
| 689 base::ListValue* referral_list, | 641 base::ListValue* referral_list, |
| 690 IOThread* io_thread, | 642 IOThread* io_thread, |
| 691 ProfileIOData* profile_io_data) { | 643 ProfileIOData* profile_io_data) { |
| 692 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 644 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 693 | 645 |
| 694 profile_io_data_ = profile_io_data; | 646 profile_io_data_ = profile_io_data; |
| 695 initial_observer_.reset(new InitialObserver()); | 647 initial_observer_.reset(new InitialObserver()); |
| 696 host_resolver_ = io_thread->globals()->host_resolver.get(); | |
| 697 | 648 |
| 698 net::URLRequestContext* context = | 649 net::URLRequestContext* context = |
| 699 url_request_context_getter_->GetURLRequestContext(); | 650 url_request_context_getter_->GetURLRequestContext(); |
| 700 transport_security_state_ = context->transport_security_state(); | 651 transport_security_state_ = context->transport_security_state(); |
| 701 ssl_config_service_ = context->ssl_config_service(); | 652 ssl_config_service_ = context->ssl_config_service(); |
| 702 proxy_service_ = context->proxy_service(); | 653 proxy_service_ = context->proxy_service(); |
| 703 | 654 |
| 704 // base::WeakPtrFactory instances need to be created and destroyed | 655 // base::WeakPtrFactory instances need to be created and destroyed |
| 705 // on the same thread. The predictor lives on the IO thread and will die | 656 // on the same thread. The predictor lives on the IO thread and will die |
| 706 // from there so now that we're on the IO thread we need to properly | 657 // from there so now that we're on the IO thread we need to properly |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1016 UrlInfo* queued_info = AppendToResolutionQueue(future_url->first, | 967 UrlInfo* queued_info = AppendToResolutionQueue(future_url->first, |
| 1017 motivation); | 968 motivation); |
| 1018 if (queued_info) | 969 if (queued_info) |
| 1019 queued_info->SetReferringHostname(url); | 970 queued_info->SetReferringHostname(url); |
| 1020 } | 971 } |
| 1021 UMA_HISTOGRAM_ENUMERATION("Net.PreconnectSubresourceEval", evalution, | 972 UMA_HISTOGRAM_ENUMERATION("Net.PreconnectSubresourceEval", evalution, |
| 1022 SUBRESOURCE_VALUE_MAX); | 973 SUBRESOURCE_VALUE_MAX); |
| 1023 } | 974 } |
| 1024 } | 975 } |
| 1025 | 976 |
| 1026 void Predictor::OnLookupFinished(LookupRequest* request, const GURL& url, | 977 void Predictor::OnLookupFinished(const GURL& url, int result) { |
| 1027 bool found) { | |
| 1028 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 978 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 1029 | 979 |
| 1030 LookupFinished(request, url, found); | 980 LookupFinished(url, result == net::OK); |
| 1031 pending_lookups_.erase(request); | 981 DCHECK_GT(num_pending_lookups_, 0u); |
| 1032 delete request; | 982 num_pending_lookups_--; |
| 1033 | |
| 1034 StartSomeQueuedResolutions(); | 983 StartSomeQueuedResolutions(); |
| 1035 } | 984 } |
| 1036 | 985 |
| 1037 void Predictor::LookupFinished(LookupRequest* request, const GURL& url, | 986 void Predictor::LookupFinished(const GURL& url, bool found) { |
| 1038 bool found) { | |
| 1039 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 987 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 1040 UrlInfo* info = &results_[url]; | 988 UrlInfo* info = &results_[url]; |
| 1041 DCHECK(info->HasUrl(url)); | 989 DCHECK(info->HasUrl(url)); |
| 1042 if (info->is_marked_to_delete()) { | 990 if (info->is_marked_to_delete()) { |
| 1043 results_.erase(url); | 991 results_.erase(url); |
| 1044 } else { | 992 } else { |
| 1045 if (found) | 993 if (found) |
| 1046 info->SetFoundState(); | 994 info->SetFoundState(); |
| 1047 else | 995 else |
| 1048 info->SetNoSuchNameState(); | 996 info->SetNoSuchNameState(); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1108 break; | 1056 break; |
| 1109 info = &results_[work_queue_.Pop()]; | 1057 info = &results_[work_queue_.Pop()]; |
| 1110 info->SetAssignedState(); | 1058 info->SetAssignedState(); |
| 1111 } | 1059 } |
| 1112 return true; | 1060 return true; |
| 1113 } | 1061 } |
| 1114 | 1062 |
| 1115 void Predictor::StartSomeQueuedResolutions() { | 1063 void Predictor::StartSomeQueuedResolutions() { |
| 1116 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1064 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 1117 | 1065 |
| 1118 // If the queue is disabled, just make LookupRequests for all entries. | 1066 // If the queue is disabled, just make requests for all entries. |
| 1119 bool enable_queue = base::FeatureList::IsEnabled(kUsePredictorDNSQueue); | 1067 bool enable_queue = base::FeatureList::IsEnabled(kUsePredictorDNSQueue); |
| 1120 while (!work_queue_.IsEmpty() && | 1068 while ( |
| 1121 (!enable_queue || | 1069 !work_queue_.IsEmpty() && |
| 1122 pending_lookups_.size() < max_concurrent_dns_lookups_)) { | 1070 (!enable_queue || num_pending_lookups_ < max_concurrent_dns_lookups_)) { |
| 1123 const GURL url(work_queue_.Pop()); | 1071 const GURL url(work_queue_.Pop()); |
| 1124 UrlInfo* info = &results_[url]; | 1072 UrlInfo* info = &results_[url]; |
| 1125 DCHECK(info->HasUrl(url)); | 1073 DCHECK(info->HasUrl(url)); |
| 1126 info->SetAssignedState(); | 1074 info->SetAssignedState(); |
| 1127 | 1075 |
| 1128 // Only perform congestion control if the queue is enabled. | 1076 // Only perform congestion control if the queue is enabled. |
| 1129 if (enable_queue && CongestionControlPerformed(info)) { | 1077 if (enable_queue && CongestionControlPerformed(info)) { |
| 1130 DCHECK(work_queue_.IsEmpty()); | 1078 DCHECK(work_queue_.IsEmpty()); |
| 1131 return; | 1079 return; |
| 1132 } | 1080 } |
| 1133 | 1081 |
| 1134 LookupRequest* request = new LookupRequest(this, host_resolver_, url); | 1082 int status = content::PreresolveUrl( |
| 1135 | 1083 url_request_context_getter_.get(), url, |
| 1136 int status = request->Start(); | 1084 base::Bind(&Predictor::OnLookupFinished, base::Unretained(this), url)); |
| 1137 if (status == net::ERR_IO_PENDING) { | 1085 if (status == net::ERR_IO_PENDING) { |
| 1138 // Will complete asynchronously. | 1086 // Will complete asynchronously. |
| 1139 pending_lookups_.insert(request); | 1087 num_pending_lookups_++; |
| 1140 peak_pending_lookups_ = std::max(peak_pending_lookups_, | 1088 peak_pending_lookups_ = |
| 1141 pending_lookups_.size()); | 1089 std::max(peak_pending_lookups_, num_pending_lookups_); |
| 1142 } else { | 1090 } else { |
| 1143 // Completed synchronously (was already cached by HostResolver), or else | 1091 // Completed synchronously (was already cached by HostResolver), or else |
| 1144 // there was (equivalently) some network error that prevents us from | 1092 // there was (equivalently) some network error that prevents us from |
| 1145 // finding the name. Status net::OK means it was "found." | 1093 // finding the name. Status net::OK means it was "found." |
| 1146 LookupFinished(request, url, status == net::OK); | 1094 LookupFinished(url, status == net::OK); |
| 1147 delete request; | |
| 1148 } | 1095 } |
| 1149 } | 1096 } |
| 1150 } | 1097 } |
| 1151 | 1098 |
| 1152 void Predictor::TrimReferrers() { | 1099 void Predictor::TrimReferrers() { |
| 1153 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1100 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 1154 if (!urls_being_trimmed_.empty()) | 1101 if (!urls_being_trimmed_.empty()) |
| 1155 return; // There is incremental trimming in progress already. | 1102 return; // There is incremental trimming in progress already. |
| 1156 | 1103 |
| 1157 // Check to see if it is time to trim yet. | 1104 // Check to see if it is time to trim yet. |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1359 } | 1306 } |
| 1360 | 1307 |
| 1361 void SimplePredictor::ShutdownOnUIThread() { | 1308 void SimplePredictor::ShutdownOnUIThread() { |
| 1362 SetShutdown(true); | 1309 SetShutdown(true); |
| 1363 } | 1310 } |
| 1364 | 1311 |
| 1365 bool SimplePredictor::CanPrefetchAndPrerender() const { return true; } | 1312 bool SimplePredictor::CanPrefetchAndPrerender() const { return true; } |
| 1366 bool SimplePredictor::CanPreresolveAndPreconnect() const { return true; } | 1313 bool SimplePredictor::CanPreresolveAndPreconnect() const { return true; } |
| 1367 | 1314 |
| 1368 } // namespace chrome_browser_net | 1315 } // namespace chrome_browser_net |
| OLD | NEW |