1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/net/predictor_api.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <map> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/lazy_instance.h" 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/metrics/field_trial.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/stl_util-inl.h" 133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h" 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/synchronization/waitable_event.h" 153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/values.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_process.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/io_thread.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/net/preconnect.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/net/referrer.h" 213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/net/url_info.h" 2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/prefs/browser_prefs.h" 233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/prefs/pref_service.h" 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/prefs/scoped_user_pref_update.h" 253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/prefs/session_startup_pref.h" 2621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h" 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h" 29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h" 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_registrar.h" 31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h" 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/host_resolver.h" 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/host_resolver_impl.h" 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::Time; 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeDelta; 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace chrome_browser_net { 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void DnsPrefetchMotivatedList(const UrlList& urls, 413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UrlInfo::ResolutionMotivation motivation); 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic UrlList GetPredictedUrlListAtStartup(PrefService* user_prefs, 443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PrefService* local_state); 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 46513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Given that the underlying Chromium resolver defaults to a total maximum of 47513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// 8 paralell resolutions, we will avoid any chance of starving navigational 48513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// resolutions by limiting the number of paralell speculative resolutions. 49513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// TODO(jar): Move this limitation into the resolver. 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 51513209b27ff55e2841eac0e4120199c23acce758Ben Murdochconst size_t PredictorInit::kMaxSpeculativeParallelResolves = 3; 52513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 53513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// To control our congestion avoidance system, which discards a queue when 54513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// resolutions are "taking too long," we need an expected resolution time. 55513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Common average is in the range of 300-500ms. 56513209b27ff55e2841eac0e4120199c23acce758Ben Murdochstatic const int kExpectedResolutionTimeMs = 500; 57513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 58513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// To control the congestion avoidance system, we need an estimate of how many 59513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// speculative requests may arrive at once. Since we currently only keep 8 60513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// subresource names for each frame, we'll use that as our basis. Note that 61513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// when scanning search results lists, we might actually get 10 at a time, and 62513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// wikipedia can often supply (during a page scan) upwards of 50. In those odd 63513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// cases, we may discard some of the later speculative requests mistakenly 64513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// assuming that the resolutions took too long. 65513209b27ff55e2841eac0e4120199c23acce758Ben Murdochstatic const int kTypicalSpeculativeGroupSize = 8; 66513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 67513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// The next constant specifies an amount of queueing delay that is "too large," 68513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// and indicative of problems with resolutions (perhaps due to an overloaded 69513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// router, or such). When we exceed this delay, congestion avoidance will kick 70513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// in and all speculations in the queue will be discarded. 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 72513209b27ff55e2841eac0e4120199c23acce758Ben Murdochconst int PredictorInit::kMaxSpeculativeResolveQueueDelayMs = 73513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch (kExpectedResolutionTimeMs * kTypicalSpeculativeGroupSize) / 74513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch kMaxSpeculativeParallelResolves; 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A version number for prefs that are saved. This should be incremented when 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// we change the format so that we discard old data. 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kPredictorStartupFormatVersion = 1; 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// There will only be one instance ever created of the following Observer class. 813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// The InitialObserver lives on the IO thread, and monitors navigations made by 823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// the network stack. This is only used to identify startup time resolutions 833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// (for re-resolution during our next process startup). 843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// TODO(jar): Consider preconnecting at startup, which may be faster than 853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// waiting for render process to start and request a connection. 863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass InitialObserver { 873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public: 883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Recording of when we observed each navigation. 893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick typedef std::map<GURL, base::TimeTicks> FirstNavigations; 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Potentially add a new URL to our startup list. 923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void Append(const GURL& url); 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Get an HTML version of our current planned first_navigations_. 953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void GetFirstResolutionsHtml(std::string* output); 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Persist the current first_navigations_ for storage in a list. 983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void GetInitialDnsResolutionList(ListValue* startup_list); 993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Discards all initial loading history. 101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen void DiscardInitialNavigationHistory() { first_navigations_.clear(); } 102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private: 1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // List of the first N URL resolutions observed in this run. 1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FirstNavigations first_navigations_; 1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // The number of URLs we'll save for pre-resolving at next startup. 1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static const size_t kStartupResolutionCount = 10; 1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}; 1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// TODO(willchan): Look at killing this global. 1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic InitialObserver* g_initial_observer = NULL; 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This section contains all the globally accessable API entry points for the 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// DNS Prefetching feature. 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Status of speculative DNS resolution and speculative TCP/IP connection 1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// feature. 1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic bool predictor_enabled = true; 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Cached inverted copy of the off_the_record pref. 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool on_the_record_switch = true; 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Enable/disable Dns prefetch activity (either via command line, or via pref). 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid EnablePredictor(bool enable) { 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTE: this is invoked on the UI thread. 1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick predictor_enabled = enable; 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid OnTheRecord(bool enable) { 133731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (on_the_record_switch == enable) 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch on_the_record_switch = enable; 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (on_the_record_switch) 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_browser_process->io_thread()->ChangedToOnTheRecord(); 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid DiscardInitialNavigationHistory() { 142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (g_initial_observer) 144dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen g_initial_observer->DiscardInitialNavigationHistory(); 145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid RegisterUserPrefs(PrefService* user_prefs) { 14821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen user_prefs->RegisterListPref(prefs::kDnsPrefetchingStartupList); 14921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen user_prefs->RegisterListPref(prefs::kDnsPrefetchingHostReferralList); 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// When enabled, we use the following instance to service all requests in the 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// browser process. 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(willchan): Look at killing this. 1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic Predictor* g_predictor = NULL; 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This API is only used in the browser process. 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// It is called from an IPC message originating in the renderer. It currently 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// includes both Page-Scan, and Link-Hover prefetching. 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(jar): Separate out link-hover prefetching, and page-scan results. 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DnsPrefetchList(const NameList& hostnames) { 1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // TODO(jar): Push GURL transport further back into renderer, but this will 1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // require a Webkit change in the observer :-/. 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UrlList urls; 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (NameList::const_iterator it = hostnames.begin(); 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it < hostnames.end(); 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++it) { 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch urls.push_back(GURL("http://" + *it + ":80")); 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 171731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DnsPrefetchMotivatedList(urls, UrlInfo::PAGE_SCAN_MOTIVATED); 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void DnsPrefetchMotivatedList( 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const UrlList& urls, 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UrlInfo::ResolutionMotivation motivation) { 178731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || 179731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::CurrentlyOn(BrowserThread::IO)); 1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!predictor_enabled || NULL == g_predictor) 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 183731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (BrowserThread::CurrentlyOn(BrowserThread::IO)) { 1843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick g_predictor->ResolveList(urls, motivation); 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 186731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 187731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FROM_HERE, 1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NewRunnableMethod(g_predictor, 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &Predictor::ResolveList, urls, motivation)); 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This API is used by the autocomplete popup box (where URLs are typed). 1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid AnticipateOmniboxUrl(const GURL& url, bool preconnectable) { 196731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!predictor_enabled || NULL == g_predictor) 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!url.is_valid() || !url.has_host()) 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick g_predictor->AnticipateOmniboxUrl(url, preconnectable); 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid PreconnectUrlAndSubresources(const GURL& url) { 2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!predictor_enabled || NULL == g_predictor) 2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!url.is_valid() || !url.has_host()) 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick g_predictor->PreconnectUrlAndSubresources(url); 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This section intermingles prefetch results with actual browser HTTP 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// network activity. It supports calculating of the benefit of a prefetch, as 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// well as recording what prefetched hostname resolutions might be potentially 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// helpful during the next chrome-startup. 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid PredictFrameSubresources(const GURL& url) { 223731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!predictor_enabled || NULL == g_predictor) 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 2263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick g_predictor->PredictFrameSubresources(url); 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid LearnAboutInitialNavigation(const GURL& url) { 230731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 2313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!predictor_enabled || NULL == g_initial_observer ) 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 2333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick g_initial_observer->Append(url); 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid LearnFromNavigation(const GURL& referring_url, const GURL& target_url) { 237731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 2383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!predictor_enabled || NULL == g_predictor) 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 2403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick g_predictor->LearnFromNavigation(referring_url, target_url); 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The observer class needs to connect starts and finishes of HTTP network 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// resolutions. We use the following type for that map. 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef std::map<int, UrlInfo> ObservedResolutionMap; 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Member definitions for InitialObserver class. 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid InitialObserver::Append(const GURL& url) { 251731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!on_the_record_switch || NULL == g_predictor) 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 2553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (kStartupResolutionCount <= first_navigations_.size()) 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (url.SchemeIs("http") || url.SchemeIs("https")) { 25972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const GURL url_without_path(Predictor::CanonicalizeUrl(url)); 2603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (first_navigations_.find(url_without_path) == first_navigations_.end()) 2613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick first_navigations_[url_without_path] = base::TimeTicks::Now(); 2623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid InitialObserver::GetInitialDnsResolutionList(ListValue* startup_list) { 266731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(startup_list); 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch startup_list->Clear(); 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(0u, startup_list->GetSize()); 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch startup_list->Append(new FundamentalValue(kPredictorStartupFormatVersion)); 2713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (FirstNavigations::iterator it = first_navigations_.begin(); 2723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick it != first_navigations_.end(); 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++it) { 2743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(it->first == Predictor::CanonicalizeUrl(it->first)); 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch startup_list->Append(new StringValue(it->first.spec())); 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid InitialObserver::GetFirstResolutionsHtml(std::string* output) { 280731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UrlInfo::UrlInfoTable resolution_list; 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 2843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (FirstNavigations::iterator it(first_navigations_.begin()); 2853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick it != first_navigations_.end(); 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it++) { 2873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UrlInfo info; 2883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick info.SetUrl(it->first); 2893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick info.set_time(it->second); 2903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick resolution_list.push_back(info); 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UrlInfo::GetHtmlTable(resolution_list, 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Future startups will prefetch DNS records for ", false, output); 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Support observer to detect opening and closing of OffTheRecord windows. 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This object lives on the UI thread. 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass OffTheRecordObserver : public NotificationObserver { 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Register() { 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(pkasting): This test should not be necessary. See crbug.com/12475. 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (registrar_.IsEmpty()) { 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::BROWSER_CLOSED, 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::AllSources()); 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::BROWSER_OPENED, 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::AllSources()); 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Observe(NotificationType type, const NotificationSource& source, 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (type.value) { 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::BROWSER_OPENED: 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!Source<Browser>(source)->profile()->IsOffTheRecord()) 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++count_off_the_record_windows_; 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnTheRecord(false); 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::BROWSER_CLOSED: 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!Source<Browser>(source)->profile()->IsOffTheRecord()) 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; // Ignore ordinary windows. 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_LT(0, count_off_the_record_windows_); 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (0 >= count_off_the_record_windows_) // Defensive coding. 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (--count_off_the_record_windows_) 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; // Still some windows are incognito. 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnTheRecord(true); 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 34021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen friend struct base::DefaultLazyInstanceTraits<OffTheRecordObserver>; 34121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OffTheRecordObserver() : count_off_the_record_windows_(0) {} 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ~OffTheRecordObserver() {} 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationRegistrar registrar_; 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int count_off_the_record_windows_; 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(OffTheRecordObserver); 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 35121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstatic base::LazyInstance<OffTheRecordObserver> g_off_the_record_observer( 35221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen base::LINKER_INITIALIZED); 35321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This section supports the about:dns page. 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Provide global support for the about:dns page. 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PredictorGetHtmlInfo(std::string* output) { 360731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch output->append("<html><head><title>About DNS</title>" 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We'd like the following no-cache... but it doesn't work. 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // "<META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">" 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "</head><body>"); 3663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!predictor_enabled || NULL == g_predictor) { 367731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick output->append("DNS pre-resolution and TCP pre-connection is disabled."); 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!on_the_record_switch) { 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch output->append("Incognito mode is active in a window."); 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 3723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // List items fetched at startup. 3733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (g_initial_observer) 3743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick g_initial_observer->GetFirstResolutionsHtml(output); 3753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Show list of subresource predictions and stats. 3763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick g_predictor->GetHtmlReferrerLists(output); 3773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Show list of prediction results. 3783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick g_predictor->GetHtmlInfo(output); 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch output->append("</body></html>"); 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 384ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ClearPredictorCache() { 385ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 386ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!predictor_enabled || NULL == g_predictor) 387ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 388ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen g_predictor->DiscardAllResults(); 389ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 390ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This section intializes global DNS prefetch services. 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void InitNetworkPredictor(TimeDelta max_dns_queue_delay, 396513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch size_t max_parallel_resolves, 397513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch PrefService* user_prefs, 398513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch PrefService* local_state, 399513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool preconnect_enabled) { 400731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool prefetching_enabled = 403ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen user_prefs->GetBoolean(prefs::kNetworkPredictionEnabled); 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Gather the list of hostnames to prefetch on startup. 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UrlList urls = 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetPredictedUrlListAtStartup(user_prefs, local_state); 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue* referral_list = 410ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static_cast<ListValue*>(user_prefs->GetList( 41121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen prefs::kDnsPrefetchingHostReferralList)->DeepCopy()); 41221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 41321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Remove obsolete preferences from local state if necessary. 41472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int current_version = 41572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen local_state->GetInteger(prefs::kMultipleProfilePrefMigration); 41672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if ((current_version & browser::DNS_PREFS) == 0) { 41721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen local_state->RegisterListPref(prefs::kDnsStartupPrefetchList); 41821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen local_state->RegisterListPref(prefs::kDnsHostReferralList); 41921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen local_state->ClearPref(prefs::kDnsStartupPrefetchList); 42021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen local_state->ClearPref(prefs::kDnsHostReferralList); 42172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen local_state->SetInteger(prefs::kMultipleProfilePrefMigration, 42272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen current_version | browser::DNS_PREFS); 42321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_browser_process->io_thread()->InitNetworkPredictor( 426513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch prefetching_enabled, max_dns_queue_delay, max_parallel_resolves, urls, 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch referral_list, preconnect_enabled); 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FinalizePredictorInitialization( 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Predictor* global_predictor, 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const UrlList& startup_urls, 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue* referral_list) { 434731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 4353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick g_predictor = global_predictor; 4363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick g_initial_observer = new InitialObserver(); 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Prefetch these hostnames on startup. 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DnsPrefetchMotivatedList(startup_urls, 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UrlInfo::STARTUP_LIST_MOTIVATED); 4413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick g_predictor->DeserializeReferrersThenDelete(referral_list); 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FreePredictorResources() { 445731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 4463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick g_predictor = NULL; // Owned and released by io_thread.cc. 4473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick delete g_initial_observer; 4483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick g_initial_observer = NULL; 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Functions to handle saving of hostnames from one session to the next, to 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// expedite startup times. 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void SaveDnsPrefetchStateForNextStartupAndTrimOnIOThread( 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue* startup_list, 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue* referral_list, 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::WaitableEvent* completion) { 459731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (NULL == g_predictor) { 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch completion->Signal(); 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (g_initial_observer) 4673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick g_initial_observer->GetInitialDnsResolutionList(startup_list); 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 469ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Do at least one trim at shutdown, in case the user wasn't running long 470ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // enough to do any regular trimming of referrers. 471ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen g_predictor->TrimReferrersNow(); 4723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick g_predictor->SerializeReferrers(referral_list); 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch completion->Signal(); 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SavePredictorStateForNextStartupAndTrim(PrefService* prefs) { 478731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!predictor_enabled || g_predictor == NULL) 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::WaitableEvent completion(true, false); 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 485ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ListPrefUpdate update_startup_list(prefs, prefs::kDnsPrefetchingStartupList); 486ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ListPrefUpdate update_referral_list(prefs, 487ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen prefs::kDnsPrefetchingHostReferralList); 488731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick bool posted = BrowserThread::PostTask( 489731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FROM_HERE, 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableFunction(SaveDnsPrefetchStateForNextStartupAndTrimOnIOThread, 492ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen update_startup_list.Get(), 493ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen update_referral_list.Get(), 49421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen &completion)); 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 496ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(jar): Synchronous waiting for the IO thread is a potential source 497ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // to deadlocks and should be investigated. See http://crbug.com/78451. 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(posted); 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (posted) 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch completion.Wait(); 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic UrlList GetPredictedUrlListAtStartup(PrefService* user_prefs, 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* local_state) { 505731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UrlList urls; 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Recall list of URLs we learned about during last session. 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This may catch secondary hostnames, pulled in by the homepages. It will 509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // also catch more of the "primary" home pages, since that was (presumably) 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // rendered first (and will be rendered first this time too). 511ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const ListValue* startup_list = 512ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen user_prefs->GetList(prefs::kDnsPrefetchingStartupList); 51321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (startup_list) { 515ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ListValue::const_iterator it = startup_list->begin(); 516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int format_version = -1; 517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (it != startup_list->end() && 518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (*it)->GetAsInteger(&format_version) && 519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch format_version == kPredictorStartupFormatVersion) { 520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++it; 521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (; it != startup_list->end(); ++it) { 522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string url_spec; 523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!(*it)->GetAsString(&url_spec)) { 524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(DFATAL); 525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; // Format incompatibility. 526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL url(url_spec); 528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!url.has_host() || !url.has_scheme()) { 529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(DFATAL); 530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; // Format incompatibility. 531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch urls.push_back(url); 534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Prepare for any static home page(s) the user has in prefs. The user may 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // have a LOT of tab's specified, so we may as well try to warm them all. 540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionStartupPref tab_start_pref = 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SessionStartupPref::GetStartupPref(user_prefs); 542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (SessionStartupPref::URLS == tab_start_pref.type) { 543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < tab_start_pref.urls.size(); i++) { 544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL gurl = tab_start_pref.urls[i]; 545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!gurl.is_valid() || gurl.SchemeIsFile() || gurl.host().empty()) 546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (gurl.SchemeIs("http") || gurl.SchemeIs("https")) 548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch urls.push_back(gurl.GetWithEmptyPath()); 549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (urls.empty()) 553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch urls.push_back(GURL("http://www.google.com:80")); 554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return urls; 556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Methods for the helper class that is used to startup and teardown the whole 560ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// g_predictor system (both DNS pre-resolution and TCP/IP pre-connection). 561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 562c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochPredictorInit::PredictorInit(PrefService* user_prefs, 563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* local_state, 5643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool preconnect_enabled) { 565731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set up a field trial to see what disabling DNS pre-resolution does to 567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // latency of page loads. 568731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick base::FieldTrial::Probability kDivisor = 1000; 569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // For each option (i.e., non-default), we have a fixed probability. 570731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick base::FieldTrial::Probability kProbabilityPerGroup = 100; // 10% probability. 571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 57272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // After June 30, 2011 builds, it will always be in default group 57372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // (default_enabled_prefetch). 57472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen trial_ = new base::FieldTrial("DnsImpact", kDivisor, 57572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "default_enabled_prefetch", 2011, 6, 30); 576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // First option is to disable prefetching completely. 5783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int disabled_prefetch = trial_->AppendGroup("disabled_prefetch", 579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kProbabilityPerGroup); 580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We're running two experiments at the same time. The first set of trials 582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // modulates the delay-time until we declare a congestion event (and purge 583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // our queue). The second modulates the number of concurrent resolutions 584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we do at any time. Users are in exactly one trial (or the default) during 585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // any one run, and hence only one experiment at a time. 586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Experiment 1: 587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set congestion detection at 250, 500, or 750ms, rather than the 1 second 588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // default. 5893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int max_250ms_prefetch = trial_->AppendGroup("max_250ms_queue_prefetch", 590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kProbabilityPerGroup); 5913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int max_500ms_prefetch = trial_->AppendGroup("max_500ms_queue_prefetch", 592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kProbabilityPerGroup); 5933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int max_750ms_prefetch = trial_->AppendGroup("max_750ms_queue_prefetch", 594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kProbabilityPerGroup); 595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set congestion detection at 2 seconds instead of the 1 second default. 5963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int max_2s_prefetch = trial_->AppendGroup("max_2s_queue_prefetch", 597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kProbabilityPerGroup); 598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Experiment 2: 599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set max simultaneous resoultions to 2, 4, or 6, and scale the congestion 600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // limit proportionally (so we don't impact average probability of asserting 601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // congesion very much). 602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int max_2_concurrent_prefetch = trial_->AppendGroup( 6033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "max_2 concurrent_prefetch", kProbabilityPerGroup); 604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int max_4_concurrent_prefetch = trial_->AppendGroup( 6053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "max_4 concurrent_prefetch", kProbabilityPerGroup); 606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int max_6_concurrent_prefetch = trial_->AppendGroup( 6073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "max_6 concurrent_prefetch", kProbabilityPerGroup); 608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We will register the incognito observer regardless of whether prefetching 610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // is enabled, as it is also used to clear the host cache. 61121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen g_off_the_record_observer.Get().Register(); 612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (trial_->group() != disabled_prefetch) { 614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Initialize the DNS prefetch system. 615513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch size_t max_parallel_resolves = kMaxSpeculativeParallelResolves; 616513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int max_queueing_delay_ms = kMaxSpeculativeResolveQueueDelayMs; 617513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (trial_->group() == max_2_concurrent_prefetch) 619513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch max_parallel_resolves = 2; 620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else if (trial_->group() == max_4_concurrent_prefetch) 621513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch max_parallel_resolves = 4; 622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else if (trial_->group() == max_6_concurrent_prefetch) 623513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch max_parallel_resolves = 6; 624513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 625513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (trial_->group() == max_250ms_prefetch) { 626513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch max_queueing_delay_ms = 627513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch (250 * kTypicalSpeculativeGroupSize) / max_parallel_resolves; 628513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else if (trial_->group() == max_500ms_prefetch) { 629513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch max_queueing_delay_ms = 630513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch (500 * kTypicalSpeculativeGroupSize) / max_parallel_resolves; 631513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else if (trial_->group() == max_750ms_prefetch) { 632513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch max_queueing_delay_ms = 633513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch (750 * kTypicalSpeculativeGroupSize) / max_parallel_resolves; 634513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else if (trial_->group() == max_2s_prefetch) { 635513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch max_queueing_delay_ms = 636513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch (2000 * kTypicalSpeculativeGroupSize) / max_parallel_resolves; 637513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeDelta max_queueing_delay( 640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeDelta::FromMilliseconds(max_queueing_delay_ms)); 641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 6423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(!g_predictor); 643513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch InitNetworkPredictor(max_queueing_delay, max_parallel_resolves, user_prefs, 644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state, preconnect_enabled); 645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 648731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickPredictorInit::~PredictorInit() { 649731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace chrome_browser_net 652