url_info.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2006-2010 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/field_trial.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/format_macros.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/histogram.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::Time; 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeDelta; 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeTicks; 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace chrome_browser_net { 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool detailed_logging_enabled = false; 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use command line switch to enable detailed logging. 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid EnablePredictorDetailedLog(bool enable) { 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch detailed_logging_enabled = enable; 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint UrlInfo::sequence_counter = 1; 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool UrlInfo::NeedsDnsUpdate() { 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (state_) { 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case PENDING: // Just now created info. 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case QUEUED: // In queue. 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case ASSIGNED: // It's being resolved. 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case ASSIGNED_BUT_MARKED: // It's being resolved. 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; // We're already working on it 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NO_SUCH_NAME: // Lookup failed. 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case FOUND: // Lookup succeeded. 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return !IsStillCached(); // See if DNS cache expired. 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst TimeDelta UrlInfo::kNullDuration(TimeDelta::FromMilliseconds(-1)); 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Common low end TTL for sites is 5 minutes. However, DNS servers give us 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the remaining time, not the original 5 minutes. Hence it doesn't much matter 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// whether we found something in the local cache, or an ISP cache, it will 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// on average be 2.5 minutes before it expires. We could try to model this with 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 180 seconds, but simpler is just to do the lookups all the time (wasting 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// OS calls(?)), and let that OS cache decide what to do (with TTL in hand). 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// We use a small time to help get some duplicate suppression, in case a page 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// has a TON of copies of the same domain name, so that we don't thrash the OS 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// to death. Hopefully it is small enough that we're not hurting our cache hit 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// rate (i.e., we could always ask the OS). 673345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTimeDelta UrlInfo::cache_expiration_duration_(TimeDelta::FromSeconds(5)); 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst TimeDelta UrlInfo::kMaxNonNetworkDnsLookupDuration( 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeDelta::FromMilliseconds(15)); 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Used by test ONLY. The value is otherwise constant. 733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// static 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UrlInfo::set_cache_expiration(TimeDelta time) { 753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick cache_expiration_duration_ = time; 763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// static 793345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTimeDelta UrlInfo::get_cache_expiration() { 803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return cache_expiration_duration_; 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UrlInfo::SetQueuedState(ResolutionMotivation motivation) { 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(PENDING == state_ || FOUND == state_ || NO_SUCH_NAME == state_); 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch old_prequeue_state_ = state_; 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = QUEUED; 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch queue_duration_ = resolve_duration_ = kNullDuration; 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetMotivation(motivation); 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetDuration(); // Set time_ 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DLogResultsStats("DNS Prefetch in queue"); 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UrlInfo::SetAssignedState() { 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(QUEUED == state_); 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = ASSIGNED; 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch queue_duration_ = GetDuration(); 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DLogResultsStats("DNS Prefetch assigned"); 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_TIMES("DNS.PrefetchQueue", queue_duration_); 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UrlInfo::RemoveFromQueue() { 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(ASSIGNED == state_); 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = old_prequeue_state_; 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DLogResultsStats("DNS Prefetch reset to prequeue"); 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static const TimeDelta kBoundary = TimeDelta::FromSeconds(2); 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (queue_duration_ > kBoundary) { 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_MEDIUM_TIMES("DNS.QueueRecycledDeltaOver2", 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch queue_duration_ - kBoundary); 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make a custom linear histogram for the region from 0 to boundary. 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const size_t kBucketCount = 52; 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static scoped_refptr<Histogram> histogram = LinearHistogram::FactoryTimeGet( 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "DNS.QueueRecycledUnder2", TimeDelta(), kBoundary, kBucketCount, 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Histogram::kUmaTargetedHistogramFlag); 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch histogram->AddTime(queue_duration_); 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UrlInfo::SetPendingDeleteState() { 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(ASSIGNED == state_ || ASSIGNED_BUT_MARKED == state_); 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = ASSIGNED_BUT_MARKED; 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UrlInfo::SetFoundState() { 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(ASSIGNED == state_); 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = FOUND; 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resolve_duration_ = GetDuration(); 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (kMaxNonNetworkDnsLookupDuration <= resolve_duration_) { 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_CUSTOM_TIMES("DNS.PrefetchResolution", resolve_duration_, 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kMaxNonNetworkDnsLookupDuration, TimeDelta::FromMinutes(15), 100); 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sequence_number_ = sequence_counter++; 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DLogResultsStats("DNS PrefetchFound"); 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UrlInfo::SetNoSuchNameState() { 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(ASSIGNED == state_); 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = NO_SUCH_NAME; 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resolve_duration_ = GetDuration(); 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (kMaxNonNetworkDnsLookupDuration <= resolve_duration_) { 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DHISTOGRAM_TIMES("DNS.PrefetchNotFoundName", resolve_duration_); 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sequence_number_ = sequence_counter++; 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DLogResultsStats("DNS PrefetchNotFound"); 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UrlInfo::SetUrl(const GURL& url) { 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (url_.is_empty()) // Not yet initialized. 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_ = url; 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(url_, url); 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// IsStillCached() guesses if the DNS cache still has IP data, 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// or at least remembers results about "not finding host." 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool UrlInfo::IsStillCached() const { 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(FOUND == state_ || NO_SUCH_NAME == state_); 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Default MS OS does not cache failures. Hence we could return false almost 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // all the time for that case. However, we'd never try again to prefetch 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the value if we returned false that way. Hence we'll just let the lookup 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // time out the same way as FOUND case. 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (sequence_counter - sequence_number_ > kMaxGuaranteedDnsCacheSize) 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeDelta time_since_resolution = TimeTicks::Now() - time_; 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return time_since_resolution < cache_expiration_duration_; 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UrlInfo::DLogResultsStats(const char* message) const { 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!detailed_logging_enabled) 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DLOG(INFO) << "\t" << message << "\tq=" 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << queue_duration().InMilliseconds() << "ms,\tr=" 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << resolve_duration().InMilliseconds() << "ms\tp=" 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << sequence_number_ 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << "\t" << url_.spec(); 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This last section supports HTML output, such as seen in about:dns. 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Preclude any possibility of Java Script or markup in the text, by only 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// allowing alphanumerics, '.', '-', ':', and whitespace. 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic std::string RemoveJs(const std::string& text) { 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string output(text); 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t length = output.length(); 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < length; i++) { 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch char next = output[i]; 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (isalnum(next) || isspace(next) || strchr(".-:/", next) != NULL) 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch output[i] = '?'; 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return output; 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass MinMaxAverage { 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MinMaxAverage() 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : sum_(0), square_sum_(0), count_(0), 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch minimum_(kint64max), maximum_(kint64min) { 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Return values for use in printf formatted as "%d" 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int sample(int64 value) { 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sum_ += value; 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch square_sum_ += value * value; 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch count_++; 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch minimum_ = std::min(minimum_, value); 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch maximum_ = std::max(maximum_, value); 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return static_cast<int>(value); 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int minimum() const { return static_cast<int>(minimum_); } 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int maximum() const { return static_cast<int>(maximum_); } 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int average() const { return static_cast<int>(sum_/count_); } 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int sum() const { return static_cast<int>(sum_); } 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int standard_deviation() const { 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch double average = static_cast<float>(sum_) / count_; 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch double variance = static_cast<float>(square_sum_)/count_ 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch - average * average; 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return static_cast<int>(floor(sqrt(variance) + .5)); 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 sum_; 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 square_sum_; 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int count_; 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 minimum_; 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 maximum_; 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // DISALLOW_COPY_AND_ASSIGN(MinMaxAverage); 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic std::string HoursMinutesSeconds(int seconds) { 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string result; 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int print_seconds = seconds % 60; 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int minutes = seconds / 60; 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int print_minutes = minutes % 60; 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int print_hours = minutes/60; 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (print_hours) 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StringAppendF(&result, "%.2d:", print_hours); 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (print_hours || print_minutes) 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StringAppendF(&result, "%2.2d:", print_minutes); 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StringAppendF(&result, "%2.2d", print_seconds); 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 2533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid UrlInfo::GetHtmlTable(const UrlInfoTable host_infos, 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* description, 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool brief, 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string* output) { 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (0 == host_infos.size()) 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch output->append(description); 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StringAppendF(output, "%" PRIuS " %s", host_infos.size(), 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (1 == host_infos.size()) ? "hostname" : "hostnames"); 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (brief) { 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch output->append("<br><br>"); 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick output->append("<br><table border=1>" 2693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "<tr><th>Host name</th>" 2703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "<th>How long ago<br>(HH:MM:SS)</th>" 2713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "<th>Motivation</th>" 2723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "</tr>"); 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const char* row_format = "<tr align=right><td>%s</td>" // Host name. 2753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "<td>%s</td>" // How long ago. 2763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "<td>%s</td>" // Motivation. 2773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "</tr>"; 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Print bulk of table, and gather stats at same time. 2803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick MinMaxAverage queue, when; 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeTicks current_time = TimeTicks::Now(); 2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (UrlInfoTable::const_iterator it(host_infos.begin()); 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it != host_infos.end(); it++) { 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch queue.sample((it->queue_duration_.InMilliseconds())); 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StringAppendF(output, row_format, 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RemoveJs(it->url_.spec()).c_str(), 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HoursMinutesSeconds(when.sample( 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (current_time - it->time_).InSeconds())).c_str(), 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it->GetAsciiMotivation().c_str()); 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch output->append("</table>"); 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#ifndef NDEBUG 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StringAppendF(output, 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Prefetch Queue Durations: min=%d, avg=%d, max=%d<br><br>", 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch queue.minimum(), queue.average(), queue.maximum()); 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch output->append("<br>"); 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UrlInfo::SetMotivation(ResolutionMotivation motivation) { 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch motivation_ = motivation; 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (motivation < LINKED_MAX_MOTIVATED) 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch was_linked_ = true; 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string UrlInfo::GetAsciiMotivation() const { 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (motivation_) { 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case MOUSE_OVER_MOTIVATED: 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return "[mouse-over]"; 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case PAGE_SCAN_MOTIVATED: 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return "[page scan]"; 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case OMNIBOX_MOTIVATED: 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return "[omnibox]"; 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case STARTUP_LIST_MOTIVATED: 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return "[startup list]"; 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NO_PREFETCH_MOTIVATION: 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return "n/a"; 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case STATIC_REFERAL_MOTIVATED: 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return RemoveJs(referring_url_.spec()) + "*"; 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case LEARNED_REFERAL_MOTIVATED: 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return RemoveJs(referring_url_.spec()); 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ""; 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace chrome_browser_net 337