| Index: chrome/browser/net/predictor_api.cc
|
| ===================================================================
|
| --- chrome/browser/net/predictor_api.cc (revision 96503)
|
| +++ chrome/browser/net/predictor_api.cc (working copy)
|
| @@ -1,651 +0,0 @@
|
| -// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "chrome/browser/net/predictor_api.h"
|
| -
|
| -#include <map>
|
| -#include <string>
|
| -
|
| -#include "base/lazy_instance.h"
|
| -#include "base/metrics/field_trial.h"
|
| -#include "base/stl_util.h"
|
| -#include "base/string_number_conversions.h"
|
| -#include "base/synchronization/waitable_event.h"
|
| -#include "base/threading/thread.h"
|
| -#include "base/values.h"
|
| -#include "chrome/browser/browser_process.h"
|
| -#include "chrome/browser/io_thread.h"
|
| -#include "chrome/browser/net/preconnect.h"
|
| -#include "chrome/browser/net/referrer.h"
|
| -#include "chrome/browser/net/url_info.h"
|
| -#include "chrome/browser/prefs/browser_prefs.h"
|
| -#include "chrome/browser/prefs/pref_service.h"
|
| -#include "chrome/browser/prefs/scoped_user_pref_update.h"
|
| -#include "chrome/browser/prefs/session_startup_pref.h"
|
| -#include "chrome/browser/profiles/profile.h"
|
| -#include "chrome/browser/ui/browser.h"
|
| -#include "chrome/common/chrome_notification_types.h"
|
| -#include "chrome/common/pref_names.h"
|
| -#include "content/browser/browser_thread.h"
|
| -#include "content/common/notification_registrar.h"
|
| -#include "content/common/notification_service.h"
|
| -#include "net/base/host_resolver.h"
|
| -#include "net/base/host_resolver_impl.h"
|
| -
|
| -using base::Time;
|
| -using base::TimeDelta;
|
| -
|
| -namespace chrome_browser_net {
|
| -
|
| -static void DnsPrefetchMotivatedList(const UrlList& urls,
|
| - UrlInfo::ResolutionMotivation motivation);
|
| -
|
| -static UrlList GetPredictedUrlListAtStartup(PrefService* user_prefs,
|
| - PrefService* local_state);
|
| -
|
| -// Given that the underlying Chromium resolver defaults to a total maximum of
|
| -// 8 paralell resolutions, we will avoid any chance of starving navigational
|
| -// resolutions by limiting the number of paralell speculative resolutions.
|
| -// TODO(jar): Move this limitation into the resolver.
|
| -// static
|
| -const size_t PredictorInit::kMaxSpeculativeParallelResolves = 3;
|
| -
|
| -// To control our congestion avoidance system, which discards a queue when
|
| -// resolutions are "taking too long," we need an expected resolution time.
|
| -// Common average is in the range of 300-500ms.
|
| -static const int kExpectedResolutionTimeMs = 500;
|
| -
|
| -// To control the congestion avoidance system, we need an estimate of how many
|
| -// speculative requests may arrive at once. Since we currently only keep 8
|
| -// subresource names for each frame, we'll use that as our basis. Note that
|
| -// when scanning search results lists, we might actually get 10 at a time, and
|
| -// wikipedia can often supply (during a page scan) upwards of 50. In those odd
|
| -// cases, we may discard some of the later speculative requests mistakenly
|
| -// assuming that the resolutions took too long.
|
| -static const int kTypicalSpeculativeGroupSize = 8;
|
| -
|
| -// The next constant specifies an amount of queueing delay that is "too large,"
|
| -// and indicative of problems with resolutions (perhaps due to an overloaded
|
| -// router, or such). When we exceed this delay, congestion avoidance will kick
|
| -// in and all speculations in the queue will be discarded.
|
| -// static
|
| -const int PredictorInit::kMaxSpeculativeResolveQueueDelayMs =
|
| - (kExpectedResolutionTimeMs * kTypicalSpeculativeGroupSize) /
|
| - kMaxSpeculativeParallelResolves;
|
| -
|
| -// A version number for prefs that are saved. This should be incremented when
|
| -// we change the format so that we discard old data.
|
| -static const int kPredictorStartupFormatVersion = 1;
|
| -
|
| -// There will only be one instance ever created of the following Observer class.
|
| -// The InitialObserver lives on the IO thread, and monitors navigations made by
|
| -// the network stack. This is only used to identify startup time resolutions
|
| -// (for re-resolution during our next process startup).
|
| -// TODO(jar): Consider preconnecting at startup, which may be faster than
|
| -// waiting for render process to start and request a connection.
|
| -class InitialObserver {
|
| - public:
|
| - // Recording of when we observed each navigation.
|
| - typedef std::map<GURL, base::TimeTicks> FirstNavigations;
|
| -
|
| - // Potentially add a new URL to our startup list.
|
| - void Append(const GURL& url);
|
| -
|
| - // Get an HTML version of our current planned first_navigations_.
|
| - void GetFirstResolutionsHtml(std::string* output);
|
| -
|
| - // Persist the current first_navigations_ for storage in a list.
|
| - void GetInitialDnsResolutionList(ListValue* startup_list);
|
| -
|
| - // Discards all initial loading history.
|
| - void DiscardInitialNavigationHistory() { first_navigations_.clear(); }
|
| -
|
| - private:
|
| - // List of the first N URL resolutions observed in this run.
|
| - FirstNavigations first_navigations_;
|
| -
|
| - // The number of URLs we'll save for pre-resolving at next startup.
|
| - static const size_t kStartupResolutionCount = 10;
|
| -};
|
| -
|
| -// TODO(willchan): Look at killing this global.
|
| -static InitialObserver* g_initial_observer = NULL;
|
| -
|
| -//------------------------------------------------------------------------------
|
| -// This section contains all the globally accessable API entry points for the
|
| -// DNS Prefetching feature.
|
| -//------------------------------------------------------------------------------
|
| -
|
| -// Status of speculative DNS resolution and speculative TCP/IP connection
|
| -// feature.
|
| -static bool predictor_enabled = true;
|
| -
|
| -// Cached inverted copy of the off_the_record pref.
|
| -static bool on_the_record_switch = true;
|
| -
|
| -// Enable/disable Dns prefetch activity (either via command line, or via pref).
|
| -void EnablePredictor(bool enable) {
|
| - // NOTE: this is invoked on the UI thread.
|
| - predictor_enabled = enable;
|
| -}
|
| -
|
| -void OnTheRecord(bool enable) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - if (on_the_record_switch == enable)
|
| - return;
|
| - on_the_record_switch = enable;
|
| - if (on_the_record_switch)
|
| - g_browser_process->io_thread()->ChangedToOnTheRecord();
|
| -}
|
| -
|
| -void DiscardInitialNavigationHistory() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| - if (g_initial_observer)
|
| - g_initial_observer->DiscardInitialNavigationHistory();
|
| -}
|
| -
|
| -void RegisterUserPrefs(PrefService* user_prefs) {
|
| - user_prefs->RegisterListPref(prefs::kDnsPrefetchingStartupList,
|
| - PrefService::UNSYNCABLE_PREF);
|
| - user_prefs->RegisterListPref(prefs::kDnsPrefetchingHostReferralList,
|
| - PrefService::UNSYNCABLE_PREF);
|
| -}
|
| -
|
| -// When enabled, we use the following instance to service all requests in the
|
| -// browser process.
|
| -// TODO(willchan): Look at killing this.
|
| -static Predictor* g_predictor = NULL;
|
| -
|
| -// This API is only used in the browser process.
|
| -// It is called from an IPC message originating in the renderer. It currently
|
| -// includes both Page-Scan, and Link-Hover prefetching.
|
| -// TODO(jar): Separate out link-hover prefetching, and page-scan results.
|
| -void DnsPrefetchList(const NameList& hostnames) {
|
| - // TODO(jar): Push GURL transport further back into renderer, but this will
|
| - // require a Webkit change in the observer :-/.
|
| - UrlList urls;
|
| - for (NameList::const_iterator it = hostnames.begin();
|
| - it < hostnames.end();
|
| - ++it) {
|
| - urls.push_back(GURL("http://" + *it + ":80"));
|
| - }
|
| -
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| - DnsPrefetchMotivatedList(urls, UrlInfo::PAGE_SCAN_MOTIVATED);
|
| -}
|
| -
|
| -static void DnsPrefetchMotivatedList(
|
| - const UrlList& urls,
|
| - UrlInfo::ResolutionMotivation motivation) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
|
| - BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| - if (!predictor_enabled || NULL == g_predictor)
|
| - return;
|
| -
|
| - if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
|
| - g_predictor->ResolveList(urls, motivation);
|
| - } else {
|
| - BrowserThread::PostTask(
|
| - BrowserThread::IO,
|
| - FROM_HERE,
|
| - NewRunnableMethod(g_predictor,
|
| - &Predictor::ResolveList, urls, motivation));
|
| - }
|
| -}
|
| -
|
| -// This API is used by the autocomplete popup box (where URLs are typed).
|
| -void AnticipateOmniboxUrl(const GURL& url, bool preconnectable) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - if (!predictor_enabled || NULL == g_predictor)
|
| - return;
|
| - if (!url.is_valid() || !url.has_host())
|
| - return;
|
| -
|
| - g_predictor->AnticipateOmniboxUrl(url, preconnectable);
|
| -}
|
| -
|
| -void PreconnectUrlAndSubresources(const GURL& url) {
|
| - if (!predictor_enabled || NULL == g_predictor)
|
| - return;
|
| - if (!url.is_valid() || !url.has_host())
|
| - return;
|
| -
|
| - g_predictor->PreconnectUrlAndSubresources(url);
|
| -}
|
| -
|
| -
|
| -//------------------------------------------------------------------------------
|
| -// This section intermingles prefetch results with actual browser HTTP
|
| -// network activity. It supports calculating of the benefit of a prefetch, as
|
| -// well as recording what prefetched hostname resolutions might be potentially
|
| -// helpful during the next chrome-startup.
|
| -//------------------------------------------------------------------------------
|
| -
|
| -void PredictFrameSubresources(const GURL& url) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| - if (!predictor_enabled || NULL == g_predictor)
|
| - return;
|
| - g_predictor->PredictFrameSubresources(url);
|
| -}
|
| -
|
| -void LearnAboutInitialNavigation(const GURL& url) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| - if (!predictor_enabled || NULL == g_initial_observer )
|
| - return;
|
| - g_initial_observer->Append(url);
|
| -}
|
| -
|
| -void LearnFromNavigation(const GURL& referring_url, const GURL& target_url) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| - if (!predictor_enabled || NULL == g_predictor)
|
| - return;
|
| - g_predictor->LearnFromNavigation(referring_url, target_url);
|
| -}
|
| -
|
| -// The observer class needs to connect starts and finishes of HTTP network
|
| -// resolutions. We use the following type for that map.
|
| -typedef std::map<int, UrlInfo> ObservedResolutionMap;
|
| -
|
| -//------------------------------------------------------------------------------
|
| -// Member definitions for InitialObserver class.
|
| -
|
| -void InitialObserver::Append(const GURL& url) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| -
|
| - if (!on_the_record_switch || NULL == g_predictor)
|
| - return;
|
| - if (kStartupResolutionCount <= first_navigations_.size())
|
| - return;
|
| -
|
| - DCHECK(url.SchemeIs("http") || url.SchemeIs("https"));
|
| - DCHECK_EQ(url, Predictor::CanonicalizeUrl(url));
|
| - if (first_navigations_.find(url) == first_navigations_.end())
|
| - first_navigations_[url] = base::TimeTicks::Now();
|
| -}
|
| -
|
| -void InitialObserver::GetInitialDnsResolutionList(ListValue* startup_list) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| - DCHECK(startup_list);
|
| - startup_list->Clear();
|
| - DCHECK_EQ(0u, startup_list->GetSize());
|
| - startup_list->Append(
|
| - new base::FundamentalValue(kPredictorStartupFormatVersion));
|
| - for (FirstNavigations::iterator it = first_navigations_.begin();
|
| - it != first_navigations_.end();
|
| - ++it) {
|
| - DCHECK(it->first == Predictor::CanonicalizeUrl(it->first));
|
| - startup_list->Append(new StringValue(it->first.spec()));
|
| - }
|
| -}
|
| -
|
| -void InitialObserver::GetFirstResolutionsHtml(std::string* output) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| -
|
| - UrlInfo::UrlInfoTable resolution_list;
|
| - {
|
| - for (FirstNavigations::iterator it(first_navigations_.begin());
|
| - it != first_navigations_.end();
|
| - it++) {
|
| - UrlInfo info;
|
| - info.SetUrl(it->first);
|
| - info.set_time(it->second);
|
| - resolution_list.push_back(info);
|
| - }
|
| - }
|
| - UrlInfo::GetHtmlTable(resolution_list,
|
| - "Future startups will prefetch DNS records for ", false, output);
|
| -}
|
| -
|
| -//------------------------------------------------------------------------------
|
| -// Support observer to detect opening and closing of OffTheRecord windows.
|
| -// This object lives on the UI thread.
|
| -
|
| -class OffTheRecordObserver : public NotificationObserver {
|
| - public:
|
| - void Register() {
|
| - // TODO(pkasting): This test should not be necessary. See crbug.com/12475.
|
| - if (registrar_.IsEmpty()) {
|
| - registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSED,
|
| - NotificationService::AllSources());
|
| - registrar_.Add(this, chrome::NOTIFICATION_BROWSER_OPENED,
|
| - NotificationService::AllSources());
|
| - }
|
| - }
|
| -
|
| - void Observe(int type, const NotificationSource& source,
|
| - const NotificationDetails& details) {
|
| - switch (type) {
|
| - case chrome::NOTIFICATION_BROWSER_OPENED:
|
| - if (!Source<Browser>(source)->profile()->IsOffTheRecord())
|
| - break;
|
| - ++count_off_the_record_windows_;
|
| - OnTheRecord(false);
|
| - break;
|
| -
|
| - case chrome::NOTIFICATION_BROWSER_CLOSED:
|
| - if (!Source<Browser>(source)->profile()->IsOffTheRecord())
|
| - break; // Ignore ordinary windows.
|
| - DCHECK_LT(0, count_off_the_record_windows_);
|
| - if (0 >= count_off_the_record_windows_) // Defensive coding.
|
| - break;
|
| - if (--count_off_the_record_windows_)
|
| - break; // Still some windows are incognito.
|
| - OnTheRecord(true);
|
| - break;
|
| -
|
| - default:
|
| - break;
|
| - }
|
| - }
|
| -
|
| - private:
|
| - friend struct base::DefaultLazyInstanceTraits<OffTheRecordObserver>;
|
| -
|
| - OffTheRecordObserver() : count_off_the_record_windows_(0) {}
|
| - ~OffTheRecordObserver() {}
|
| -
|
| - NotificationRegistrar registrar_;
|
| - int count_off_the_record_windows_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(OffTheRecordObserver);
|
| -};
|
| -
|
| -static base::LazyInstance<OffTheRecordObserver> g_off_the_record_observer(
|
| - base::LINKER_INITIALIZED);
|
| -
|
| -//------------------------------------------------------------------------------
|
| -// This section supports the about:dns page.
|
| -//------------------------------------------------------------------------------
|
| -
|
| -// Provide global support for the about:dns page.
|
| -void PredictorGetHtmlInfo(std::string* output) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| -
|
| - if (!predictor_enabled || NULL == g_predictor) {
|
| - output->append("DNS pre-resolution and TCP pre-connection is disabled.");
|
| - } else {
|
| - if (!on_the_record_switch) {
|
| - output->append("Incognito mode is active in a window.");
|
| - } else {
|
| - // List items fetched at startup.
|
| - if (g_initial_observer)
|
| - g_initial_observer->GetFirstResolutionsHtml(output);
|
| - // Show list of subresource predictions and stats.
|
| - g_predictor->GetHtmlReferrerLists(output);
|
| - // Show list of prediction results.
|
| - g_predictor->GetHtmlInfo(output);
|
| - }
|
| - }
|
| -}
|
| -
|
| -void ClearPredictorCache() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| - if (!predictor_enabled || NULL == g_predictor)
|
| - return;
|
| - g_predictor->DiscardAllResults();
|
| -}
|
| -
|
| -//------------------------------------------------------------------------------
|
| -// This section intializes global DNS prefetch services.
|
| -//------------------------------------------------------------------------------
|
| -
|
| -static void InitNetworkPredictor(TimeDelta max_dns_queue_delay,
|
| - size_t max_parallel_resolves,
|
| - PrefService* user_prefs,
|
| - PrefService* local_state,
|
| - bool preconnect_enabled) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| -
|
| - bool prefetching_enabled =
|
| - user_prefs->GetBoolean(prefs::kNetworkPredictionEnabled);
|
| -
|
| - // Gather the list of hostnames to prefetch on startup.
|
| - UrlList urls =
|
| - GetPredictedUrlListAtStartup(user_prefs, local_state);
|
| -
|
| - ListValue* referral_list =
|
| - static_cast<ListValue*>(user_prefs->GetList(
|
| - prefs::kDnsPrefetchingHostReferralList)->DeepCopy());
|
| -
|
| - // Remove obsolete preferences from local state if necessary.
|
| - int current_version =
|
| - local_state->GetInteger(prefs::kMultipleProfilePrefMigration);
|
| - if ((current_version & browser::DNS_PREFS) == 0) {
|
| - local_state->RegisterListPref(prefs::kDnsStartupPrefetchList,
|
| - PrefService::UNSYNCABLE_PREF);
|
| - local_state->RegisterListPref(prefs::kDnsHostReferralList,
|
| - PrefService::UNSYNCABLE_PREF);
|
| - local_state->ClearPref(prefs::kDnsStartupPrefetchList);
|
| - local_state->ClearPref(prefs::kDnsHostReferralList);
|
| - local_state->SetInteger(prefs::kMultipleProfilePrefMigration,
|
| - current_version | browser::DNS_PREFS);
|
| - }
|
| -
|
| - g_browser_process->io_thread()->InitNetworkPredictor(
|
| - prefetching_enabled, max_dns_queue_delay, max_parallel_resolves, urls,
|
| - referral_list, preconnect_enabled);
|
| -}
|
| -
|
| -void FinalizePredictorInitialization(
|
| - Predictor* global_predictor,
|
| - const UrlList& startup_urls,
|
| - ListValue* referral_list) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| - g_predictor = global_predictor;
|
| - g_initial_observer = new InitialObserver();
|
| -
|
| - // Prefetch these hostnames on startup.
|
| - DnsPrefetchMotivatedList(startup_urls,
|
| - UrlInfo::STARTUP_LIST_MOTIVATED);
|
| - g_predictor->DeserializeReferrersThenDelete(referral_list);
|
| -}
|
| -
|
| -void FreePredictorResources() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| - g_predictor = NULL; // Owned and released by io_thread.cc.
|
| - delete g_initial_observer;
|
| - g_initial_observer = NULL;
|
| -}
|
| -
|
| -//------------------------------------------------------------------------------
|
| -// Functions to handle saving of hostnames from one session to the next, to
|
| -// expedite startup times.
|
| -
|
| -static void SaveDnsPrefetchStateForNextStartupAndTrimOnIOThread(
|
| - ListValue* startup_list,
|
| - ListValue* referral_list,
|
| - base::WaitableEvent* completion) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| -
|
| - if (NULL == g_predictor) {
|
| - completion->Signal();
|
| - return;
|
| - }
|
| -
|
| - if (g_initial_observer)
|
| - g_initial_observer->GetInitialDnsResolutionList(startup_list);
|
| -
|
| - // Do at least one trim at shutdown, in case the user wasn't running long
|
| - // enough to do any regular trimming of referrers.
|
| - g_predictor->TrimReferrersNow();
|
| - g_predictor->SerializeReferrers(referral_list);
|
| -
|
| - completion->Signal();
|
| -}
|
| -
|
| -void SavePredictorStateForNextStartupAndTrim(PrefService* prefs) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| -
|
| - if (!predictor_enabled || g_predictor == NULL)
|
| - return;
|
| -
|
| - base::WaitableEvent completion(true, false);
|
| -
|
| - ListPrefUpdate update_startup_list(prefs, prefs::kDnsPrefetchingStartupList);
|
| - ListPrefUpdate update_referral_list(prefs,
|
| - prefs::kDnsPrefetchingHostReferralList);
|
| - bool posted = BrowserThread::PostTask(
|
| - BrowserThread::IO,
|
| - FROM_HERE,
|
| - NewRunnableFunction(SaveDnsPrefetchStateForNextStartupAndTrimOnIOThread,
|
| - update_startup_list.Get(),
|
| - update_referral_list.Get(),
|
| - &completion));
|
| -
|
| - // TODO(jar): Synchronous waiting for the IO thread is a potential source
|
| - // to deadlocks and should be investigated. See http://crbug.com/78451.
|
| - DCHECK(posted);
|
| - if (posted)
|
| - completion.Wait();
|
| -}
|
| -
|
| -static UrlList GetPredictedUrlListAtStartup(PrefService* user_prefs,
|
| - PrefService* local_state) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - UrlList urls;
|
| - // Recall list of URLs we learned about during last session.
|
| - // This may catch secondary hostnames, pulled in by the homepages. It will
|
| - // also catch more of the "primary" home pages, since that was (presumably)
|
| - // rendered first (and will be rendered first this time too).
|
| - const ListValue* startup_list =
|
| - user_prefs->GetList(prefs::kDnsPrefetchingStartupList);
|
| -
|
| - if (startup_list) {
|
| - ListValue::const_iterator it = startup_list->begin();
|
| - int format_version = -1;
|
| - if (it != startup_list->end() &&
|
| - (*it)->GetAsInteger(&format_version) &&
|
| - format_version == kPredictorStartupFormatVersion) {
|
| - ++it;
|
| - for (; it != startup_list->end(); ++it) {
|
| - std::string url_spec;
|
| - if (!(*it)->GetAsString(&url_spec)) {
|
| - LOG(DFATAL);
|
| - break; // Format incompatibility.
|
| - }
|
| - GURL url(url_spec);
|
| - if (!url.has_host() || !url.has_scheme()) {
|
| - LOG(DFATAL);
|
| - break; // Format incompatibility.
|
| - }
|
| -
|
| - urls.push_back(url);
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Prepare for any static home page(s) the user has in prefs. The user may
|
| - // have a LOT of tab's specified, so we may as well try to warm them all.
|
| - SessionStartupPref tab_start_pref =
|
| - SessionStartupPref::GetStartupPref(user_prefs);
|
| - if (SessionStartupPref::URLS == tab_start_pref.type) {
|
| - for (size_t i = 0; i < tab_start_pref.urls.size(); i++) {
|
| - GURL gurl = tab_start_pref.urls[i];
|
| - if (!gurl.is_valid() || gurl.SchemeIsFile() || gurl.host().empty())
|
| - continue;
|
| - if (gurl.SchemeIs("http") || gurl.SchemeIs("https"))
|
| - urls.push_back(gurl.GetWithEmptyPath());
|
| - }
|
| - }
|
| -
|
| - if (urls.empty())
|
| - urls.push_back(GURL("http://www.google.com:80"));
|
| -
|
| - return urls;
|
| -}
|
| -
|
| -//------------------------------------------------------------------------------
|
| -// Methods for the helper class that is used to startup and teardown the whole
|
| -// g_predictor system (both DNS pre-resolution and TCP/IP pre-connection).
|
| -
|
| -PredictorInit::PredictorInit(PrefService* user_prefs,
|
| - PrefService* local_state,
|
| - bool preconnect_enabled) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - // Set up a field trial to see what disabling DNS pre-resolution does to
|
| - // latency of page loads.
|
| - base::FieldTrial::Probability kDivisor = 1000;
|
| - // For each option (i.e., non-default), we have a fixed probability.
|
| - base::FieldTrial::Probability kProbabilityPerGroup = 1; // 0.1% probability.
|
| -
|
| - // After June 30, 2011 builds, it will always be in default group
|
| - // (default_enabled_prefetch).
|
| - trial_ = new base::FieldTrial("DnsImpact", kDivisor,
|
| - "default_enabled_prefetch", 2011, 10, 30);
|
| -
|
| - // First option is to disable prefetching completely.
|
| - int disabled_prefetch = trial_->AppendGroup("disabled_prefetch",
|
| - kProbabilityPerGroup);
|
| -
|
| - // We're running two experiments at the same time. The first set of trials
|
| - // modulates the delay-time until we declare a congestion event (and purge
|
| - // our queue). The second modulates the number of concurrent resolutions
|
| - // we do at any time. Users are in exactly one trial (or the default) during
|
| - // any one run, and hence only one experiment at a time.
|
| - // Experiment 1:
|
| - // Set congestion detection at 250, 500, or 750ms, rather than the 1 second
|
| - // default.
|
| - int max_250ms_prefetch = trial_->AppendGroup("max_250ms_queue_prefetch",
|
| - kProbabilityPerGroup);
|
| - int max_500ms_prefetch = trial_->AppendGroup("max_500ms_queue_prefetch",
|
| - kProbabilityPerGroup);
|
| - int max_750ms_prefetch = trial_->AppendGroup("max_750ms_queue_prefetch",
|
| - kProbabilityPerGroup);
|
| - // Set congestion detection at 2 seconds instead of the 1 second default.
|
| - int max_2s_prefetch = trial_->AppendGroup("max_2s_queue_prefetch",
|
| - kProbabilityPerGroup);
|
| - // Experiment 2:
|
| - // Set max simultaneous resoultions to 2, 4, or 6, and scale the congestion
|
| - // limit proportionally (so we don't impact average probability of asserting
|
| - // congesion very much).
|
| - int max_2_concurrent_prefetch = trial_->AppendGroup(
|
| - "max_2 concurrent_prefetch", kProbabilityPerGroup);
|
| - int max_4_concurrent_prefetch = trial_->AppendGroup(
|
| - "max_4 concurrent_prefetch", kProbabilityPerGroup);
|
| - int max_6_concurrent_prefetch = trial_->AppendGroup(
|
| - "max_6 concurrent_prefetch", kProbabilityPerGroup);
|
| -
|
| - // We will register the incognito observer regardless of whether prefetching
|
| - // is enabled, as it is also used to clear the host cache.
|
| - g_off_the_record_observer.Get().Register();
|
| -
|
| - if (trial_->group() != disabled_prefetch) {
|
| - // Initialize the DNS prefetch system.
|
| - size_t max_parallel_resolves = kMaxSpeculativeParallelResolves;
|
| - int max_queueing_delay_ms = kMaxSpeculativeResolveQueueDelayMs;
|
| -
|
| - if (trial_->group() == max_2_concurrent_prefetch)
|
| - max_parallel_resolves = 2;
|
| - else if (trial_->group() == max_4_concurrent_prefetch)
|
| - max_parallel_resolves = 4;
|
| - else if (trial_->group() == max_6_concurrent_prefetch)
|
| - max_parallel_resolves = 6;
|
| -
|
| - if (trial_->group() == max_250ms_prefetch) {
|
| - max_queueing_delay_ms =
|
| - (250 * kTypicalSpeculativeGroupSize) / max_parallel_resolves;
|
| - } else if (trial_->group() == max_500ms_prefetch) {
|
| - max_queueing_delay_ms =
|
| - (500 * kTypicalSpeculativeGroupSize) / max_parallel_resolves;
|
| - } else if (trial_->group() == max_750ms_prefetch) {
|
| - max_queueing_delay_ms =
|
| - (750 * kTypicalSpeculativeGroupSize) / max_parallel_resolves;
|
| - } else if (trial_->group() == max_2s_prefetch) {
|
| - max_queueing_delay_ms =
|
| - (2000 * kTypicalSpeculativeGroupSize) / max_parallel_resolves;
|
| - }
|
| -
|
| - TimeDelta max_queueing_delay(
|
| - TimeDelta::FromMilliseconds(max_queueing_delay_ms));
|
| -
|
| - DCHECK(!g_predictor);
|
| - InitNetworkPredictor(max_queueing_delay, max_parallel_resolves, user_prefs,
|
| - local_state, preconnect_enabled);
|
| - }
|
| -}
|
| -
|
| -PredictorInit::~PredictorInit() {
|
| -}
|
| -
|
| -} // namespace chrome_browser_net
|
|
|