1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/net/url_info.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <math.h> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <algorithm> 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/format_macros.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h" 14731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/histogram.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::Time; 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeDelta; 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeTicks; 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace chrome_browser_net { 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool detailed_logging_enabled = false; 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use command line switch to enable detailed logging. 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid EnablePredictorDetailedLog(bool enable) { 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch detailed_logging_enabled = enable; 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint UrlInfo::sequence_counter = 1; 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 33731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickUrlInfo::UrlInfo() 34731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick : state_(PENDING), 35731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick old_prequeue_state_(state_), 36731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick resolve_duration_(kNullDuration), 37731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick queue_duration_(kNullDuration), 38731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick sequence_number_(0), 39731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick motivation_(NO_PREFETCH_MOTIVATION), 40731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick was_linked_(false) { 41731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 42731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 43731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickUrlInfo::~UrlInfo() {} 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool UrlInfo::NeedsDnsUpdate() { 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (state_) { 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case PENDING: // Just now created info. 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case QUEUED: // In queue. 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case ASSIGNED: // It's being resolved. 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case ASSIGNED_BUT_MARKED: // It's being resolved. 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; // We're already working on it 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NO_SUCH_NAME: // Lookup failed. 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case FOUND: // Lookup succeeded. 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return !IsStillCached(); // See if DNS cache expired. 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst TimeDelta UrlInfo::kNullDuration(TimeDelta::FromMilliseconds(-1)); 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Common low end TTL for sites is 5 minutes. However, DNS servers give us 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the remaining time, not the original 5 minutes. Hence it doesn't much matter 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// whether we found something in the local cache, or an ISP cache, it will 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// on average be 2.5 minutes before it expires. We could try to model this with 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 180 seconds, but simpler is just to do the lookups all the time (wasting 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// OS calls(?)), and let that OS cache decide what to do (with TTL in hand). 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// We use a small time to help get some duplicate suppression, in case a page 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// has a TON of copies of the same domain name, so that we don't thrash the OS 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// to death. Hopefully it is small enough that we're not hurting our cache hit 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// rate (i.e., we could always ask the OS). 773345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTimeDelta UrlInfo::cache_expiration_duration_(TimeDelta::FromSeconds(5)); 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst TimeDelta UrlInfo::kMaxNonNetworkDnsLookupDuration( 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeDelta::FromMilliseconds(15)); 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Used by test ONLY. The value is otherwise constant. 833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// static 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UrlInfo::set_cache_expiration(TimeDelta time) { 853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick cache_expiration_duration_ = time; 863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// static 893345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTimeDelta UrlInfo::get_cache_expiration() { 903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return cache_expiration_duration_; 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UrlInfo::SetQueuedState(ResolutionMotivation motivation) { 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(PENDING == state_ || FOUND == state_ || NO_SUCH_NAME == state_); 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch old_prequeue_state_ = state_; 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = QUEUED; 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch queue_duration_ = resolve_duration_ = kNullDuration; 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetMotivation(motivation); 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetDuration(); // Set time_ 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DLogResultsStats("DNS Prefetch in queue"); 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UrlInfo::SetAssignedState() { 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(QUEUED == state_); 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = ASSIGNED; 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch queue_duration_ = GetDuration(); 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DLogResultsStats("DNS Prefetch assigned"); 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_TIMES("DNS.PrefetchQueue", queue_duration_); 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UrlInfo::RemoveFromQueue() { 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(ASSIGNED == state_); 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = old_prequeue_state_; 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DLogResultsStats("DNS Prefetch reset to prequeue"); 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static const TimeDelta kBoundary = TimeDelta::FromSeconds(2); 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (queue_duration_ > kBoundary) { 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_MEDIUM_TIMES("DNS.QueueRecycledDeltaOver2", 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch queue_duration_ - kBoundary); 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make a custom linear histogram for the region from 0 to boundary. 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const size_t kBucketCount = 52; 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static base::Histogram* histogram(NULL); 124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!histogram) 125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen histogram = base::LinearHistogram::FactoryTimeGet( 126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "DNS.QueueRecycledUnder2", TimeDelta(), kBoundary, kBucketCount, 127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::Histogram::kUmaTargetedHistogramFlag); 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch histogram->AddTime(queue_duration_); 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UrlInfo::SetPendingDeleteState() { 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(ASSIGNED == state_ || ASSIGNED_BUT_MARKED == state_); 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = ASSIGNED_BUT_MARKED; 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UrlInfo::SetFoundState() { 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(ASSIGNED == state_); 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = FOUND; 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resolve_duration_ = GetDuration(); 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (kMaxNonNetworkDnsLookupDuration <= resolve_duration_) { 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_CUSTOM_TIMES("DNS.PrefetchResolution", resolve_duration_, 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kMaxNonNetworkDnsLookupDuration, TimeDelta::FromMinutes(15), 100); 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sequence_number_ = sequence_counter++; 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DLogResultsStats("DNS PrefetchFound"); 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UrlInfo::SetNoSuchNameState() { 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(ASSIGNED == state_); 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = NO_SUCH_NAME; 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resolve_duration_ = GetDuration(); 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (kMaxNonNetworkDnsLookupDuration <= resolve_duration_) { 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DHISTOGRAM_TIMES("DNS.PrefetchNotFoundName", resolve_duration_); 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sequence_number_ = sequence_counter++; 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DLogResultsStats("DNS PrefetchNotFound"); 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UrlInfo::SetUrl(const GURL& url) { 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (url_.is_empty()) // Not yet initialized. 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_ = url; 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(url_, url); 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// IsStillCached() guesses if the DNS cache still has IP data, 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// or at least remembers results about "not finding host." 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool UrlInfo::IsStillCached() const { 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(FOUND == state_ || NO_SUCH_NAME == state_); 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Default MS OS does not cache failures. Hence we could return false almost 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // all the time for that case. However, we'd never try again to prefetch 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the value if we returned false that way. Hence we'll just let the lookup 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // time out the same way as FOUND case. 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (sequence_counter - sequence_number_ > kMaxGuaranteedDnsCacheSize) 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeDelta time_since_resolution = TimeTicks::Now() - time_; 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return time_since_resolution < cache_expiration_duration_; 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UrlInfo::DLogResultsStats(const char* message) const { 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!detailed_logging_enabled) 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 187513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DVLOG(1) << "\t" << message << "\tq=" << queue_duration().InMilliseconds() 188513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << "ms,\tr=" << resolve_duration().InMilliseconds() 189513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << "ms,\tp=" << sequence_number_ << "\t" << url_.spec(); 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This last section supports HTML output, such as seen in about:dns. 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Preclude any possibility of Java Script or markup in the text, by only 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// allowing alphanumerics, '.', '-', ':', and whitespace. 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic std::string RemoveJs(const std::string& text) { 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string output(text); 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t length = output.length(); 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < length; i++) { 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch char next = output[i]; 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (isalnum(next) || isspace(next) || strchr(".-:/", next) != NULL) 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch output[i] = '?'; 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return output; 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass MinMaxAverage { 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MinMaxAverage() 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : sum_(0), square_sum_(0), count_(0), 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch minimum_(kint64max), maximum_(kint64min) { 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Return values for use in printf formatted as "%d" 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int sample(int64 value) { 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sum_ += value; 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch square_sum_ += value * value; 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch count_++; 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch minimum_ = std::min(minimum_, value); 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch maximum_ = std::max(maximum_, value); 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return static_cast<int>(value); 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int minimum() const { return static_cast<int>(minimum_); } 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int maximum() const { return static_cast<int>(maximum_); } 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int average() const { return static_cast<int>(sum_/count_); } 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int sum() const { return static_cast<int>(sum_); } 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int standard_deviation() const { 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch double average = static_cast<float>(sum_) / count_; 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch double variance = static_cast<float>(square_sum_)/count_ 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch - average * average; 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return static_cast<int>(floor(sqrt(variance) + .5)); 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 sum_; 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 square_sum_; 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int count_; 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 minimum_; 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 maximum_; 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // DISALLOW_COPY_AND_ASSIGN(MinMaxAverage); 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic std::string HoursMinutesSeconds(int seconds) { 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string result; 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int print_seconds = seconds % 60; 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int minutes = seconds / 60; 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int print_minutes = minutes % 60; 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int print_hours = minutes/60; 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (print_hours) 2554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch base::StringAppendF(&result, "%.2d:", print_hours); 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (print_hours || print_minutes) 2574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch base::StringAppendF(&result, "%2.2d:", print_minutes); 2584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch base::StringAppendF(&result, "%2.2d", print_seconds); 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid UrlInfo::GetHtmlTable(const UrlInfoTable& host_infos, 264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const char* description, 265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool brief, 266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string* output) { 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (0 == host_infos.size()) 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch output->append(description); 2704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch base::StringAppendF(output, "%" PRIuS " %s", host_infos.size(), 2714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch (1 == host_infos.size()) ? "hostname" : "hostnames"); 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (brief) { 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch output->append("<br><br>"); 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick output->append("<br><table border=1>" 2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "<tr><th>Host name</th>" 2803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "<th>How long ago<br>(HH:MM:SS)</th>" 2813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "<th>Motivation</th>" 2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "</tr>"); 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const char* row_format = "<tr align=right><td>%s</td>" // Host name. 2853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "<td>%s</td>" // How long ago. 2863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "<td>%s</td>" // Motivation. 2873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "</tr>"; 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Print bulk of table, and gather stats at same time. 2903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick MinMaxAverage queue, when; 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeTicks current_time = TimeTicks::Now(); 2923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (UrlInfoTable::const_iterator it(host_infos.begin()); 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it != host_infos.end(); it++) { 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch queue.sample((it->queue_duration_.InMilliseconds())); 2954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch base::StringAppendF( 2964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch output, 2974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch row_format, 2984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch RemoveJs(it->url_.spec()).c_str(), 2994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch HoursMinutesSeconds(when.sample( 3004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch (current_time - it->time_).InSeconds())).c_str(), 3014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch it->GetAsciiMotivation().c_str()); 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch output->append("</table>"); 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#ifndef NDEBUG 3064a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch base::StringAppendF( 3074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch output, 3084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch "Prefetch Queue Durations: min=%d, avg=%d, max=%d<br><br>", 3094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch queue.minimum(), queue.average(), queue.maximum()); 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch output->append("<br>"); 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UrlInfo::SetMotivation(ResolutionMotivation motivation) { 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch motivation_ = motivation; 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (motivation < LINKED_MAX_MOTIVATED) 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch was_linked_ = true; 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string UrlInfo::GetAsciiMotivation() const { 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (motivation_) { 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case MOUSE_OVER_MOTIVATED: 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return "[mouse-over]"; 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case PAGE_SCAN_MOTIVATED: 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return "[page scan]"; 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case OMNIBOX_MOTIVATED: 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return "[omnibox]"; 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case STARTUP_LIST_MOTIVATED: 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return "[startup list]"; 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NO_PREFETCH_MOTIVATION: 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return "n/a"; 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case STATIC_REFERAL_MOTIVATED: 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return RemoveJs(referring_url_.spec()) + "*"; 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case LEARNED_REFERAL_MOTIVATED: 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return RemoveJs(referring_url_.spec()); 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ""; 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace chrome_browser_net 350