Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / browser / prerender / prerender_tab_helper.cc
blob3fe0dcdbf151c7e645bb27868da4a6ecacf8ba8c
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/prerender/prerender_histograms.h"
11 #include "chrome/browser/prerender/prerender_local_predictor.h"
12 #include "chrome/browser/prerender/prerender_manager.h"
13 #include "chrome/browser/prerender/prerender_manager_factory.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "components/password_manager/core/browser/password_manager.h"
16 #include "content/public/browser/navigation_details.h"
17 #include "content/public/browser/navigation_entry.h"
18 #include "content/public/browser/render_view_host.h"
19 #include "content/public/browser/web_contents.h"
20 #include "content/public/common/frame_navigate_params.h"
22 using content::WebContents;
24 DEFINE_WEB_CONTENTS_USER_DATA_KEY(prerender::PrerenderTabHelper);
26 namespace prerender {
28 namespace {
30 void ReportTabHelperURLSeenToLocalPredictor(
31 PrerenderManager* prerender_manager,
32 const GURL& url,
33 WebContents* web_contents) {
34 if (!prerender_manager)
35 return;
36 PrerenderLocalPredictor* local_predictor =
37 prerender_manager->local_predictor();
38 if (!local_predictor)
39 return;
40 local_predictor->OnTabHelperURLSeen(url, web_contents);
43 } // namespace
45 // static
46 void PrerenderTabHelper::CreateForWebContentsWithPasswordManager(
47 content::WebContents* web_contents,
48 password_manager::PasswordManager* password_manager) {
49 if (!FromWebContents(web_contents)) {
50 web_contents->SetUserData(UserDataKey(),
51 new PrerenderTabHelper(web_contents,
52 password_manager));
56 PrerenderTabHelper::PrerenderTabHelper(
57 content::WebContents* web_contents,
58 password_manager::PasswordManager* password_manager)
59 : content::WebContentsObserver(web_contents),
60 origin_(ORIGIN_NONE),
61 next_load_is_control_prerender_(false),
62 next_load_origin_(ORIGIN_NONE),
63 weak_factory_(this) {
64 if (password_manager) {
65 // May be NULL in testing.
66 password_manager->AddSubmissionCallback(
67 base::Bind(&PrerenderTabHelper::PasswordSubmitted,
68 weak_factory_.GetWeakPtr()));
71 // Determine if this is a prerender.
72 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
73 if (prerender_manager &&
74 prerender_manager->IsWebContentsPrerendering(web_contents, &origin_)) {
75 navigation_type_ = NAVIGATION_TYPE_PRERENDERED;
76 } else {
77 navigation_type_ = NAVIGATION_TYPE_NORMAL;
81 PrerenderTabHelper::~PrerenderTabHelper() {
84 void PrerenderTabHelper::ProvisionalChangeToMainFrameUrl(
85 const GURL& url,
86 content::RenderFrameHost* render_frame_host) {
87 url_ = url;
88 RecordEvent(EVENT_MAINFRAME_CHANGE);
89 RecordEventIfLoggedInURL(EVENT_MAINFRAME_CHANGE_DOMAIN_LOGGED_IN, url);
90 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
91 if (!prerender_manager)
92 return;
93 if (prerender_manager->IsWebContentsPrerendering(web_contents(), NULL))
94 return;
95 ReportTabHelperURLSeenToLocalPredictor(prerender_manager, url,
96 web_contents());
99 void PrerenderTabHelper::DidCommitProvisionalLoadForFrame(
100 int64 frame_id,
101 const base::string16& frame_unique_name,
102 bool is_main_frame,
103 const GURL& validated_url,
104 content::PageTransition transition_type,
105 content::RenderViewHost* render_view_host) {
106 if (!is_main_frame)
107 return;
108 RecordEvent(EVENT_MAINFRAME_COMMIT);
109 RecordEventIfLoggedInURL(EVENT_MAINFRAME_COMMIT_DOMAIN_LOGGED_IN,
110 validated_url);
111 url_ = validated_url;
112 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
113 if (!prerender_manager)
114 return;
115 if (prerender_manager->IsWebContentsPrerendering(web_contents(), NULL))
116 return;
117 prerender_manager->RecordNavigation(validated_url);
118 ReportTabHelperURLSeenToLocalPredictor(prerender_manager, validated_url,
119 web_contents());
122 void PrerenderTabHelper::DidStopLoading(
123 content::RenderViewHost* render_view_host) {
124 // Compute the PPLT metric and report it in a histogram, if needed. If the
125 // page is still prerendering, record the not swapped in page load time
126 // instead.
127 if (!pplt_load_start_.is_null()) {
128 base::TimeTicks now = base::TimeTicks::Now();
129 if (IsPrerendering()) {
130 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
131 if (prerender_manager) {
132 prerender_manager->RecordPageLoadTimeNotSwappedIn(
133 origin_, now - pplt_load_start_, url_);
134 } else {
135 NOTREACHED();
137 } else {
138 double fraction_elapsed_at_swapin = -1.0;
139 if (!actual_load_start_.is_null()) {
140 double plt = (now - actual_load_start_).InMillisecondsF();
141 if (plt > 0.0) {
142 fraction_elapsed_at_swapin = 1.0 -
143 (now - pplt_load_start_).InMillisecondsF() / plt;
144 } else {
145 fraction_elapsed_at_swapin = 1.0;
147 DCHECK_GE(fraction_elapsed_at_swapin, 0.0);
148 DCHECK_LE(fraction_elapsed_at_swapin, 1.0);
151 RecordPerceivedPageLoadTime(
152 now - pplt_load_start_, fraction_elapsed_at_swapin);
156 // Reset the PPLT metric.
157 pplt_load_start_ = base::TimeTicks();
158 actual_load_start_ = base::TimeTicks();
161 void PrerenderTabHelper::DidStartProvisionalLoadForFrame(
162 int64 frame_id,
163 int64 parent_frame_id,
164 bool is_main_frame,
165 const GURL& validated_url,
166 bool is_error_page,
167 bool is_iframe_srcdoc,
168 content::RenderViewHost* render_view_host) {
169 if (!is_main_frame)
170 return;
172 // Record PPLT state for the beginning of a new navigation.
173 pplt_load_start_ = base::TimeTicks::Now();
174 actual_load_start_ = base::TimeTicks();
176 if (next_load_is_control_prerender_) {
177 DCHECK_EQ(NAVIGATION_TYPE_NORMAL, navigation_type_);
178 navigation_type_ = NAVIGATION_TYPE_WOULD_HAVE_BEEN_PRERENDERED;
179 origin_ = next_load_origin_;
180 next_load_is_control_prerender_ = false;
181 next_load_origin_ = ORIGIN_NONE;
185 void PrerenderTabHelper::PasswordSubmitted(const autofill::PasswordForm& form) {
186 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
187 if (prerender_manager) {
188 prerender_manager->RecordLikelyLoginOnURL(form.origin);
189 RecordEvent(EVENT_LOGIN_ACTION_ADDED);
190 if (form.password_value.empty())
191 RecordEvent(EVENT_LOGIN_ACTION_ADDED_PW_EMPTY);
195 PrerenderManager* PrerenderTabHelper::MaybeGetPrerenderManager() const {
196 return PrerenderManagerFactory::GetForProfile(
197 Profile::FromBrowserContext(web_contents()->GetBrowserContext()));
200 bool PrerenderTabHelper::IsPrerendering() {
201 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
202 if (!prerender_manager)
203 return false;
204 return prerender_manager->IsWebContentsPrerendering(web_contents(), NULL);
207 void PrerenderTabHelper::PrerenderSwappedIn() {
208 // Ensure we are not prerendering any more.
209 DCHECK_EQ(NAVIGATION_TYPE_PRERENDERED, navigation_type_);
210 DCHECK(!IsPrerendering());
211 if (pplt_load_start_.is_null()) {
212 // If we have already finished loading, report a 0 PPLT.
213 RecordPerceivedPageLoadTime(base::TimeDelta(), 1.0);
214 DCHECK_EQ(NAVIGATION_TYPE_NORMAL, navigation_type_);
215 } else {
216 // If we have not finished loading yet, record the actual load start, and
217 // rebase the start time to now.
218 actual_load_start_ = pplt_load_start_;
219 pplt_load_start_ = base::TimeTicks::Now();
223 void PrerenderTabHelper::WouldHavePrerenderedNextLoad(Origin origin) {
224 next_load_is_control_prerender_ = true;
225 next_load_origin_ = origin;
228 void PrerenderTabHelper::RecordEvent(PrerenderTabHelper::Event event) const {
229 UMA_HISTOGRAM_ENUMERATION("Prerender.TabHelperEvent",
230 event, PrerenderTabHelper::EVENT_MAX_VALUE);
233 void PrerenderTabHelper::RecordEventIfLoggedInURL(
234 PrerenderTabHelper::Event event, const GURL& url) {
235 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
236 if (!prerender_manager)
237 return;
238 scoped_ptr<bool> is_present(new bool);
239 scoped_ptr<bool> lookup_succeeded(new bool);
240 bool* is_present_ptr = is_present.get();
241 bool* lookup_succeeded_ptr = lookup_succeeded.get();
242 prerender_manager->CheckIfLikelyLoggedInOnURL(
243 url,
244 is_present_ptr,
245 lookup_succeeded_ptr,
246 base::Bind(&PrerenderTabHelper::RecordEventIfLoggedInURLResult,
247 weak_factory_.GetWeakPtr(),
248 event,
249 base::Passed(&is_present),
250 base::Passed(&lookup_succeeded)));
253 void PrerenderTabHelper::RecordEventIfLoggedInURLResult(
254 PrerenderTabHelper::Event event,
255 scoped_ptr<bool> is_present,
256 scoped_ptr<bool> lookup_succeeded) {
257 if (*lookup_succeeded && *is_present)
258 RecordEvent(event);
261 void PrerenderTabHelper::RecordPerceivedPageLoadTime(
262 base::TimeDelta perceived_page_load_time,
263 double fraction_plt_elapsed_at_swap_in) {
264 DCHECK(!IsPrerendering());
265 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
266 if (!prerender_manager)
267 return;
269 // Note: it is possible for |next_load_is_control_prerender_| to be true at
270 // this point. This does not affect the classification of the current load,
271 // but only the next load. (This occurs if a WOULD_HAVE_BEEN_PRERENDERED
272 // navigation interrupts and aborts another navigation.)
273 prerender_manager->RecordPerceivedPageLoadTime(
274 origin_, navigation_type_, perceived_page_load_time,
275 fraction_plt_elapsed_at_swap_in, url_);
277 // Reset state for the next navigation.
278 navigation_type_ = NAVIGATION_TYPE_NORMAL;
279 origin_ = ORIGIN_NONE;
282 } // namespace prerender