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// A Predictor object is instantiated once in the browser process, and manages 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// both preresolution of hostnames, as well as TCP/IP preconnection to expected 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// subresources. 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Most hostname lists are provided by the renderer processes, and include URLs 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// that *might* be used in the near future by the browsing user. One goal of 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// this class is to cause the underlying DNS structure to lookup a hostname 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// before it is really needed, and hence reduce latency in the standard lookup 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// paths. 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Subresource relationships are usually acquired from the referrer field in a 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// navigation. A subresource URL may be associated with a referrer URL. Later 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// navigations may, if the likelihood of needing the subresource is high enough, 163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// cause this module to speculatively create a TCP/IP connection. If there is 173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// only a low likelihood, then a DNS pre-resolution operation may be performed. 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef CHROME_BROWSER_NET_PREDICTOR_H_ 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define CHROME_BROWSER_NET_PREDICTOR_H_ 213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <map> 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <queue> 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <set> 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <vector> 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/gtest_prod_util.h" 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/ref_counted.h" 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/net/url_info.h" 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/net/referrer.h" 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/net/predictor_common.h" 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/host_port_pair.h" 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass ListValue; 373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace net { 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass HostResolver; 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace net 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace chrome_browser_net { 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef chrome_common_net::UrlList UrlList; 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef chrome_common_net::NameList NameList; 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef std::map<GURL, UrlInfo> Results; 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Note that Predictor is not thread safe, and must only be called from 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the IO thread. Failure to do so will result in a DCHECK at runtime. 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass Predictor : public base::RefCountedThreadSafe<Predictor> { 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A version number for prefs that are saved. This should be incremented when 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we change the format so that we discard old data. 543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick enum { PREDICTOR_REFERRER_VERSION = 2 }; 553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // |max_concurrent| specifies how many concurrent (parallel) prefetches will 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // be performed. Host lookups will be issued through |host_resolver|. 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Predictor(net::HostResolver* host_resolver, 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::TimeDelta max_queue_delay_ms, size_t max_concurrent, 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool preconnect_enabled); 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Cancel pending requests and prevent new ones from being made. 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Shutdown(); 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // In some circumstances, for privacy reasons, all results should be 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // discarded. This method gracefully handles that activity. 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Destroy all our internal state, which shows what names we've looked up, and 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // how long each has taken, etc. etc. We also destroy records of suggesses 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (cache hits etc.). 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void DiscardAllResults(); 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add hostname(s) to the queue for processing. 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void ResolveList(const UrlList& urls, 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UrlInfo::ResolutionMotivation motivation); 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Resolve(const GURL& url, 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UrlInfo::ResolutionMotivation motivation); 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Instigate pre-connection to any URLs, or pre-resolution of related host, 793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // that we predict will be needed after this navigation (typically 803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // more-embedded resources on a page). This method will actually post a task 813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // to do the actual work, so as not to jump ahead of the frame navigation that 823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // instigated this activity. 833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void PredictFrameSubresources(const GURL& url); 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // The Omnibox has proposed a given url to the user, and if it is a search 863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // URL, then it also indicates that this is preconnectable (i.e., we could 873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // preconnect to the search server). 883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void AnticipateOmniboxUrl(const GURL& url, bool preconnectable); 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Preconnect a URL and all of its subresource domains. 913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void PreconnectUrlAndSubresources(const GURL& url); 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Record details of a navigation so that we can preresolve the host name 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ahead of time the next time the users navigates to the indicated host. 953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Should only be called when urls are distinct, and they should already be 963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // canonicalized to not have a path. 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void LearnFromNavigation(const GURL& referring_url, const GURL& target_url); 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Dump HTML table containing list of referrers for about:dns. 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void GetHtmlReferrerLists(std::string* output); 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Dump the list of currently known referrer domains and related prefetchable 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // domains. 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void GetHtmlInfo(std::string* output); 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Discards any referrer for which all the suggested host names are currently 107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // annotated with negligible expected-use. Scales down (diminishes) the 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // expected-use of those that remain, so that their use will go down by a 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // factor each time we trim (moving the referrer closer to being discarded in 110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // a future call). 111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The task is performed synchronously and completes before returing. 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void TrimReferrersNow(); 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Construct a ListValue object that contains all the data in the referrers_ 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // so that it can be persisted in a pref. 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void SerializeReferrers(ListValue* referral_list); 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Process a ListValue that contains all the data from a previous reference 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // list, as constructed by SerializeReferrers(), and add all the identified 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // values into the current referrer list. 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void DeserializeReferrers(const ListValue& referral_list); 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void DeserializeReferrersThenDelete(ListValue* referral_list); 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // For unit test code only. 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t max_concurrent_dns_lookups() const { 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return max_concurrent_dns_lookups_; 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Flag setting to use preconnection instead of just DNS pre-fetching. 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool preconnect_enabled() const { return preconnect_enabled_; } 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Put URL in canonical form, including a scheme, host, and port. 1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Returns GURL::EmptyGURL() if the scheme is not http/https or if the url 1353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // cannot be otherwise canonicalized. 1363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static GURL CanonicalizeUrl(const GURL& url); 1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class base::RefCountedThreadSafe<Predictor>; 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FRIEND_TEST_ALL_PREFIXES(PredictorTest, BenefitLookupTest); 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FRIEND_TEST_ALL_PREFIXES(PredictorTest, ShutdownWhenResolutionIsPendingTest); 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FRIEND_TEST_ALL_PREFIXES(PredictorTest, SingleLookupTest); 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FRIEND_TEST_ALL_PREFIXES(PredictorTest, ConcurrentLookupTest); 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FRIEND_TEST_ALL_PREFIXES(PredictorTest, MassiveConcurrentLookupTest); 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FRIEND_TEST_ALL_PREFIXES(PredictorTest, PriorityQueuePushPopTest); 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FRIEND_TEST_ALL_PREFIXES(PredictorTest, PriorityQueueReorderTest); 147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FRIEND_TEST_ALL_PREFIXES(PredictorTest, ReferrerSerializationTrimTest); 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class WaitForResolutionHelper; // For testing. 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch class LookupRequest; 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A simple priority queue for handling host names. 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Some names that are queued up have |motivation| that requires very rapid 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // handling. For example, a sub-resource name lookup MUST be done before the 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // actual sub-resource is fetched. In contrast, a name that was speculatively 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // noted in a page has to be resolved before the user "gets around to" 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // clicking on a link. By tagging (with a motivation) each push we make into 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // this FIFO queue, the queue can re-order the more important names to service 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // them sooner (relative to some low priority background resolutions). 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch class HostNameQueue { 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HostNameQueue(); 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ~HostNameQueue(); 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Push(const GURL& url, 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UrlInfo::ResolutionMotivation motivation); 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool IsEmpty() const; 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL Pop(); 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen private: 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The names in the queue that should be serviced (popped) ASAP. 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::queue<GURL> rush_queue_; 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The names in the queue that should only be serviced when rush_queue is 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // empty. 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::queue<GURL> background_queue_; 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(HostNameQueue); 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A map that is keyed with the host/port that we've learned were the cause 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // of loading additional URLs. The list of additional targets is held 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // in a Referrer instance, which is a value in this map. 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typedef std::map<GURL, Referrer> Referrers; 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Depending on the expected_subresource_use_, we may either make a TCP/IP 185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // preconnection, or merely pre-resolve the hostname via DNS (or even do 186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // nothing). The following are the threasholds for taking those actions. 187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static const double kPreconnectWorthyExpectedValue; 188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static const double kDNSPreresolutionWorthyExpectedValue; 189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Referred hosts with a subresource_use_rate_ that are less than the 190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // following threshold will be discarded when we Trim() the list. 191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static const double kDiscardableExpectedValue; 192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // During trimming operation to discard hosts for which we don't have likely 193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // subresources, we multiply the expected_subresource_use_ value by the 194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // following ratio until that value is less than kDiscardableExpectedValue. 195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // This number should always be less than 1, an more than 0. 196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static const double kReferrerTrimRatio; 197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Interval between periodic trimming of our whole referrer list. 199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We only do a major trimming about once an hour, and then only when the user 200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // is actively browsing. 201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static const base::TimeDelta kDurationBetweenTrimmings; 202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Interval between incremental trimmings (to avoid inducing Jank). 203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static const base::TimeDelta kDurationBetweenTrimmingIncrements; 204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Number of referring URLs processed in an incremental trimming. 205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static const size_t kUrlsTrimmedPerIncrement; 206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ~Predictor(); 2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Perform actual resolution or preconnection to subresources now. This is 2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // an internal worker method that is reached via a post task from 2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // PredictFrameSubresources(). 2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void PrepareFrameSubresources(const GURL& url); 2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Only for testing. Returns true if hostname has been successfully resolved 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (name found). 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool WasFound(const GURL& url) const { 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Results::const_iterator it(results_.find(url)); 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return (it != results_.end()) && 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it->second.was_found(); 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Only for testing. Return how long was the resolution 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // or UrlInfo::kNullDuration if it hasn't been resolved yet. 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::TimeDelta GetResolutionDuration(const GURL& url) { 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (results_.find(url) == results_.end()) 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return UrlInfo::kNullDuration; 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return results_[url].resolve_duration(); 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Only for testing; 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t peak_pending_lookups() const { return peak_pending_lookups_; } 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Access method for use by async lookup request to pass resolution result. 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void OnLookupFinished(LookupRequest* request, const GURL& url, bool found); 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Underlying method for both async and synchronous lookup to update state. 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void LookupFinished(LookupRequest* request, 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& url, bool found); 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Queue hostname for resolution. If queueing was done, return the pointer 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to the queued instance, otherwise return NULL. 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UrlInfo* AppendToResolutionQueue(const GURL& url, 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UrlInfo::ResolutionMotivation motivation); 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Check to see if too much queuing delay has been noted for the given info, 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // which indicates that there is "congestion" or growing delay in handling the 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // resolution of names. Rather than letting this congestion potentially grow 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // without bounds, we abandon our queued efforts at pre-resolutions in such a 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // case. 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // To do this, we will recycle |info|, as well as all queued items, back to 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the state they had before they were queued up. We can't do anything about 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the resolutions we've already sent off for processing on another thread, so 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we just let them complete. On a slow system, subject to congestion, this 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // will greatly reduce the number of resolutions done, but it will assure that 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // any resolutions that are done, are in a timely and hence potentially 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // helpful manner. 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool CongestionControlPerformed(UrlInfo* info); 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Take lookup requests from work_queue_ and tell HostResolver to look them up 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // asynchronously, provided we don't exceed concurrent resolution limit. 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void StartSomeQueuedResolutions(); 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Performs trimming similar to TrimReferrersNow(), except it does it as a 264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // series of short tasks by posting continuations again an again until done. 265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void TrimReferrers(); 266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Loads urls_being_trimmed_ from keys of current referrers_. 268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void LoadUrlsForTrimming(); 269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Posts a task to do additional incremental trimming of referrers_. 271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void PostIncrementalTrimTask(); 272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Calls Trim() on some or all of urls_being_trimmed_. 274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If it does not process all the URLs in that vector, it posts a task to 275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // continue with them shortly (i.e., it yeilds and continues). 276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void IncrementalTrimReferrers(bool trim_all_now); 277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // work_queue_ holds a list of names we need to look up. 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HostNameQueue work_queue_; 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // results_ contains information for existing/prior prefetches. 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Results results_; 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::set<LookupRequest*> pending_lookups_; 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // For testing, to verify that we don't exceed the limit. 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t peak_pending_lookups_; 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When true, we don't make new lookup requests. 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool shutdown_; 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 292513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // The number of concurrent speculative lookups currently allowed to be sent 293513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // to the resolver. Any additional lookups will be queued to avoid exceeding 294513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // this value. The queue is a priority queue that will accelerate 295513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // sub-resource speculation, and retard resolutions suggested by page scans. 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const size_t max_concurrent_dns_lookups_; 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The maximum queueing delay that is acceptable before we enter congestion 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // reduction mode, and discard all queued (but not yet assigned) resolutions. 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const base::TimeDelta max_dns_queue_delay_; 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 302731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // The host resolver we warm DNS entries for. 303731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick net::HostResolver* const host_resolver_; 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Are we currently using preconnection, rather than just DNS resolution, for 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // subresources and omni-box search URLs. 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool preconnect_enabled_; 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Most recent suggestion from Omnibox provided via AnticipateOmniboxUrl(). 3103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string last_omnibox_host_; 3113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // The time when the last preresolve was done for last_omnibox_host_. 3133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::TimeTicks last_omnibox_preresolve_; 3143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // The number of consecutive requests to AnticipateOmniboxUrl() that suggested 3163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // preconnecting (because it was to a search service). 3173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int consecutive_omnibox_preconnect_count_; 3183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // The time when the last preconnection was requested to a search service. 3203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::TimeTicks last_omnibox_preconnect_; 3213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // For each URL that we might navigate to (that we've "learned about") 323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // we have a Referrer list. Each Referrer list has all hostnames we might 324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // need to pre-resolve or pre-connect to when there is a navigation to the 325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // orginial hostname. 326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Referrers referrers_; 327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // List of URLs in referrers_ currently being trimmed (scaled down to 329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // eventually be aged out of use). 330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<GURL> urls_being_trimmed_; 331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // A time after which we need to do more trimming of referrers. 333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::TimeTicks next_trim_time_; 334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ScopedRunnableMethodFactory<Predictor> trim_task_factory_; 336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(Predictor); 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace chrome_browser_net 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // CHROME_BROWSER_NET_PREDICTOR_H_ 343