Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / net / predictor.cc
index 74b1c8a..df12e02 100644 (file)
@@ -13,6 +13,7 @@
 #include "base/bind.h"
 #include "base/compiler_specific.h"
 #include "base/containers/mru_cache.h"
+#include "base/logging.h"
 #include "base/metrics/histogram.h"
 #include "base/prefs/pref_service.h"
 #include "base/prefs/scoped_user_pref_update.h"
@@ -28,6 +29,7 @@
 #include "chrome/browser/net/preconnect.h"
 #include "chrome/browser/net/spdyproxy/proxy_advisor.h"
 #include "chrome/browser/prefs/session_startup_pref.h"
+#include "chrome/browser/profiles/profile_io_data.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "components/data_reduction_proxy/browser/data_reduction_proxy_settings.h"
@@ -133,139 +135,11 @@ class Predictor::LookupRequest {
   DISALLOW_COPY_AND_ASSIGN(LookupRequest);
 };
 
-// This records UMAs for preconnect usage based on navigation URLs to
-// gather precision/recall for user-event based preconnect triggers.
-// Stats are gathered via a LRU cache that remembers all preconnect within the
-// last N seconds.
-// A preconnect trigger is considered as used iff a navigation including
-// access to the preconnected host occurs within a time period specified by
-// kMaxUnusedSocketLifetimeSecondsWithoutAGet.
-class Predictor::PreconnectUsage {
- public:
-  PreconnectUsage();
-  ~PreconnectUsage();
-
-  // Record a preconnect trigger to |url|.
-  void ObservePreconnect(const GURL& url);
-
-  // Record a user navigation with its redirect history, |url_chain|.
-  // We are uncertain if this is actually a link navigation.
-  void ObserveNavigationChain(const std::vector<GURL>& url_chain,
-                              bool is_subresource);
-
-  // Record a user link navigation to |final_url|.
-  // We are certain that this is a user-triggered link navigation.
-  void ObserveLinkNavigation(const GURL& final_url);
-
- private:
-  // This tracks whether a preconnect was used in some navigation or not
-  class PreconnectPrecisionStat {
-   public:
-    PreconnectPrecisionStat()
-        : timestamp_(base::TimeTicks::Now()),
-          was_used_(false) {
-    }
-
-    const base::TimeTicks& timestamp() { return timestamp_; }
-
-    void set_was_used() { was_used_ = true; }
-    bool was_used() const { return was_used_; }
-
-   private:
-    base::TimeTicks timestamp_;
-    bool was_used_;
-  };
-
-  typedef base::MRUCache<GURL, PreconnectPrecisionStat> MRUPreconnects;
-  MRUPreconnects mru_preconnects_;
-
-  // The longest time an entry can persist in mru_preconnect_
-  const base::TimeDelta max_duration_;
-
-  std::vector<GURL> recent_navigation_chain_;
-
-  DISALLOW_COPY_AND_ASSIGN(PreconnectUsage);
-};
-
-Predictor::PreconnectUsage::PreconnectUsage()
-    : mru_preconnects_(MRUPreconnects::NO_AUTO_EVICT),
-      max_duration_(base::TimeDelta::FromSeconds(
-          Predictor::kMaxUnusedSocketLifetimeSecondsWithoutAGet)) {
-}
-
-Predictor::PreconnectUsage::~PreconnectUsage() {}
-
-void Predictor::PreconnectUsage::ObservePreconnect(const GURL& url) {
-  // Evict any overly old entries and record stats.
-  base::TimeTicks now = base::TimeTicks::Now();
-
-  MRUPreconnects::reverse_iterator eldest_preconnect =
-      mru_preconnects_.rbegin();
-  while (!mru_preconnects_.empty()) {
-    DCHECK(eldest_preconnect == mru_preconnects_.rbegin());
-    if (now - eldest_preconnect->second.timestamp() < max_duration_)
-      break;
-
-    UMA_HISTOGRAM_BOOLEAN("Net.PreconnectTriggerUsed",
-                          eldest_preconnect->second.was_used());
-    eldest_preconnect = mru_preconnects_.Erase(eldest_preconnect);
-  }
-
-  // Add new entry.
-  GURL canonical_url(Predictor::CanonicalizeUrl(url));
-  mru_preconnects_.Put(canonical_url, PreconnectPrecisionStat());
-}
-
-void Predictor::PreconnectUsage::ObserveNavigationChain(
-    const std::vector<GURL>& url_chain,
-    bool is_subresource) {
-  if (url_chain.empty())
-    return;
-
-  if (!is_subresource)
-    recent_navigation_chain_ = url_chain;
-
-  GURL canonical_url(Predictor::CanonicalizeUrl(url_chain.back()));
-
-  MRUPreconnects::iterator itPreconnect = mru_preconnects_.Peek(canonical_url);
-  bool was_preconnected = (itPreconnect != mru_preconnects_.end());
-
-  // This is an UMA which was named incorrectly. This actually measures the
-  // ratio of URLRequests which have used a preconnected session.
-  UMA_HISTOGRAM_BOOLEAN("Net.PreconnectedNavigation", was_preconnected);
-}
-
-void Predictor::PreconnectUsage::ObserveLinkNavigation(const GURL& url) {
-  if (recent_navigation_chain_.empty() ||
-      url != recent_navigation_chain_.back()) {
-    // The navigation chain is not available for this navigation.
-    recent_navigation_chain_.clear();
-    recent_navigation_chain_.push_back(url);
-  }
-
-  // See if the link navigation involved preconnected session.
-  bool did_use_preconnect = false;
-  for (std::vector<GURL>::const_iterator it = recent_navigation_chain_.begin();
-       it != recent_navigation_chain_.end();
-       ++it) {
-    GURL canonical_url(Predictor::CanonicalizeUrl(*it));
-
-    // Record the preconnect trigger for the url as used if exist
-    MRUPreconnects::iterator itPreconnect =
-        mru_preconnects_.Peek(canonical_url);
-    bool was_preconnected = (itPreconnect != mru_preconnects_.end());
-    if (was_preconnected) {
-      itPreconnect->second.set_was_used();
-      did_use_preconnect = true;
-    }
-  }
-
-  UMA_HISTOGRAM_BOOLEAN("Net.PreconnectedLinkNavigations", did_use_preconnect);
-}
-
-Predictor::Predictor(bool preconnect_enabled)
+Predictor::Predictor(bool preconnect_enabled, bool predictor_enabled)
     : url_request_context_getter_(NULL),
