Remove the old signature of NotificationManager::closePersistent().
[chromium-blink-merge.git] / chrome / browser / prerender / prerender_tab_helper.cc
blob33017f7ae829ff44b799c1483c4a91dbd49eb38d
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 content::RenderViewHost* render_view_host) {
105 // Compute the PPLT metric and report it in a histogram, if needed. If the
106 // page is still prerendering, record the not swapped in page load time
107 // instead.
108 if (!pplt_load_start_.is_null()) {
109 base::TimeTicks now = base::TimeTicks::Now();
110 if (IsPrerendering()) {
111 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
112 if (prerender_manager) {
113 prerender_manager->RecordPageLoadTimeNotSwappedIn(
114 origin_, now - pplt_load_start_, url_);
115 } else {
116 NOTREACHED();
118 } else {
119 double fraction_elapsed_at_swapin = -1.0;
120 if (!actual_load_start_.is_null()) {
121 double plt = (now - actual_load_start_).InMillisecondsF();
122 if (plt > 0.0) {
123 fraction_elapsed_at_swapin = 1.0 -
124 (now - pplt_load_start_).InMillisecondsF() / plt;
125 } else {
126 fraction_elapsed_at_swapin = 1.0;
128 DCHECK_GE(fraction_elapsed_at_swapin, 0.0);
129 DCHECK_LE(fraction_elapsed_at_swapin, 1.0);
132 RecordPerceivedPageLoadTime(
133 now - pplt_load_start_, fraction_elapsed_at_swapin);
137 // Reset the PPLT metric.
138 pplt_load_start_ = base::TimeTicks();
139 actual_load_start_ = base::TimeTicks();
142 void PrerenderTabHelper::DidStartProvisionalLoadForFrame(
143 content::RenderFrameHost* render_frame_host,
144 const GURL& validated_url,
145 bool is_error_page,
146 bool is_iframe_srcdoc) {
147 if (render_frame_host->GetParent())
148 return;
150 // Record PPLT state for the beginning of a new navigation.
151 pplt_load_start_ = base::TimeTicks::Now();
152 actual_load_start_ = base::TimeTicks();
154 if (next_load_is_control_prerender_) {
155 DCHECK_EQ(NAVIGATION_TYPE_NORMAL, navigation_type_);
156 navigation_type_ = NAVIGATION_TYPE_WOULD_HAVE_BEEN_PRERENDERED;
157 origin_ = next_load_origin_;
158 next_load_is_control_prerender_ = false;
159 next_load_origin_ = ORIGIN_NONE;
162 MainFrameUrlDidChange(validated_url);
165 void PrerenderTabHelper::MainFrameUrlDidChange(const GURL& url) {
166 url_ = url;
167 RecordEvent(EVENT_MAINFRAME_CHANGE);
168 RecordEventIfLoggedInURL(EVENT_MAINFRAME_CHANGE_DOMAIN_LOGGED_IN, url);
169 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
170 if (!prerender_manager)
171 return;
172 if (prerender_manager->IsWebContentsPrerendering(web_contents(), NULL))
173 return;
174 ReportTabHelperURLSeenToLocalPredictor(prerender_manager, url,
175 web_contents());
178 void PrerenderTabHelper::PasswordSubmitted(const autofill::PasswordForm& form) {
179 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
180 if (prerender_manager) {
181 prerender_manager->RecordLikelyLoginOnURL(form.origin);
182 RecordEvent(EVENT_LOGIN_ACTION_ADDED);
183 if (form.password_value.empty())
184 RecordEvent(EVENT_LOGIN_ACTION_ADDED_PW_EMPTY);
188 PrerenderManager* PrerenderTabHelper::MaybeGetPrerenderManager() const {
189 return PrerenderManagerFactory::GetForProfile(
190 Profile::FromBrowserContext(web_contents()->GetBrowserContext()));
193 bool PrerenderTabHelper::IsPrerendering() {
194 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
195 if (!prerender_manager)
196 return false;
197 return prerender_manager->IsWebContentsPrerendering(web_contents(), NULL);
200 void PrerenderTabHelper::PrerenderSwappedIn() {
201 // Ensure we are not prerendering any more.
202 DCHECK_EQ(NAVIGATION_TYPE_PRERENDERED, navigation_type_);
203 DCHECK(!IsPrerendering());
204 if (pplt_load_start_.is_null()) {
205 // If we have already finished loading, report a 0 PPLT.
206 RecordPerceivedPageLoadTime(base::TimeDelta(), 1.0);
207 DCHECK_EQ(NAVIGATION_TYPE_NORMAL, navigation_type_);
208 } else {
209 // If we have not finished loading yet, record the actual load start, and
210 // rebase the start time to now.
211 actual_load_start_ = pplt_load_start_;
212 pplt_load_start_ = base::TimeTicks::Now();
216 void PrerenderTabHelper::WouldHavePrerenderedNextLoad(Origin origin) {
217 next_load_is_control_prerender_ = true;
218 next_load_origin_ = origin;
221 void PrerenderTabHelper::RecordEvent(PrerenderTabHelper::Event event) const {
222 UMA_HISTOGRAM_ENUMERATION("Prerender.TabHelperEvent",
223 event, PrerenderTabHelper::EVENT_MAX_VALUE);
226 void PrerenderTabHelper::RecordEventIfLoggedInURL(
227 PrerenderTabHelper::Event event, const GURL& url) {
228 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
229 if (!prerender_manager)
230 return;
231 scoped_ptr<bool> is_present(new bool);
232 scoped_ptr<bool> lookup_succeeded(new bool);
233 bool* is_present_ptr = is_present.get();
234 bool* lookup_succeeded_ptr = lookup_succeeded.get();
235 prerender_manager->CheckIfLikelyLoggedInOnURL(
236 url,
237 is_present_ptr,
238 lookup_succeeded_ptr,
239 base::Bind(&PrerenderTabHelper::RecordEventIfLoggedInURLResult,
240 weak_factory_.GetWeakPtr(),
241 event,
242 base::Passed(&is_present),
243 base::Passed(&lookup_succeeded)));
246 void PrerenderTabHelper::RecordEventIfLoggedInURLResult(
247 PrerenderTabHelper::Event event,
248 scoped_ptr<bool> is_present,
249 scoped_ptr<bool> lookup_succeeded) {
250 if (*lookup_succeeded && *is_present)
251 RecordEvent(event);
254 void PrerenderTabHelper::RecordPerceivedPageLoadTime(
255 base::TimeDelta perceived_page_load_time,
256 double fraction_plt_elapsed_at_swap_in) {
257 DCHECK(!IsPrerendering());
258 PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
259 if (!prerender_manager)
260 return;
262 // Note: it is possible for |next_load_is_control_prerender_| to be true at
263 // this point. This does not affect the classification of the current load,
264 // but only the next load. (This occurs if a WOULD_HAVE_BEEN_PRERENDERED
265 // navigation interrupts and aborts another navigation.)
266 prerender_manager->RecordPerceivedPageLoadTime(
267 origin_, navigation_type_, perceived_page_load_time,
268 fraction_plt_elapsed_at_swap_in, url_);
270 // Reset state for the next navigation.
271 navigation_type_ = NAVIGATION_TYPE_NORMAL;
272 origin_ = ORIGIN_NONE;
275 } // namespace prerender