Make castv2 performance test work.
[chromium-blink-merge.git] / chrome / browser / prerender / prerender_tab_helper.cc
blob1d51f925fcf89e872a040724cfd692d764406884
1 // Copyright (c) 2012 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/prerender/prerender_tab_helper.h"
7 #include "base/bind.h"
8 #include "base/metrics/histogram.h"
9 #include "base/time/time.h"
10 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
11 #include "chrome/browser/prerender/prerender_histograms.h"
12 #include "chrome/browser/prerender/prerender_local_predictor.h"
13 #include "chrome/browser/prerender/prerender_manager.h"
14 #include "chrome/browser/prerender/prerender_manager_factory.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "components/password_manager/core/browser/password_manager.h"
17 #include "content/public/browser/navigation_details.h"
18 #include "content/public/browser/navigation_entry.h"
19 #include "content/public/browser/render_frame_host.h"
20 #include "content/public/browser/resource_request_details.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/common/frame_navigate_params.h"
24 using content::WebContents;
26 DEFINE_WEB_CONTENTS_USER_DATA_KEY(prerender::PrerenderTabHelper);
28 namespace prerender {
30 namespace {
32 void ReportTabHelperURLSeenToLocalPredictor(
33 PrerenderManager* prerender_manager,
34 const GURL& url,
35 WebContents* web_contents) {
36 if (!prerender_manager)
37 return;
38 PrerenderLocalPredictor* local_predictor =
39 prerender_manager->local_predictor();
40 if (!local_predictor)
41 return;
42 local_predictor->OnTabHelperURLSeen(url, web_contents);
45 } // namespace
47 PrerenderTabHelper::PrerenderTabHelper(content::WebContents* web_contents)
48 : content::WebContentsObserver(web_contents),
49 origin_(ORIGIN_NONE),
50 next_load_is_control_prerender_(false),
51 next_load_origin_(ORIGIN_NONE),
52 weak_factory_(this) {
53 ChromePasswordManagerClient* client =
54 ChromePasswordManagerClient::FromWebContents(web_contents);
55 // May be NULL during testing.
56 if (client) {
57 client->GetPasswordManager()->AddSubmissionCallback(base::Bind(
58 &PrerenderTabHelper::PasswordSubmitted, weak_factory_.GetWeakPtr()));
61 // Determine if this is a prerender.
62 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
63 if (prerender_manager &&
64 prerender_manager->IsWebContentsPrerendering(web_contents, &origin_)) {
65 navigation_type_ = NAVIGATION_TYPE_PRERENDERED;
66 } else {
67 navigation_type_ = NAVIGATION_TYPE_NORMAL;
71 PrerenderTabHelper::~PrerenderTabHelper() {
74 void PrerenderTabHelper::DidGetRedirectForResourceRequest(
75 content::RenderFrameHost* render_frame_host,
76 const content::ResourceRedirectDetails& details) {
77 if (details.resource_type != content::RESOURCE_TYPE_MAIN_FRAME)
78 return;
80 MainFrameUrlDidChange(details.new_url);
83 void PrerenderTabHelper::DidCommitProvisionalLoadForFrame(
84 content::RenderFrameHost* render_frame_host,
85 const GURL& validated_url,
86 ui::PageTransition transition_type) {
87 if (render_frame_host->GetParent())
88 return;
89 RecordEvent(EVENT_MAINFRAME_COMMIT);
90 RecordEventIfLoggedInURL(EVENT_MAINFRAME_COMMIT_DOMAIN_LOGGED_IN,
91 validated_url);
92 url_ = validated_url;
93 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
94 if (!prerender_manager)
95 return;
96 if (prerender_manager->IsWebContentsPrerendering(web_contents(), NULL))
97 return;
98 prerender_manager->RecordNavigation(validated_url);
99 ReportTabHelperURLSeenToLocalPredictor(prerender_manager, validated_url,
100 web_contents());
103 void PrerenderTabHelper::DidStopLoading() {
104 // Compute the PPLT metric and report it in a histogram, if needed. If the
105 // page is still prerendering, record the not swapped in page load time
106 // instead.
107 if (!pplt_load_start_.is_null()) {
108 base::TimeTicks now = base::TimeTicks::Now();
109 if (IsPrerendering()) {
110 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
111 if (prerender_manager) {
112 prerender_manager->RecordPageLoadTimeNotSwappedIn(
113 origin_, now - pplt_load_start_, url_);
114 } else {
115 NOTREACHED();
117 } else {
118 double fraction_elapsed_at_swapin = -1.0;
119 if (!actual_load_start_.is_null()) {
120 double plt = (now - actual_load_start_).InMillisecondsF();
121 if (plt > 0.0) {
122 fraction_elapsed_at_swapin = 1.0 -
123 (now - pplt_load_start_).InMillisecondsF() / plt;
124 } else {
125 fraction_elapsed_at_swapin = 1.0;
127 DCHECK_GE(fraction_elapsed_at_swapin, 0.0);
128 DCHECK_LE(fraction_elapsed_at_swapin, 1.0);
131 RecordPerceivedPageLoadTime(
132 now - pplt_load_start_, fraction_elapsed_at_swapin);
136 // Reset the PPLT metric.
137 pplt_load_start_ = base::TimeTicks();
138 actual_load_start_ = base::TimeTicks();
141 void PrerenderTabHelper::DidStartProvisionalLoadForFrame(
142 content::RenderFrameHost* render_frame_host,
143 const GURL& validated_url,
144 bool is_error_page,
145 bool is_iframe_srcdoc) {
146 if (render_frame_host->GetParent())
147 return;
149 // Record PPLT state for the beginning of a new navigation.
150 pplt_load_start_ = base::TimeTicks::Now();
151 actual_load_start_ = base::TimeTicks();
153 if (next_load_is_control_prerender_) {
154 DCHECK_EQ(NAVIGATION_TYPE_NORMAL, navigation_type_);
155 navigation_type_ = NAVIGATION_TYPE_WOULD_HAVE_BEEN_PRERENDERED;
156 origin_ = next_load_origin_;
157 next_load_is_control_prerender_ = false;
158 next_load_origin_ = ORIGIN_NONE;
161 MainFrameUrlDidChange(validated_url);
164 void PrerenderTabHelper::MainFrameUrlDidChange(const GURL& url) {
165 url_ = url;
166 RecordEvent(EVENT_MAINFRAME_CHANGE);
167 RecordEventIfLoggedInURL(EVENT_MAINFRAME_CHANGE_DOMAIN_LOGGED_IN, url);
168 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
169 if (!prerender_manager)
170 return;
171 if (prerender_manager->IsWebContentsPrerendering(web_contents(), NULL))
172 return;
173 ReportTabHelperURLSeenToLocalPredictor(prerender_manager, url,
174 web_contents());
177 void PrerenderTabHelper::PasswordSubmitted(const autofill::PasswordForm& form) {
178 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
179 if (prerender_manager) {
180 prerender_manager->RecordLikelyLoginOnURL(form.origin);
181 RecordEvent(EVENT_LOGIN_ACTION_ADDED);
182 if (form.password_value.empty())
183 RecordEvent(EVENT_LOGIN_ACTION_ADDED_PW_EMPTY);
187 PrerenderManager* PrerenderTabHelper::MaybeGetPrerenderManager() const {
188 return PrerenderManagerFactory::GetForProfile(
189 Profile::FromBrowserContext(web_contents()->GetBrowserContext()));
192 bool PrerenderTabHelper::IsPrerendering() {
193 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
194 if (!prerender_manager)
195 return false;
196 return prerender_manager->IsWebContentsPrerendering(web_contents(), NULL);
199 void PrerenderTabHelper::PrerenderSwappedIn() {
200 // Ensure we are not prerendering any more.
201 DCHECK_EQ(NAVIGATION_TYPE_PRERENDERED, navigation_type_);
202 DCHECK(!IsPrerendering());
203 if (pplt_load_start_.is_null()) {
204 // If we have already finished loading, report a 0 PPLT.
205 RecordPerceivedPageLoadTime(base::TimeDelta(), 1.0);
206 DCHECK_EQ(NAVIGATION_TYPE_NORMAL, navigation_type_);
207 } else {
208 // If we have not finished loading yet, record the actual load start, and
209 // rebase the start time to now.
210 actual_load_start_ = pplt_load_start_;
211 pplt_load_start_ = base::TimeTicks::Now();
215 void PrerenderTabHelper::WouldHavePrerenderedNextLoad(Origin origin) {
216 next_load_is_control_prerender_ = true;
217 next_load_origin_ = origin;
220 void PrerenderTabHelper::RecordEvent(PrerenderTabHelper::Event event) const {
221 UMA_HISTOGRAM_ENUMERATION("Prerender.TabHelperEvent",
222 event, PrerenderTabHelper::EVENT_MAX_VALUE);
225 void PrerenderTabHelper::RecordEventIfLoggedInURL(
226 PrerenderTabHelper::Event event, const GURL& url) {
227 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
228 if (!prerender_manager)
229 return;
230 scoped_ptr<bool> is_present(new bool);
231 scoped_ptr<bool> lookup_succeeded(new bool);
232 bool* is_present_ptr = is_present.get();
233 bool* lookup_succeeded_ptr = lookup_succeeded.get();
234 prerender_manager->CheckIfLikelyLoggedInOnURL(
235 url,
236 is_present_ptr,
237 lookup_succeeded_ptr,
238 base::Bind(&PrerenderTabHelper::RecordEventIfLoggedInURLResult,
239 weak_factory_.GetWeakPtr(),
240 event,
241 base::Passed(&is_present),
242 base::Passed(&lookup_succeeded)));
245 void PrerenderTabHelper::RecordEventIfLoggedInURLResult(
246 PrerenderTabHelper::Event event,
247 scoped_ptr<bool> is_present,
248 scoped_ptr<bool> lookup_succeeded) {
249 if (*lookup_succeeded && *is_present)
250 RecordEvent(event);
253 void PrerenderTabHelper::RecordPerceivedPageLoadTime(
254 base::TimeDelta perceived_page_load_time,
255 double fraction_plt_elapsed_at_swap_in) {
256 DCHECK(!IsPrerendering());
257 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
258 if (!prerender_manager)
259 return;
261 // Note: it is possible for |next_load_is_control_prerender_| to be true at
262 // this point. This does not affect the classification of the current load,
263 // but only the next load. (This occurs if a WOULD_HAVE_BEEN_PRERENDERED
264 // navigation interrupts and aborts another navigation.)
265 prerender_manager->RecordPerceivedPageLoadTime(
266 origin_, navigation_type_, perceived_page_load_time,
267 fraction_plt_elapsed_at_swap_in, url_);
269 // Reset state for the next navigation.
270 navigation_type_ = NAVIGATION_TYPE_NORMAL;
271 origin_ = ORIGIN_NONE;
274 } // namespace prerender