-      predictor_enabled_(true),
+      predictor_enabled_(predictor_enabled),
+      user_prefs_(NULL),
+      profile_io_data_(NULL),
       peak_pending_lookups_(0),
       shutdown_(false),
       max_concurrent_dns_lookups_(g_max_parallel_resolves),
@@ -290,10 +164,11 @@ Predictor::~Predictor() {
 
 // static
 Predictor* Predictor::CreatePredictor(bool preconnect_enabled,
+                                      bool predictor_enabled,
                                       bool simple_shutdown) {
   if (simple_shutdown)
-    return new SimplePredictor(preconnect_enabled);
-  return new Predictor(preconnect_enabled);
+    return new SimplePredictor(preconnect_enabled, predictor_enabled);
+  return new Predictor(preconnect_enabled, predictor_enabled);
 }
 
 void Predictor::RegisterProfilePrefs(
@@ -309,12 +184,11 @@ void Predictor::RegisterProfilePrefs(
 void Predictor::InitNetworkPredictor(PrefService* user_prefs,
                                      PrefService* local_state,
                                      IOThread* io_thread,
-                                     net::URLRequestContextGetter* getter) {
+                                     net::URLRequestContextGetter* getter,
+                                     ProfileIOData* profile_io_data) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  bool predictor_enabled =
-      user_prefs->GetBoolean(prefs::kNetworkPredictionEnabled);
-
+  user_prefs_ = user_prefs;
   url_request_context_getter_ = getter;
 
   // Gather the list of hostnames to prefetch on startup.
@@ -350,7 +224,7 @@ void Predictor::InitNetworkPredictor(PrefService* user_prefs,
           &Predictor::FinalizeInitializationOnIOThread,
           base::Unretained(this),
           urls, referral_list,
-          io_thread, predictor_enabled));
+          io_thread, profile_io_data));
 }
 
 void Predictor::AnticipateOmniboxUrl(const GURL& url, bool preconnectable) {
@@ -359,6 +233,9 @@ void Predictor::AnticipateOmniboxUrl(const GURL& url, bool preconnectable) {
     return;
   if (!url.is_valid() || !url.has_host())
     return;
+  if (!CanPreresolveAndPreconnect())
+    return;
+
   std::string host = url.HostNoBrackets();
   bool is_new_host_request = (host != last_omnibox_host_);
   last_omnibox_host_ = host;
@@ -366,7 +243,7 @@ void Predictor::AnticipateOmniboxUrl(const GURL& url, bool preconnectable) {
   UrlInfo::ResolutionMotivation motivation(UrlInfo::OMNIBOX_MOTIVATED);
   base::TimeTicks now = base::TimeTicks::Now();
 
-  if (preconnect_enabled()) {
+  if (preconnect_enabled_) {
     if (preconnectable && !is_new_host_request) {
       ++consecutive_omnibox_preconnect_count_;
       // The omnibox suggests a search URL (for which we can preconnect) after
@@ -393,12 +270,12 @@ void Predictor::AnticipateOmniboxUrl(const GURL& url, bool preconnectable) {
         // get with a fake request (/gen_204 might be the good path on Google).
         const int kMaxSearchKeepaliveSeconds(10);
         if ((now - last_omnibox_preconnect_).InSeconds() <
-             kMaxSearchKeepaliveSeconds)
+            kMaxSearchKeepaliveSeconds)
           return;  // We've done a preconnect recently.
         last_omnibox_preconnect_ = now;
         const int kConnectionsNeeded = 1;
-        PreconnectUrl(CanonicalizeUrl(url), GURL(), motivation,
-                      kConnectionsNeeded);
+        PreconnectUrl(
+            CanonicalizeUrl(url), GURL(), motivation, kConnectionsNeeded);
         return;  // Skip pre-resolution, since we'll open a connection.
       }
     } else {
@@ -429,9 +306,11 @@ void Predictor::PreconnectUrlAndSubresources(const GURL& url,
     const GURL& first_party_for_cookies) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
          BrowserThread::CurrentlyOn(BrowserThread::IO));
-  if (!predictor_enabled_ || !preconnect_enabled() ||
+  if (!predictor_enabled_ || !preconnect_enabled_ ||
       !url.is_valid() || !url.has_host())
     return;
+  if (!CanPreresolveAndPreconnect())
+    return;
 
   UrlInfo::ResolutionMotivation motivation(UrlInfo::EARLY_LOAD_MOTIVATED);
   const int kConnectionsNeeded = 1;
@@ -588,7 +467,7 @@ void Predictor::Resolve(const GURL& url,
 void Predictor::LearnFromNavigation(const GURL& referring_url,
                                     const GURL& target_url) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  if (!predictor_enabled_)
+  if (!predictor_enabled_ || !CanPrefetchAndPrerender())
     return;
   DCHECK_EQ(referring_url, Predictor::CanonicalizeUrl(referring_url));
   DCHECK_NE(referring_url, GURL::EmptyGURL());
@@ -611,7 +490,8 @@ void Predictor::PredictorGetHtmlInfo(Predictor* predictor,
                  // We'd like the following no-cache... but it doesn't work.
                  // "<META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">"
                  "</head><body>");
-  if (predictor && predictor->predictor_enabled()) {
+  if (predictor && predictor->predictor_enabled() &&
+      predictor->CanPrefetchAndPrerender()) {
     predictor->GetHtmlInfo(output);
   } else {
     output->append("DNS pre-resolution and TCP pre-connection is disabled.");
@@ -808,13 +688,12 @@ void Predictor::FinalizeInitializationOnIOThread(
     const UrlList& startup_urls,
     base::ListValue* referral_list,
     IOThread* io_thread,
-    bool predictor_enabled) {
+    ProfileIOData* profile_io_data) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
-  predictor_enabled_ = predictor_enabled;
+  profile_io_data_ = profile_io_data;
   initial_observer_.reset(new InitialObserver());
   host_resolver_ = io_thread->globals()->host_resolver.get();
-  preconnect_usage_.reset(new PreconnectUsage());
 
   net::URLRequestContext* context =
       url_request_context_getter_->GetURLRequestContext();
@@ -842,8 +721,10 @@ void Predictor::FinalizeInitializationOnIOThread(
 
 void Predictor::LearnAboutInitialNavigation(const GURL& url) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  if (!predictor_enabled_ || NULL == initial_observer_.get() )
+  if (!predictor_enabled_ || NULL == initial_observer_.get() ||
+      !CanPrefetchAndPrerender()) {
     return;
+  }
   initial_observer_->Append(url, this);
 }
 
@@ -872,6 +753,8 @@ void Predictor::DnsPrefetchMotivatedList(
          BrowserThread::CurrentlyOn(BrowserThread::IO));
   if (!predictor_enabled_)
     return;
+  if (!CanPrefetchAndPrerender())
+    return;
 
   if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
     ResolveList(urls, motivation);
@@ -903,14 +786,17 @@ static void SaveDnsPrefetchStateForNextStartupAndTrimOnIOThread(
       startup_list, referral_list, completion);
 }
 
-void Predictor::SaveStateForNextStartupAndTrim(PrefService* prefs) {
+void Predictor::SaveStateForNextStartupAndTrim() {
   if (!predictor_enabled_)
     return;
+  if (!CanPrefetchAndPrerender())
+    return;
 
   base::WaitableEvent completion(true, false);
 
-  ListPrefUpdate update_startup_list(prefs, prefs::kDnsPrefetchingStartupList);
-  ListPrefUpdate update_referral_list(prefs,
+  ListPrefUpdate update_startup_list(user_prefs_,
+                                     prefs::kDnsPrefetchingStartupList);
+  ListPrefUpdate update_referral_list(user_prefs_,
                                       prefs::kDnsPrefetchingHostReferralList);
   if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
     SaveDnsPrefetchStateForNextStartupAndTrimOnIOThread(
@@ -956,26 +842,6 @@ void Predictor::SaveDnsPrefetchStateForNextStartupAndTrim(
   completion->Signal();
 }
 
-void Predictor::EnablePredictor(bool enable) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
-         BrowserThread::CurrentlyOn(BrowserThread::IO));
-
-  if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
-    EnablePredictorOnIOThread(enable);
-  } else {
-    BrowserThread::PostTask(
-        BrowserThread::IO,
-        FROM_HERE,
-        base::Bind(&Predictor::EnablePredictorOnIOThread,
-                   base::Unretained(this), enable));
-  }
-}
-
-void Predictor::EnablePredictorOnIOThread(bool enable) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  predictor_enabled_ = enable;
-}
-
 void Predictor::PreconnectUrl(const GURL& url,
                               const GURL& first_party_for_cookies,
                               UrlInfo::ResolutionMotivation motivation,
@@ -1003,9 +869,6 @@ void Predictor::PreconnectUrlOnIOThread(
   // Skip the HSTS redirect.
   GURL url = GetHSTSRedirectOnIOThread(original_url);
 
-  if (motivation == UrlInfo::MOUSE_OVER_MOTIVATED)
-    RecordPreconnectTrigger(url);
-
   AdviseProxy(url, motivation, true /* is_preconnect */);
 
   if (observer_) {
@@ -1020,33 +883,14 @@ void Predictor::PreconnectUrlOnIOThread(
                        url_request_context_getter_.get());
 }
 
-void Predictor::RecordPreconnectTrigger(const GURL& url) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  if (preconnect_usage_)
-    preconnect_usage_->ObservePreconnect(url);
-}
-
-void Predictor::RecordPreconnectNavigationStat(
-    const std::vector<GURL>& url_chain,
-    bool is_subresource) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
-  if (preconnect_usage_)
-    preconnect_usage_->ObserveNavigationChain(url_chain, is_subresource);
-}
-
-void Predictor::RecordLinkNavigation(const GURL& url) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  if (preconnect_usage_)
-    preconnect_usage_->ObserveLinkNavigation(url);
-}
-
 void Predictor::PredictFrameSubresources(const GURL& url,
                                          const GURL& first_party_for_cookies) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
          BrowserThread::CurrentlyOn(BrowserThread::IO));
   if (!predictor_enabled_)
     return;
+  if (!CanPrefetchAndPrerender())
+    return;
   DCHECK_EQ(url.GetWithEmptyPath(), url);
   // Add one pass through the message loop to allow current navigation to
   // proceed.
@@ -1081,6 +925,24 @@ void Predictor::AdviseProxy(const GURL& url,
   }
 }
 
+bool Predictor::CanPrefetchAndPrerender() const {
+  if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+    return chrome_browser_net::CanPrefetchAndPrerenderUI(user_prefs_);
+  } else {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+    return chrome_browser_net::CanPrefetchAndPrerenderIO(profile_io_data_);
+  }
+}
+
+bool Predictor::CanPreresolveAndPreconnect() const {
+  if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+    return chrome_browser_net::CanPreresolveAndPreconnectUI(user_prefs_);
+  } else {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+    return chrome_browser_net::CanPreresolveAndPreconnectIO(profile_io_data_);
+  }
+}
+
 enum SubresourceValue {
   PRECONNECTION,
   PRERESOLUTION,
@@ -1461,7 +1323,8 @@ void SimplePredictor::InitNetworkPredictor(
     PrefService* user_prefs,
     PrefService* local_state,
     IOThread* io_thread,
-    net::URLRequestContextGetter* getter) {
+    net::URLRequestContextGetter* getter,
+    ProfileIOData* profile_io_data) {
   // Empty function for unittests.
 }
 
@@ -1469,4 +1332,7 @@ void SimplePredictor::ShutdownOnUIThread() {
   SetShutdown(true);
 }
 
+bool SimplePredictor::CanPrefetchAndPrerender() const { return true; }
+bool SimplePredictor::CanPreresolveAndPreconnect() const { return true; }
+
 }  // namespace chrome_browser_net