Index: chrome/browser/net/predictor_api.cc |
=================================================================== |
--- chrome/browser/net/predictor_api.cc (revision 89645) |
+++ chrome/browser/net/predictor_api.cc (working copy) |
@@ -37,11 +37,7 @@ |
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 |
@@ -73,77 +69,11 @@ |
(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); |
@@ -151,151 +81,13 @@ |
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 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. |
@@ -313,23 +105,22 @@ |
void Observe(NotificationType type, const NotificationSource& source, |
const NotificationDetails& details) { |
+ Profile* profile = NULL; |
switch (type.value) { |
case NotificationType::BROWSER_OPENED: |
- if (!Source<Browser>(source)->profile()->IsOffTheRecord()) |
+ profile = Source<Browser>(source)->profile(); |
+ if (!profile->IsOffTheRecord()) |
break; |
- ++count_off_the_record_windows_; |
- OnTheRecord(false); |
+ profile->GetPredictor()->HandleIncognitoBrowserOpened(); |
+ profile->PredictorOnTheRecord(false); |
break; |
case NotificationType::BROWSER_CLOSED: |
- if (!Source<Browser>(source)->profile()->IsOffTheRecord()) |
+ profile = Source<Browser>(source)->profile(); |
+ if (!profile->IsOffTheRecord()) |
break; // Ignore ordinary windows. |
Miranda Callahan
2011/07/21 14:38:04
indent "break;
rpetterson
2011/08/10 02:24:46
Done.
|
- 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); |
+ if (profile->GetPredictor()->HandleIncognitoBrowserClosed()) |
+ profile->PredictorOnTheRecord(true); |
break; |
default: |
@@ -340,11 +131,10 @@ |
private: |
friend struct base::DefaultLazyInstanceTraits<OffTheRecordObserver>; |
- OffTheRecordObserver() : count_off_the_record_windows_(0) {} |
+ OffTheRecordObserver() {} |
~OffTheRecordObserver() {} |
NotificationRegistrar registrar_; |
- int count_off_the_record_windows_; |
DISALLOW_COPY_AND_ASSIGN(OffTheRecordObserver); |
}; |
@@ -352,51 +142,16 @@ |
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)); |
- |
- output->append("<html><head><title>About DNS</title>" |
- // We'd like the following no-cache... but it doesn't work. |
- // "<META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">" |
- "</head><body>"); |
- 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); |
- } |
- } |
- output->append("</body></html>"); |
-} |
- |
-void ClearPredictorCache() { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- if (!predictor_enabled || NULL == g_predictor) |
- return; |
- g_predictor->DiscardAllResults(); |
-} |
- |
//------------------------------------------------------------------------------ |
-// This section intializes global DNS prefetch services. |
+// This section intializes DNS prefetch services. |
//------------------------------------------------------------------------------ |
static void InitNetworkPredictor(TimeDelta max_dns_queue_delay, |
size_t max_parallel_resolves, |
PrefService* user_prefs, |
PrefService* local_state, |
+ Profile* profile, |
bool preconnect_enabled) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
@@ -404,8 +159,12 @@ |
user_prefs->GetBoolean(prefs::kNetworkPredictionEnabled); |
// Gather the list of hostnames to prefetch on startup. |
+ // There is no predictor if the profile is off the record, but a predictor |
+ // should not be initialized in that case. |
+ DCHECK(!profile->IsOffTheRecord()); |
UrlList urls = |
- GetPredictedUrlListAtStartup(user_prefs, local_state); |
+ profile->GetPredictor()->GetPredictedUrlListAtStartup(user_prefs, |
+ local_state); |
ListValue* referral_list = |
static_cast<ListValue*>(user_prefs->GetList( |
@@ -427,143 +186,17 @@ |
g_browser_process->io_thread()->InitNetworkPredictor( |
prefetching_enabled, max_dns_queue_delay, max_parallel_resolves, urls, |
- referral_list, preconnect_enabled); |
+ referral_list, profile, 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, |
willchan no longer on Chromium
2011/07/21 12:10:53
PredictorInit() is doing 2 different things. It's
rpetterson
2011/08/10 02:24:46
Done.
|
PrefService* local_state, |
+ Profile* profile, |
Miranda Callahan
2011/07/21 14:38:04
Not sure if this is valid after you make the chang
rpetterson
2011/08/10 02:24:46
Done.
|
bool preconnect_enabled) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
// Set up a field trial to see what disabling DNS pre-resolution does to |
@@ -642,9 +275,9 @@ |
TimeDelta max_queueing_delay( |
TimeDelta::FromMilliseconds(max_queueing_delay_ms)); |
- DCHECK(!g_predictor); |
+ DCHECK(!profile->GetPredictor()); |
InitNetworkPredictor(max_queueing_delay, max_parallel_resolves, user_prefs, |
- local_state, preconnect_enabled); |
+ local_state, profile, preconnect_enabled); |
} |
} |