Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / predictors / resource_prefetch_common.cc
blob1fd2c097e909bf2e41fc05f9cb41227dfbe01bec
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/predictors/resource_prefetch_common.h"
7 #include <stdlib.h>
9 #include "base/command_line.h"
10 #include "base/metrics/field_trial.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/strings/string_split.h"
13 #include "chrome/browser/net/prediction_options.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/common/chrome_switches.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/render_frame_host.h"
18 #include "content/public/browser/render_process_host.h"
19 #include "content/public/browser/web_contents.h"
21 using base::FieldTrialList;
22 using std::string;
23 using std::vector;
25 namespace predictors {
27 const char kSpeculativePrefetchingTrialName[] =
28 "SpeculativeResourcePrefetching";
31 * SpeculativeResourcePrefetching is a field trial, and its value must have the
32 * following format: key1=value1:key2=value2:key3=value3
33 * e.g. "Prefetching=Enabled:Predictor=Url:Confidence=High"
34 * The function below extracts the value corresponding to a key provided from
35 * the SpeculativeResourcePrefetching field trial.
37 std::string GetFiledTrialSpecValue(string key) {
38 std::string trial_name =
39 FieldTrialList::FindFullName(kSpeculativePrefetchingTrialName);
40 for (const base::StringPiece& element : base::SplitStringPiece(
41 trial_name, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
42 std::vector<base::StringPiece> key_value = base::SplitStringPiece(
43 element, "=", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
44 if (key_value.size() == 2 && key_value[0] == key)
45 return key_value[1].as_string();
47 return string();
50 bool IsSpeculativeResourcePrefetchingEnabled(
51 Profile* profile,
52 ResourcePrefetchPredictorConfig* config) {
53 DCHECK(config);
55 // Off the record - disabled.
56 if (!profile || profile->IsOffTheRecord())
57 return false;
59 // Enabled by command line switch. The config has the default params already
60 // set. The command line with just enable them with the default params.
61 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
62 switches::kSpeculativeResourcePrefetching)) {
63 const std::string value =
64 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
65 switches::kSpeculativeResourcePrefetching);
67 if (value == switches::kSpeculativeResourcePrefetchingDisabled) {
68 return false;
69 } else if (value == switches::kSpeculativeResourcePrefetchingLearning) {
70 config->mode |= ResourcePrefetchPredictorConfig::URL_LEARNING;
71 config->mode |= ResourcePrefetchPredictorConfig::HOST_LEARNING;
72 return true;
73 } else if (value == switches::kSpeculativeResourcePrefetchingEnabled) {
74 config->mode |= ResourcePrefetchPredictorConfig::URL_LEARNING;
75 config->mode |= ResourcePrefetchPredictorConfig::HOST_LEARNING;
76 config->mode |= ResourcePrefetchPredictorConfig::URL_PREFETCHING;
77 config->mode |= ResourcePrefetchPredictorConfig::HOST_PRFETCHING;
78 return true;
82 // Disable if no field trial is specified.
83 std::string trial = base::FieldTrialList::FindFullName(
84 kSpeculativePrefetchingTrialName);
85 if (trial.empty())
86 return false;
88 // Enabled by field trial.
89 std::string spec_prefetching = GetFiledTrialSpecValue("Prefetching");
90 std::string spec_predictor = GetFiledTrialSpecValue("Predictor");
91 std::string spec_confidence = GetFiledTrialSpecValue("Confidence");
92 std::string spec_more_resources = GetFiledTrialSpecValue("MoreResources");
93 std::string spec_small_db = GetFiledTrialSpecValue("SmallDB");
95 if (spec_prefetching == "Learning") {
96 if (spec_predictor == "Url") {
97 config->mode |= ResourcePrefetchPredictorConfig::URL_LEARNING;
98 } else if (spec_predictor == "Host") {
99 config->mode |= ResourcePrefetchPredictorConfig::HOST_LEARNING;
100 } else {
101 // Default: both Url and Host
102 config->mode |= ResourcePrefetchPredictorConfig::URL_LEARNING;
103 config->mode |= ResourcePrefetchPredictorConfig::HOST_LEARNING;
105 } else if (spec_prefetching == "Enabled") {
106 if (spec_predictor == "Url") {
107 config->mode |= ResourcePrefetchPredictorConfig::URL_LEARNING;
108 config->mode |= ResourcePrefetchPredictorConfig::URL_PREFETCHING;
109 } else if (spec_predictor == "Host") {
110 config->mode |= ResourcePrefetchPredictorConfig::HOST_LEARNING;
111 config->mode |= ResourcePrefetchPredictorConfig::HOST_PRFETCHING;
112 } else {
113 // Default: both Url and Host
114 config->mode |= ResourcePrefetchPredictorConfig::URL_LEARNING;
115 config->mode |= ResourcePrefetchPredictorConfig::HOST_LEARNING;
116 config->mode |= ResourcePrefetchPredictorConfig::URL_PREFETCHING;
117 config->mode |= ResourcePrefetchPredictorConfig::HOST_PRFETCHING;
119 } else {
120 // Default: spec_prefetching == "Disabled"
121 return false;
124 if (spec_confidence == "Low") {
125 config->min_url_visit_count = 1;
126 config->min_resource_confidence_to_trigger_prefetch = 0.5f;
127 config->min_resource_hits_to_trigger_prefetch = 1;
128 } else if (spec_confidence == "High") {
129 config->min_url_visit_count = 3;
130 config->min_resource_confidence_to_trigger_prefetch = 0.9f;
131 config->min_resource_hits_to_trigger_prefetch = 3;
132 } else {
133 // default
134 config->min_url_visit_count = 2;
135 config->min_resource_confidence_to_trigger_prefetch = 0.7f;
136 config->min_resource_hits_to_trigger_prefetch = 2;
139 if (spec_more_resources == "Enabled") {
140 config->max_resources_per_entry = 100;
143 if (spec_small_db == "Enabled") {
144 config->max_urls_to_track = 200;
145 config->max_hosts_to_track = 100;
148 return true;
151 NavigationID::NavigationID()
152 : render_process_id(-1),
153 render_frame_id(-1) {
156 NavigationID::NavigationID(const NavigationID& other)
157 : render_process_id(other.render_process_id),
158 render_frame_id(other.render_frame_id),
159 main_frame_url(other.main_frame_url),
160 creation_time(other.creation_time) {
163 NavigationID::NavigationID(content::WebContents* web_contents)
164 : render_process_id(web_contents->GetRenderProcessHost()->GetID()),
165 render_frame_id(web_contents->GetMainFrame()->GetRoutingID()),
166 main_frame_url(web_contents->GetURL()) {
169 bool NavigationID::is_valid() const {
170 return render_process_id != -1 && render_frame_id != -1 &&
171 !main_frame_url.is_empty();
174 bool NavigationID::operator<(const NavigationID& rhs) const {
175 DCHECK(is_valid() && rhs.is_valid());
176 if (render_process_id != rhs.render_process_id)
177 return render_process_id < rhs.render_process_id;
178 else if (render_frame_id != rhs.render_frame_id)
179 return render_frame_id < rhs.render_frame_id;
180 else
181 return main_frame_url < rhs.main_frame_url;
184 bool NavigationID::operator==(const NavigationID& rhs) const {
185 DCHECK(is_valid() && rhs.is_valid());
186 return IsSameRenderer(rhs) && main_frame_url == rhs.main_frame_url;
189 bool NavigationID::IsSameRenderer(const NavigationID& other) const {
190 DCHECK(is_valid() && other.is_valid());
191 return render_process_id == other.render_process_id &&
192 render_frame_id == other.render_frame_id;
195 ResourcePrefetchPredictorConfig::ResourcePrefetchPredictorConfig()
196 : mode(0),
197 max_navigation_lifetime_seconds(60),
198 max_urls_to_track(500),
199 max_hosts_to_track(200),
200 min_url_visit_count(2),
201 max_resources_per_entry(50),
202 max_consecutive_misses(3),
203 min_resource_confidence_to_trigger_prefetch(0.7f),
204 min_resource_hits_to_trigger_prefetch(2),
205 max_prefetches_inflight_per_navigation(24),
206 max_prefetches_inflight_per_host_per_navigation(3) {
209 ResourcePrefetchPredictorConfig::~ResourcePrefetchPredictorConfig() {
212 bool ResourcePrefetchPredictorConfig::IsLearningEnabled() const {
213 return IsURLLearningEnabled() || IsHostLearningEnabled();
216 bool ResourcePrefetchPredictorConfig::IsPrefetchingEnabled(
217 Profile* profile) const {
218 return IsURLPrefetchingEnabled(profile) || IsHostPrefetchingEnabled(profile);
221 bool ResourcePrefetchPredictorConfig::IsURLLearningEnabled() const {
222 return (mode & URL_LEARNING) > 0;
225 bool ResourcePrefetchPredictorConfig::IsHostLearningEnabled() const {
226 return (mode & HOST_LEARNING) > 0;
229 bool ResourcePrefetchPredictorConfig::IsURLPrefetchingEnabled(
230 Profile* profile) const {
231 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
232 if (!profile || !profile->GetPrefs() ||
233 !chrome_browser_net::CanPrefetchAndPrerenderUI(profile->GetPrefs())) {
234 return false;
236 return (mode & URL_PREFETCHING) > 0;
239 bool ResourcePrefetchPredictorConfig::IsHostPrefetchingEnabled(
240 Profile* profile) const {
241 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
242 if (!profile || !profile->GetPrefs() ||
243 !chrome_browser_net::CanPrefetchAndPrerenderUI(profile->GetPrefs())) {
244 return false;
246 return (mode & HOST_PRFETCHING) > 0;
249 bool ResourcePrefetchPredictorConfig::IsLowConfidenceForTest() const {
250 return min_url_visit_count == 1 &&
251 std::abs(min_resource_confidence_to_trigger_prefetch - 0.5f) < 1e-6 &&
252 min_resource_hits_to_trigger_prefetch == 1;
255 bool ResourcePrefetchPredictorConfig::IsHighConfidenceForTest() const {
256 return min_url_visit_count == 3 &&
257 std::abs(min_resource_confidence_to_trigger_prefetch - 0.9f) < 1e-6 &&
258 min_resource_hits_to_trigger_prefetch == 3;
261 bool ResourcePrefetchPredictorConfig::IsMoreResourcesEnabledForTest() const {
262 return max_resources_per_entry == 100;
265 bool ResourcePrefetchPredictorConfig::IsSmallDBEnabledForTest() const {
266 return max_urls_to_track == 200 && max_hosts_to_track == 100;
269 } // namespace predictors