15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/net/predictor.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cmath> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sstream> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "base/basictypes.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "base/containers/mru_cache.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h" 181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/prefs/scoped_user_pref_update.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h" 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h" 25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/io_thread.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/net/preconnect.h" 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/net/spdyproxy/data_reduction_proxy_settings.h" 30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/net/spdyproxy/proxy_advisor.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prefs/session_startup_pref.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h" 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/user_prefs/pref_registry_syncable.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/address_list.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/completion_callback.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/host_port_pair.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h" 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/dns/host_resolver.h" 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/dns/single_request_host_resolver.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chrome_browser_net { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int Predictor::kPredictorReferrerVersion = 2; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const double Predictor::kPreconnectWorthyExpectedValue = 0.8; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const double Predictor::kDNSPreresolutionWorthyExpectedValue = 0.1; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const double Predictor::kDiscardableExpectedValue = 0.05; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The goal is of trimming is to to reduce the importance (number of expected 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// subresources needed) by a factor of 2 after about 24 hours of uptime. We will 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// trim roughly once-an-hour of uptime. The ratio to use in each trim operation 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is then the 24th root of 0.5. If a user only surfs for 4 hours a day, then 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// after about 6 days they will have halved all their estimates of subresource 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// connections. Once this falls below kDiscardableExpectedValue the referrer 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// will be discarded. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(jar): Measure size of referrer lists in the field. Consider an adaptive 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// system that uses a higher trim ratio when the list is large. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const double Predictor::kReferrerTrimRatio = 0.97153; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int64 Predictor::kDurationBetweenTrimmingsHours = 1; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int64 Predictor::kDurationBetweenTrimmingIncrementsSeconds = 15; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t Predictor::kUrlsTrimmedPerIncrement = 5u; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t Predictor::kMaxSpeculativeParallelResolves = 3; 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const int Predictor::kMaxUnusedSocketLifetimeSecondsWithoutAGet = 10; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To control our congestion avoidance system, which discards a queue when 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// resolutions are "taking too long," we need an expected resolution time. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Common average is in the range of 300-500ms. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kExpectedResolutionTimeMs = 500; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int Predictor::kTypicalSpeculativeGroupSize = 8; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int Predictor::kMaxSpeculativeResolveQueueDelayMs = 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (kExpectedResolutionTimeMs * Predictor::kTypicalSpeculativeGroupSize) / 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Predictor::kMaxSpeculativeParallelResolves; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int g_max_queueing_delay_ms = 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Predictor::kMaxSpeculativeResolveQueueDelayMs; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static size_t g_max_parallel_resolves = 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Predictor::kMaxSpeculativeParallelResolves; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A version number for prefs that are saved. This should be incremented when 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we change the format so that we discard old data. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kPredictorStartupFormatVersion = 1; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Predictor::LookupRequest { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LookupRequest(Predictor* predictor, 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::HostResolver* host_resolver, 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : predictor_(predictor), 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_(url), 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resolver_(host_resolver) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return underlying network resolver status. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // net::OK ==> Host was found synchronously. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // net:ERR_IO_PENDING ==> Network will callback later with result. 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // anything else ==> Host was not found synchronously. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int Start() { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::HostResolver::RequestInfo resolve_info( 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::HostPortPair::FromURL(url_)); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make a note that this is a speculative resolve request. This allows us 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to separate it from real navigations in the observer's callback, and 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // lets the HostResolver know it can de-prioritize it. 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resolve_info.set_is_speculative(true); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return resolver_.Resolve( 1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) resolve_info, 1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) net::DEFAULT_PRIORITY, 1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) &addresses_, 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&LookupRequest::OnLookupFinished, base::Unretained(this)), 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::BoundNetLog()); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnLookupFinished(int result) { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) predictor_->OnLookupFinished(this, url_, result == net::OK); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Predictor* predictor_; // The predictor which started us. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL url_; // Hostname to resolve. 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::SingleRequestHostResolver resolver_; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::AddressList addresses_; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(LookupRequest); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// This records UMAs for preconnect usage based on navigation URLs to 1343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// gather precision/recall for user-event based preconnect triggers. 1353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// Stats are gathered via a LRU cache that remembers all preconnect within the 1363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// last N seconds. 1373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// A preconnect trigger is considered as used iff a navigation including 1383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// access to the preconnected host occurs within a time period specified by 1393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// kMaxUnusedSocketLifetimeSecondsWithoutAGet. 1403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochclass Predictor::PreconnectUsage { 1413240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch public: 1423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch PreconnectUsage(); 1433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch ~PreconnectUsage(); 1443240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1453240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // Record a preconnect trigger to |url|. 1463240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch void ObservePreconnect(const GURL& url); 1473240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // Record a user navigation with its redirect history, |url_chain|. 1493240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // We are uncertain if this is actually a link navigation. 1503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch void ObserveNavigationChain(const std::vector<GURL>& url_chain, 1513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch bool is_subresource); 1523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // Record a user link navigation to |final_url|. 1543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // We are certain that this is a user-triggered link navigation. 1553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch void ObserveLinkNavigation(const GURL& final_url); 1563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch private: 1583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // This tracks whether a preconnect was used in some navigation or not 1593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch class PreconnectPrecisionStat { 1603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch public: 1613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch PreconnectPrecisionStat() 1623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch : timestamp_(base::TimeTicks::Now()), 1633240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch was_used_(false) { 1643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 1653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch const base::TimeTicks& timestamp() { return timestamp_; } 1673240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1683240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch void set_was_used() { was_used_ = true; } 1693240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch bool was_used() const { return was_used_; } 1703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch private: 1723240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch base::TimeTicks timestamp_; 1733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch bool was_used_; 1743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch }; 1753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch typedef base::MRUCache<GURL, PreconnectPrecisionStat> MRUPreconnects; 1773240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch MRUPreconnects mru_preconnects_; 1783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1793240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // The longest time an entry can persist in mru_preconnect_ 1803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch const base::TimeDelta max_duration_; 1813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch std::vector<GURL> recent_navigation_chain_; 1833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch DISALLOW_COPY_AND_ASSIGN(PreconnectUsage); 1853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}; 1863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochPredictor::PreconnectUsage::PreconnectUsage() 1883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch : mru_preconnects_(MRUPreconnects::NO_AUTO_EVICT), 1893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch max_duration_(base::TimeDelta::FromSeconds( 1903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch Predictor::kMaxUnusedSocketLifetimeSecondsWithoutAGet)) { 1913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch} 1923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochPredictor::PreconnectUsage::~PreconnectUsage() {} 1943240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1953240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid Predictor::PreconnectUsage::ObservePreconnect(const GURL& url) { 1963240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // Evict any overly old entries and record stats. 1973240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch base::TimeTicks now = base::TimeTicks::Now(); 1983240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1993240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch MRUPreconnects::reverse_iterator eldest_preconnect = 2003240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch mru_preconnects_.rbegin(); 2013240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch while (!mru_preconnects_.empty()) { 2023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch DCHECK(eldest_preconnect == mru_preconnects_.rbegin()); 2033240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (now - eldest_preconnect->second.timestamp() < max_duration_) 2043240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch break; 2053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 2063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch UMA_HISTOGRAM_BOOLEAN("Net.PreconnectTriggerUsed", 2073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch eldest_preconnect->second.was_used()); 2083240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch eldest_preconnect = mru_preconnects_.Erase(eldest_preconnect); 2093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 2103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 2113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // Add new entry. 2123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch GURL canonical_url(Predictor::CanonicalizeUrl(url)); 2133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch mru_preconnects_.Put(canonical_url, PreconnectPrecisionStat()); 2143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch} 2153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 2163240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid Predictor::PreconnectUsage::ObserveNavigationChain( 2173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch const std::vector<GURL>& url_chain, 2183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch bool is_subresource) { 2193240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (url_chain.empty()) 2203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return; 2213240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 2223240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (!is_subresource) 2233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch recent_navigation_chain_ = url_chain; 2243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 2253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch GURL canonical_url(Predictor::CanonicalizeUrl(url_chain.back())); 2263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 2273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch MRUPreconnects::iterator itPreconnect = mru_preconnects_.Peek(canonical_url); 2283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch bool was_preconnected = (itPreconnect != mru_preconnects_.end()); 2293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 2303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // This is an UMA which was named incorrectly. This actually measures the 2313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // ratio of URLRequests which have used a preconnected session. 2323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch UMA_HISTOGRAM_BOOLEAN("Net.PreconnectedNavigation", was_preconnected); 2333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch} 2343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 2353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid Predictor::PreconnectUsage::ObserveLinkNavigation(const GURL& url) { 2363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (recent_navigation_chain_.empty() || 2373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch url != recent_navigation_chain_.back()) { 2383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // The navigation chain is not available for this navigation. 2393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch recent_navigation_chain_.clear(); 2403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch recent_navigation_chain_.push_back(url); 2413240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 2423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 2433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // See if the link navigation involved preconnected session. 2443240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch bool did_use_preconnect = false; 2453240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch for (std::vector<GURL>::const_iterator it = recent_navigation_chain_.begin(); 2463240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch it != recent_navigation_chain_.end(); 2473240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch ++it) { 2483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch GURL canonical_url(Predictor::CanonicalizeUrl(*it)); 2493240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 2503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // Record the preconnect trigger for the url as used if exist 2513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch MRUPreconnects::iterator itPreconnect = 2523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch mru_preconnects_.Peek(canonical_url); 2533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch bool was_preconnected = (itPreconnect != mru_preconnects_.end()); 2543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (was_preconnected) { 2553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) itPreconnect->second.set_was_used(); 2563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch did_use_preconnect = true; 2573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 2593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 2603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch UMA_HISTOGRAM_BOOLEAN("Net.PreconnectedLinkNavigations", did_use_preconnect); 2613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch} 2623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Predictor::Predictor(bool preconnect_enabled) 2647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) : url_request_context_getter_(NULL), 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) predictor_enabled_(true), 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) peak_pending_lookups_(0), 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_(false), 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_concurrent_dns_lookups_(g_max_parallel_resolves), 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_dns_queue_delay_( 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta::FromMilliseconds(g_max_queueing_delay_ms)), 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_resolver_(NULL), 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) preconnect_enabled_(preconnect_enabled), 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consecutive_omnibox_preconnect_count_(0), 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_trim_time_(base::TimeTicks::Now() + 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta::FromHours(kDurationBetweenTrimmingsHours)) { 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Predictor::~Predictor() { 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(rlp): Add DCHECK for CurrentlyOn(BrowserThread::IO) when the 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ProfileManagerTest has been updated with a mock profile. 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(shutdown_); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Predictor* Predictor::CreatePredictor(bool preconnect_enabled, 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool simple_shutdown) { 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (simple_shutdown) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new SimplePredictor(preconnect_enabled); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new Predictor(preconnect_enabled); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid Predictor::RegisterProfilePrefs( 2947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch user_prefs::PrefRegistrySyncable* registry) { 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registry->RegisterListPref(prefs::kDnsPrefetchingStartupList, 296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registry->RegisterListPref(prefs::kDnsPrefetchingHostReferralList, 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --------------------- Start UI methods. ------------------------------------ 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::InitNetworkPredictor(PrefService* user_prefs, 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrefService* local_state, 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOThread* io_thread, 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequestContextGetter* getter) { 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool predictor_enabled = 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_prefs->GetBoolean(prefs::kNetworkPredictionEnabled); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_request_context_getter_ = getter; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Gather the list of hostnames to prefetch on startup. 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlList urls = GetPredictedUrlListAtStartup(user_prefs, local_state); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ListValue* referral_list = 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<base::ListValue*>(user_prefs->GetList( 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs::kDnsPrefetchingHostReferralList)->DeepCopy()); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now that we have the statistics in memory, wipe them from the Preferences 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // file. They will be serialized back on a clean shutdown. This way we only 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // have to worry about clearing our in-memory state when Clearing Browsing 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Data. 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_prefs->ClearPref(prefs::kDnsPrefetchingStartupList); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_prefs->ClearPref(prefs::kDnsPrefetchingHostReferralList); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if defined(OS_ANDROID) || defined(OS_IOS) 329f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // TODO(marq): Once https://codereview.chromium.org/30883003/ lands, also 330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // condition this on DataReductionProxySettings::IsDataReductionProxyAllowed() 331f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Until then, we may create a proxy advisor when the proxy feature itself 332f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // isn't available, and the advisor instance will never send advisory 333f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // requests, which is slightly wasteful but not harmful. 334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (DataReductionProxySettings::IsPreconnectHintingAllowed()) { 335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) proxy_advisor_.reset(new ProxyAdvisor(user_prefs, getter)); 336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 337f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif 338f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::IO, 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind( 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &Predictor::FinalizeInitializationOnIOThread, 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(this), 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) urls, referral_list, 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_thread, predictor_enabled)); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::AnticipateOmniboxUrl(const GURL& url, bool preconnectable) { 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!predictor_enabled_) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url.is_valid() || !url.has_host()) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string host = url.HostNoBrackets(); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_new_host_request = (host != last_omnibox_host_); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_omnibox_host_ = host; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo::ResolutionMotivation motivation(UrlInfo::OMNIBOX_MOTIVATED); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks now = base::TimeTicks::Now(); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (preconnect_enabled()) { 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (preconnectable && !is_new_host_request) { 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++consecutive_omnibox_preconnect_count_; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The omnibox suggests a search URL (for which we can preconnect) after 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one or two characters are typed, even though such typing often (1 in 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3?) becomes a real URL. This code waits till is has more evidence of a 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // preconnectable URL (search URL) before forming a preconnection, so as 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to reduce the useless preconnect rate. 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Perchance this logic should be pushed back into the omnibox, where the 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // actual characters typed, such as a space, can better forcast whether 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we need to search/preconnect or not. By waiting for at least 4 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // characters in a row that have lead to a search proposal, we avoid 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // preconnections for a prefix like "www." and we also wait until we have 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // at least a 4 letter word to search for. 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Each character typed appears to induce 2 calls to 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AnticipateOmniboxUrl(), so we double 4 characters and limit at 8 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // requests. 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(jar): Use an A/B test to optimize this. 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kMinConsecutiveRequests = 8; 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (consecutive_omnibox_preconnect_count_ >= kMinConsecutiveRequests) { 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(jar): Perhaps we should do a GET to leave the socket open in the 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pool. Currently, we just do a connect, which MAY be reset if we 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // don't use it in 10 secondes!!! As a result, we may do more 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // connections, and actually cost the server more than if we did a real 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // get with a fake request (/gen_204 might be the good path on Google). 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kMaxSearchKeepaliveSeconds(10); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((now - last_omnibox_preconnect_).InSeconds() < 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kMaxSearchKeepaliveSeconds) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // We've done a preconnect recently. 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_omnibox_preconnect_ = now; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kConnectionsNeeded = 1; 39390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) PreconnectUrl(CanonicalizeUrl(url), GURL(), motivation, 39490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kConnectionsNeeded); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // Skip pre-resolution, since we'll open a connection. 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consecutive_omnibox_preconnect_count_ = 0; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fall through and consider pre-resolution. 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Omnibox tends to call in pairs (just a few milliseconds apart), and we 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // really don't need to keep resolving a name that often. 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(jar): A/B tests could check for perf impact of the early returns. 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_new_host_request) { 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kMinPreresolveSeconds(10); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kMinPreresolveSeconds > (now - last_omnibox_preresolve_).InSeconds()) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_omnibox_preresolve_ = now; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::IO, 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&Predictor::Resolve, base::Unretained(this), 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CanonicalizeUrl(url), motivation)); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 42190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void Predictor::PreconnectUrlAndSubresources(const GURL& url, 42290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const GURL& first_party_for_cookies) { 42390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || 42490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) BrowserThread::CurrentlyOn(BrowserThread::IO)); 42590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!predictor_enabled_ || !preconnect_enabled() || 42690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) !url.is_valid() || !url.has_host()) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 42890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 42990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) UrlInfo::ResolutionMotivation motivation(UrlInfo::EARLY_LOAD_MOTIVATED); 43090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const int kConnectionsNeeded = 1; 43190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) PreconnectUrl(CanonicalizeUrl(url), first_party_for_cookies, 43290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) motivation, kConnectionsNeeded); 43390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) PredictFrameSubresources(url.GetWithEmptyPath(), first_party_for_cookies); 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UrlList Predictor::GetPredictedUrlListAtStartup( 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrefService* user_prefs, 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrefService* local_state) { 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlList urls; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Recall list of URLs we learned about during last session. 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This may catch secondary hostnames, pulled in by the homepages. It will 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // also catch more of the "primary" home pages, since that was (presumably) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // rendered first (and will be rendered first this time too). 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ListValue* startup_list = 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_prefs->GetList(prefs::kDnsPrefetchingStartupList); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (startup_list) { 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ListValue::const_iterator it = startup_list->begin(); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int format_version = -1; 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != startup_list->end() && 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*it)->GetAsInteger(&format_version) && 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format_version == kPredictorStartupFormatVersion) { 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; it != startup_list->end(); ++it) { 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url_spec; 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(*it)->GetAsString(&url_spec)) { 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; // Format incompatibility. 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url(url_spec); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url.has_host() || !url.has_scheme()) { 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; // Format incompatibility. 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) urls.push_back(url); 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prepare for any static home page(s) the user has in prefs. The user may 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // have a LOT of tab's specified, so we may as well try to warm them all. 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionStartupPref tab_start_pref = 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionStartupPref::GetStartupPref(user_prefs); 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SessionStartupPref::URLS == tab_start_pref.type) { 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < tab_start_pref.urls.size(); i++) { 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL gurl = tab_start_pref.urls[i]; 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gurl.is_valid() || gurl.SchemeIsFile() || gurl.host().empty()) 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 4813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (gurl.SchemeIsHTTPOrHTTPS()) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) urls.push_back(gurl.GetWithEmptyPath()); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (urls.empty()) 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) urls.push_back(GURL("http://www.google.com:80")); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return urls; 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::set_max_queueing_delay(int max_queueing_delay_ms) { 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_max_queueing_delay_ms = max_queueing_delay_ms; 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::set_max_parallel_resolves(size_t max_parallel_resolves) { 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_max_parallel_resolves = max_parallel_resolves; 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void Predictor::ShutdownOnUIThread() { 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::IO, 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&Predictor::Shutdown, base::Unretained(this))); 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------- End UI methods. ------------------------------------- 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --------------------- Start IO methods. ------------------------------------ 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::Shutdown() { 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!shutdown_); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_ = true; 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLDeleteElements(&pending_lookups_); 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::DiscardAllResults() { 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete anything listed so far in this session that shows in about:dns. 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) referrers_.clear(); 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try to delete anything in our work queue. 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!work_queue_.IsEmpty()) { 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Emulate processing cycle as though host was not found. 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url = work_queue_.Pop(); 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo* info = &results_[url]; 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(info->HasUrl(url)); 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->SetAssignedState(); 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->SetNoSuchNameState(); 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now every result_ is either resolved, or is being resolved 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (see LookupRequest). 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Step through result_, recording names of all hosts that can't be erased. 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can't erase anything being worked on. 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Results assignees; 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Results::iterator it = results_.begin(); results_.end() != it; ++it) { 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url(it->first); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo* info = &it->second; 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(info->HasUrl(url)); 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (info->is_assigned()) { 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->SetPendingDeleteState(); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assignees[url] = *info; 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(assignees.size(), max_concurrent_dns_lookups_); 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results_.clear(); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Put back in the names being worked on. 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Results::iterator it = assignees.begin(); assignees.end() != it; ++it) { 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(it->second.is_marked_to_delete()); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results_[it->first] = it->second; 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Overloaded Resolve() to take a vector of names. 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::ResolveList(const UrlList& urls, 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo::ResolutionMotivation motivation) { 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (UrlList::const_iterator it = urls.begin(); it < urls.end(); ++it) { 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AppendToResolutionQueue(*it, motivation); 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Basic Resolve() takes an invidual name, and adds it 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to the queue. 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::Resolve(const GURL& url, 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo::ResolutionMotivation motivation) { 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url.has_host()) 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AppendToResolutionQueue(url, motivation); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::LearnFromNavigation(const GURL& referring_url, 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& target_url) { 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!predictor_enabled_) 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(referring_url, Predictor::CanonicalizeUrl(referring_url)); 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(referring_url, GURL::EmptyGURL()); 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(target_url, Predictor::CanonicalizeUrl(target_url)); 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(target_url, GURL::EmptyGURL()); 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) referrers_[referring_url].SuggestHost(target_url); 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Possibly do some referrer trimming. 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TrimReferrers(); 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//----------------------------------------------------------------------------- 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This section supports the about:dns page. 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::PredictorGetHtmlInfo(Predictor* predictor, 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* output) { 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->append("<html><head><title>About DNS</title>" 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We'd like the following no-cache... but it doesn't work. 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "<META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">" 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "</head><body>"); 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (predictor && predictor->predictor_enabled()) { 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) predictor->GetHtmlInfo(output); 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->append("DNS pre-resolution and TCP pre-connection is disabled."); 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->append("</body></html>"); 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Provide sort order so all .com's are together, etc. 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct RightToLeftStringSorter { 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool operator()(const GURL& left, const GURL& right) const { 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ReverseComponents(left) < ReverseComponents(right); 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Transforms something like "http://www.google.com/xyz" to 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "http://com.google.www/xyz". 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static std::string ReverseComponents(const GURL& url) { 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reverse the components in the hostname. 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> parts; 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SplitString(url.host(), '.', &parts); 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::reverse(parts.begin(), parts.end()); 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string reversed_host = JoinString(parts, '.'); 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return the new URL. 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL::Replacements url_components; 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_components.SetHostStr(reversed_host); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return url.ReplaceComponents(url_components).spec(); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::GetHtmlReferrerLists(std::string* output) { 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (referrers_.empty()) 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(jar): Remove any plausible JavaScript from names before displaying. 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::set<GURL, struct RightToLeftStringSorter> 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SortedNames; 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SortedNames sorted_names; 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Referrers::iterator it = referrers_.begin(); 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) referrers_.end() != it; ++it) 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sorted_names.insert(it->first); 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->append("<br><table border>"); 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->append( 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "<tr><th>Host for Page</th>" 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "<th>Page Load<br>Count</th>" 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "<th>Subresource<br>Navigations</th>" 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "<th>Subresource<br>PreConnects</th>" 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "<th>Subresource<br>PreResolves</th>" 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "<th>Expected<br>Connects</th>" 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "<th>Subresource Spec</th></tr>"); 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (SortedNames::iterator it = sorted_names.begin(); 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sorted_names.end() != it; ++it) { 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Referrer* referrer = &(referrers_[*it]); 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool first_set_of_futures = true; 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Referrer::iterator future_url = referrer->begin(); 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) future_url != referrer->end(); ++future_url) { 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->append("<tr align=right>"); 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (first_set_of_futures) { 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringAppendF(output, 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "<td rowspan=%d>%s</td><td rowspan=%d>%d</td>", 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(referrer->size()), 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->spec().c_str(), 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(referrer->size()), 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(referrer->use_count())); 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_set_of_futures = false; 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringAppendF(output, 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "<td>%d</td><td>%d</td><td>%d</td><td>%2.3f</td><td>%s</td></tr>", 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(future_url->second.navigation_count()), 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(future_url->second.preconnection_count()), 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(future_url->second.preresolution_count()), 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<double>(future_url->second.subresource_use_rate()), 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) future_url->first.spec().c_str()); 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->append("</table>"); 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::GetHtmlInfo(std::string* output) { 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (initial_observer_.get()) 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initial_observer_->GetFirstResolutionsHtml(output); 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Show list of subresource predictions and stats. 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetHtmlReferrerLists(output); 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Local lists for calling UrlInfo 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo::UrlInfoTable name_not_found; 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo::UrlInfoTable name_preresolved; 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get copies of all useful data. 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::map<GURL, UrlInfo, RightToLeftStringSorter> SortedUrlInfo; 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SortedUrlInfo snapshot; 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // UrlInfo supports value semantics, so we can do a shallow copy. 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Results::iterator it(results_.begin()); it != results_.end(); it++) 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snapshot[it->first] = it->second; 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Partition the UrlInfo's into categories. 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (SortedUrlInfo::iterator it(snapshot.begin()); 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != snapshot.end(); it++) { 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it->second.was_nonexistent()) { 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name_not_found.push_back(it->second); 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!it->second.was_found()) 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // Still being processed. 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name_preresolved.push_back(it->second); 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool brief = false; 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef NDEBUG 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) brief = true; 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // NDEBUG 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Call for display of each table, along with title. 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo::GetHtmlTable(name_preresolved, 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Preresolution DNS records performed for ", brief, output); 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo::GetHtmlTable(name_not_found, 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Preresolving DNS records revealed non-existence for ", brief, output); 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::TrimReferrersNow() { 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Just finish up work if an incremental trim is in progress. 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (urls_being_trimmed_.empty()) 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadUrlsForTrimming(); 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IncrementalTrimReferrers(true); // Do everything now. 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::SerializeReferrers(base::ListValue* referral_list) { 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) referral_list->Clear(); 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) referral_list->Append(new base::FundamentalValue(kPredictorReferrerVersion)); 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Referrers::const_iterator it = referrers_.begin(); 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != referrers_.end(); ++it) { 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Serialize the list of subresource names. 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Value* subresource_list(it->second.Serialize()); 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a list for each referer. 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListValue* motivator(new ListValue); 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) motivator->Append(new StringValue(it->first.spec())); 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) motivator->Append(subresource_list); 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) referral_list->Append(motivator); 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::DeserializeReferrers(const base::ListValue& referral_list) { 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int format_version = -1; 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (referral_list.GetSize() > 0 && 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) referral_list.GetInteger(0, &format_version) && 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format_version == kPredictorReferrerVersion) { 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 1; i < referral_list.GetSize(); ++i) { 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::ListValue* motivator; 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!referral_list.GetList(i, &motivator)) { 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string motivating_url_spec; 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!motivator->GetString(0, &motivating_url_spec)) { 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Value* subresource_list; 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!motivator->Get(1, &subresource_list)) { 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) referrers_[GURL(motivating_url_spec)].Deserialize(*subresource_list); 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::DeserializeReferrersThenDelete( 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ListValue* referral_list) { 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeserializeReferrers(*referral_list); 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete referral_list; 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::DiscardInitialNavigationHistory() { 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (initial_observer_.get()) 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initial_observer_->DiscardInitialNavigationHistory(); 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::FinalizeInitializationOnIOThread( 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const UrlList& startup_urls, 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ListValue* referral_list, 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOThread* io_thread, 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool predictor_enabled) { 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) predictor_enabled_ = predictor_enabled; 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initial_observer_.reset(new InitialObserver()); 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_resolver_ = io_thread->globals()->host_resolver.get(); 8103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch preconnect_usage_.reset(new PreconnectUsage()); 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // base::WeakPtrFactory instances need to be created and destroyed 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // on the same thread. The predictor lives on the IO thread and will die 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from there so now that we're on the IO thread we need to properly 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // initialize the base::WeakPtrFactory. 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(groby): Check if WeakPtrFactory has the same constraint. 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_factory_.reset(new base::WeakPtrFactory<Predictor>(this)); 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prefetch these hostnames on startup. 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DnsPrefetchMotivatedList(startup_urls, UrlInfo::STARTUP_LIST_MOTIVATED); 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeserializeReferrersThenDelete(referral_list); 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//----------------------------------------------------------------------------- 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This section intermingles prefetch results with actual browser HTTP 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// network activity. It supports calculating of the benefit of a prefetch, as 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// well as recording what prefetched hostname resolutions might be potentially 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// helpful during the next chrome-startup. 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//----------------------------------------------------------------------------- 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::LearnAboutInitialNavigation(const GURL& url) { 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!predictor_enabled_ || NULL == initial_observer_.get() ) 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initial_observer_->Append(url, this); 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This API is only used in the browser process. 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It is called from an IPC message originating in the renderer. It currently 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// includes both Page-Scan, and Link-Hover prefetching. 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(jar): Separate out link-hover prefetching, and page-scan results. 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::DnsPrefetchList(const NameList& hostnames) { 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(jar): Push GURL transport further back into renderer, but this will 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // require a Webkit change in the observer :-/. 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlList urls; 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (NameList::const_iterator it = hostnames.begin(); 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it < hostnames.end(); 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it) { 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) urls.push_back(GURL("http://" + *it + ":80")); 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DnsPrefetchMotivatedList(urls, UrlInfo::PAGE_SCAN_MOTIVATED); 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::DnsPrefetchMotivatedList( 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const UrlList& urls, 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo::ResolutionMotivation motivation) { 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::CurrentlyOn(BrowserThread::IO)); 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!predictor_enabled_) 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (BrowserThread::CurrentlyOn(BrowserThread::IO)) { 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResolveList(urls, motivation); 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::IO, 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&Predictor::ResolveList, base::Unretained(this), 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) urls, motivation)); 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//----------------------------------------------------------------------------- 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Functions to handle saving of hostnames from one session to the next, to 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// expedite startup times. 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void SaveDnsPrefetchStateForNextStartupAndTrimOnIOThread( 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ListValue* startup_list, 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ListValue* referral_list, 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WaitableEvent* completion, 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Predictor* predictor) { 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NULL == predictor) { 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completion->Signal(); 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) predictor->SaveDnsPrefetchStateForNextStartupAndTrim( 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) startup_list, referral_list, completion); 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::SaveStateForNextStartupAndTrim(PrefService* prefs) { 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!predictor_enabled_) 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WaitableEvent completion(true, false); 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListPrefUpdate update_startup_list(prefs, prefs::kDnsPrefetchingStartupList); 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListPrefUpdate update_referral_list(prefs, 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs::kDnsPrefetchingHostReferralList); 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (BrowserThread::CurrentlyOn(BrowserThread::IO)) { 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveDnsPrefetchStateForNextStartupAndTrimOnIOThread( 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) update_startup_list.Get(), 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) update_referral_list.Get(), 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &completion, 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this); 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool posted = BrowserThread::PostTask( 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::IO, 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind( 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &SaveDnsPrefetchStateForNextStartupAndTrimOnIOThread, 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) update_startup_list.Get(), 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) update_referral_list.Get(), 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &completion, 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(jar): Synchronous waiting for the IO thread is a potential source 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to deadlocks and should be investigated. See http://crbug.com/78451. 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(posted); 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (posted) { 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://crbug.com/124954 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::ScopedAllowWait allow_wait; 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completion.Wait(); 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::SaveDnsPrefetchStateForNextStartupAndTrim( 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ListValue* startup_list, 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ListValue* referral_list, 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WaitableEvent* completion) { 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (initial_observer_.get()) 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initial_observer_->GetInitialDnsResolutionList(startup_list); 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Do at least one trim at shutdown, in case the user wasn't running long 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // enough to do any regular trimming of referrers. 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TrimReferrersNow(); 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SerializeReferrers(referral_list); 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completion->Signal(); 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::EnablePredictor(bool enable) { 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::CurrentlyOn(BrowserThread::IO)); 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (BrowserThread::CurrentlyOn(BrowserThread::IO)) { 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnablePredictorOnIOThread(enable); 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::IO, 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&Predictor::EnablePredictorOnIOThread, 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(this), enable)); 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::EnablePredictorOnIOThread(bool enable) { 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) predictor_enabled_ = enable; 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 96790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void Predictor::PreconnectUrl(const GURL& url, 96890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const GURL& first_party_for_cookies, 96990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) UrlInfo::ResolutionMotivation motivation, 97090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int count) { 97190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || 97290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) BrowserThread::CurrentlyOn(BrowserThread::IO)); 97390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 97490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (BrowserThread::CurrentlyOn(BrowserThread::IO)) { 97590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) PreconnectUrlOnIOThread(url, first_party_for_cookies, motivation, count); 97690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 97790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) BrowserThread::PostTask( 97890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) BrowserThread::IO, 97990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) FROM_HERE, 98090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Bind(&Predictor::PreconnectUrlOnIOThread, 98190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Unretained(this), url, first_party_for_cookies, 98290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) motivation, count)); 98390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 98490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 98590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 98690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void Predictor::PreconnectUrlOnIOThread( 9873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch const GURL& url, 9883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch const GURL& first_party_for_cookies, 9893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch UrlInfo::ResolutionMotivation motivation, 9903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch int count) { 9913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (motivation == UrlInfo::MOUSE_OVER_MOTIVATED) 9923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch RecordPreconnectTrigger(url); 99390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 994f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) AdviseProxy(url, motivation, true /* is_preconnect */); 995f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 996868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PreconnectOnIOThread(url, 997868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) first_party_for_cookies, 998868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) motivation, 999868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) count, 1000868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) url_request_context_getter_.get()); 100190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 100290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10033240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid Predictor::RecordPreconnectTrigger(const GURL& url) { 10043240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 10053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (preconnect_usage_) 10063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch preconnect_usage_->ObservePreconnect(url); 10073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch} 10083240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 10093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid Predictor::RecordPreconnectNavigationStat( 10103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch const std::vector<GURL>& url_chain, 10113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch bool is_subresource) { 10123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 10133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 10143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (preconnect_usage_) 10153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch preconnect_usage_->ObserveNavigationChain(url_chain, is_subresource); 10163240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch} 10173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 10183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid Predictor::RecordLinkNavigation(const GURL& url) { 10193240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 10203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (preconnect_usage_) 10213240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch preconnect_usage_->ObserveLinkNavigation(url); 102290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 102390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 102490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void Predictor::PredictFrameSubresources(const GURL& url, 102590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const GURL& first_party_for_cookies) { 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::CurrentlyOn(BrowserThread::IO)); 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!predictor_enabled_) 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(url.GetWithEmptyPath(), url); 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add one pass through the message loop to allow current navigation to 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // proceed. 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (BrowserThread::CurrentlyOn(BrowserThread::IO)) { 103490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) PrepareFrameSubresources(url, first_party_for_cookies); 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::IO, 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&Predictor::PrepareFrameSubresources, 104090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Unretained(this), url, first_party_for_cookies)); 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1044f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void Predictor::AdviseProxy(const GURL& url, 1045f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) UrlInfo::ResolutionMotivation motivation, 1046f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool is_preconnect) { 1047f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!proxy_advisor_) 1048f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 1049f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1050f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || 1051f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BrowserThread::CurrentlyOn(BrowserThread::IO)); 1052f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1053f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (BrowserThread::CurrentlyOn(BrowserThread::IO)) { 1054f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) AdviseProxyOnIOThread(url, motivation, is_preconnect); 1055f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 1056f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BrowserThread::PostTask( 1057f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BrowserThread::IO, 1058f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) FROM_HERE, 1059f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Bind(&Predictor::AdviseProxyOnIOThread, 1060f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Unretained(this), url, motivation, is_preconnect)); 1061f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1062f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 1063f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum SubresourceValue { 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRECONNECTION, 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRERESOLUTION, 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TOO_NEW, 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SUBRESOURCE_VALUE_MAX 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 107190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void Predictor::PrepareFrameSubresources(const GURL& url, 107290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const GURL& first_party_for_cookies) { 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(url.GetWithEmptyPath(), url); 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Referrers::iterator it = referrers_.find(url); 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (referrers_.end() == it) { 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only when we don't know anything about this url, make 2 connections 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // available. We could do this completely via learning (by prepopulating 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the referrer_ list with this expected value), but it would swell the 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // size of the list with all the "Leaf" nodes in the tree (nodes that don't 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // load any subresources). If we learn about this resource, we will instead 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // provide a more carefully estimated preconnection count. 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (preconnect_enabled_) { 108490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) PreconnectUrlOnIOThread(url, first_party_for_cookies, 108590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) UrlInfo::SELF_REFERAL_MOTIVATED, 2); 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Referrer* referrer = &(it->second); 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) referrer->IncrementUseCount(); 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const UrlInfo::ResolutionMotivation motivation = 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo::LEARNED_REFERAL_MOTIVATED; 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Referrer::iterator future_url = referrer->begin(); 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) future_url != referrer->end(); ++future_url) { 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SubresourceValue evalution(TOO_NEW); 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double connection_expectation = future_url->second.subresource_use_rate(); 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS("Net.PreconnectSubresourceExpectation", 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(connection_expectation * 100), 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10, 5000, 50); 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) future_url->second.ReferrerWasObserved(); 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (preconnect_enabled_ && 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connection_expectation > kPreconnectWorthyExpectedValue) { 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evalution = PRECONNECTION; 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) future_url->second.IncrementPreconnectionCount(); 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = static_cast<int>(std::ceil(connection_expectation)); 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url.host() == future_url->first.host()) 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++count; 110990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) PreconnectUrlOnIOThread(future_url->first, first_party_for_cookies, 111090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) motivation, count); 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (connection_expectation > kDNSPreresolutionWorthyExpectedValue) { 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evalution = PRERESOLUTION; 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) future_url->second.preresolution_increment(); 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo* queued_info = AppendToResolutionQueue(future_url->first, 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) motivation); 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (queued_info) 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) queued_info->SetReferringHostname(url); 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Net.PreconnectSubresourceEval", evalution, 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SUBRESOURCE_VALUE_MAX); 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::OnLookupFinished(LookupRequest* request, const GURL& url, 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool found) { 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LookupFinished(request, url, found); 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_lookups_.erase(request); 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete request; 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSomeQueuedResolutions(); 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::LookupFinished(LookupRequest* request, const GURL& url, 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool found) { 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo* info = &results_[url]; 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(info->HasUrl(url)); 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (info->is_marked_to_delete()) { 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results_.erase(url); 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found) 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->SetFoundState(); 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->SetNoSuchNameState(); 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UrlInfo* Predictor::AppendToResolutionQueue( 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo::ResolutionMotivation motivation) { 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(url.has_host()); 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shutdown_) 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo* info = &results_[url]; 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->SetUrl(url); // Initialize or DCHECK. 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(jar): I need to discard names that have long since expired. 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Currently we only add to the domain map :-/ 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(info->HasUrl(url)); 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!info->NeedsDnsUpdate()) { 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->DLogResultsStats("DNS PrefetchNotUpdated"); 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) AdviseProxy(url, motivation, false /* is_preconnect */); 1172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (proxy_advisor_ && proxy_advisor_->WouldProxyURL(url)) { 1173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) info->DLogResultsStats("DNS PrefetchForProxiedRequest"); 1174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return NULL; 1175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->SetQueuedState(motivation); 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) work_queue_.Push(url, motivation); 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartSomeQueuedResolutions(); 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return info; 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Predictor::CongestionControlPerformed(UrlInfo* info) { 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: queue_duration is ONLY valid after we go to assigned state. 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (info->queue_duration() < max_dns_queue_delay_) 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to discard all entries in our queue, as we're keeping them waiting 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // too long. By doing this, we'll have a chance to quickly service urgent 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // resolutions, and not have a bogged down system. 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (true) { 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->RemoveFromQueue(); 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (work_queue_.IsEmpty()) 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info = &results_[work_queue_.Pop()]; 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->SetAssignedState(); 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::StartSomeQueuedResolutions() { 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!work_queue_.IsEmpty() && 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_lookups_.size() < max_concurrent_dns_lookups_) { 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL url(work_queue_.Pop()); 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo* info = &results_[url]; 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(info->HasUrl(url)); 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->SetAssignedState(); 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CongestionControlPerformed(info)) { 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(work_queue_.IsEmpty()); 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LookupRequest* request = new LookupRequest(this, host_resolver_, url); 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int status = request->Start(); 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status == net::ERR_IO_PENDING) { 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Will complete asynchronously. 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_lookups_.insert(request); 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) peak_pending_lookups_ = std::max(peak_pending_lookups_, 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_lookups_.size()); 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Completed synchronously (was already cached by HostResolver), or else 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // there was (equivalently) some network error that prevents us from 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // finding the name. Status net::OK means it was "found." 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LookupFinished(request, url, status == net::OK); 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete request; 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::TrimReferrers() { 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!urls_being_trimmed_.empty()) 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // There is incremental trimming in progress already. 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check to see if it is time to trim yet. 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks now = base::TimeTicks::Now(); 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (now < next_trim_time_) 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_trim_time_ = now + TimeDelta::FromHours(kDurationBetweenTrimmingsHours); 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadUrlsForTrimming(); 12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PostIncrementalTrimTask(); 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::LoadUrlsForTrimming() { 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(urls_being_trimmed_.empty()); 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Referrers::const_iterator it = referrers_.begin(); 12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != referrers_.end(); ++it) 12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) urls_being_trimmed_.push_back(it->first); 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("Net.PredictionTrimSize", urls_being_trimmed_.size()); 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::PostIncrementalTrimTask() { 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (urls_being_trimmed_.empty()) 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TimeDelta kDurationBetweenTrimmingIncrements = 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta::FromSeconds(kDurationBetweenTrimmingIncrementsSeconds); 126190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&Predictor::IncrementalTrimReferrers, 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_factory_->GetWeakPtr(), false), 12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kDurationBetweenTrimmingIncrements); 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::IncrementalTrimReferrers(bool trim_all_now) { 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t trim_count = urls_being_trimmed_.size(); 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!trim_all_now) 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trim_count = std::min(trim_count, kUrlsTrimmedPerIncrement); 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (trim_count-- != 0) { 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Referrers::iterator it = referrers_.find(urls_being_trimmed_.back()); 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) urls_being_trimmed_.pop_back(); 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it == referrers_.end()) 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // Defensive code: It got trimmed away already. 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!it->second.Trim(kReferrerTrimRatio, kDiscardableExpectedValue)) 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) referrers_.erase(it); 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PostIncrementalTrimTask(); 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void Predictor::AdviseProxyOnIOThread(const GURL& url, 1284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) UrlInfo::ResolutionMotivation motivation, 1285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool is_preconnect) { 1286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!proxy_advisor_) 1287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 1288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) proxy_advisor_->Advise(url, motivation, is_preconnect); 1290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 1291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------- End IO methods. ------------------------------------- 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//----------------------------------------------------------------------------- 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Predictor::HostNameQueue::HostNameQueue() { 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Predictor::HostNameQueue::~HostNameQueue() { 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::HostNameQueue::Push(const GURL& url, 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo::ResolutionMotivation motivation) { 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (motivation) { 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case UrlInfo::STATIC_REFERAL_MOTIVATED: 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case UrlInfo::LEARNED_REFERAL_MOTIVATED: 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case UrlInfo::MOUSE_OVER_MOTIVATED: 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rush_queue_.push(url); 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background_queue_.push(url); 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Predictor::HostNameQueue::IsEmpty() const { 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rush_queue_.empty() && background_queue_.empty(); 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL Predictor::HostNameQueue::Pop() { 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!IsEmpty()); 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::queue<GURL> *queue(rush_queue_.empty() ? &background_queue_ 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : &rush_queue_); 13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url(queue->front()); 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) queue->pop(); 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return url; 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//----------------------------------------------------------------------------- 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Member definitions for InitialObserver class. 13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Predictor::InitialObserver::InitialObserver() { 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Predictor::InitialObserver::~InitialObserver() { 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::InitialObserver::Append(const GURL& url, 13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Predictor* predictor) { 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(rlp): Do we really need the predictor check here? 13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NULL == predictor) 13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kStartupResolutionCount <= first_navigations_.size()) 13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(url.SchemeIsHTTPOrHTTPS()); 13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(url, Predictor::CanonicalizeUrl(url)); 13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (first_navigations_.find(url) == first_navigations_.end()) 13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_navigations_[url] = base::TimeTicks::Now(); 13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::InitialObserver::GetInitialDnsResolutionList( 13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ListValue* startup_list) { 13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(startup_list); 13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) startup_list->Clear(); 13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(0u, startup_list->GetSize()); 13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) startup_list->Append( 13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new base::FundamentalValue(kPredictorStartupFormatVersion)); 13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (FirstNavigations::iterator it = first_navigations_.begin(); 13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != first_navigations_.end(); 13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it) { 13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(it->first == Predictor::CanonicalizeUrl(it->first)); 13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) startup_list->Append(new StringValue(it->first.spec())); 13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Predictor::InitialObserver::GetFirstResolutionsHtml( 13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* output) { 13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo::UrlInfoTable resolution_list; 13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (FirstNavigations::iterator it(first_navigations_.begin()); 13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != first_navigations_.end(); 13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it++) { 13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo info; 13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.SetUrl(it->first); 13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.set_time(it->second); 13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resolution_list.push_back(info); 13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo::GetHtmlTable(resolution_list, 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Future startups will prefetch DNS records for ", false, output); 13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//----------------------------------------------------------------------------- 13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper functions 13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//----------------------------------------------------------------------------- 13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL Predictor::CanonicalizeUrl(const GURL& url) { 13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url.has_host()) 13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GURL::EmptyGURL(); 13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string scheme; 14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url.has_scheme()) { 14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheme = url.scheme(); 14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (scheme != "http" && scheme != "https") 14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GURL::EmptyGURL(); 14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url.has_port()) 14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return url.GetWithEmptyPath(); 14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheme = "http"; 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we omit a port, it will default to 80 or 443 as appropriate. 14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string colon_plus_port; 14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url.has_port()) 14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) colon_plus_port = ":" + url.port(); 14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GURL(scheme + "://" + url.host() + colon_plus_port); 14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SimplePredictor::InitNetworkPredictor( 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrefService* user_prefs, 14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrefService* local_state, 14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOThread* io_thread, 14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequestContextGetter* getter) { 14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Empty function for unittests. 14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void SimplePredictor::ShutdownOnUIThread() { 14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetShutdown(true); 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace chrome_browser_net 1431