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.
4
5#ifndef CHROME_BROWSER_PRERENDER_PRERENDER_TAB_HELPER_H_
6#define CHROME_BROWSER_PRERENDER_PRERENDER_TAB_HELPER_H_
7
8#include "base/memory/scoped_ptr.h"
9#include "base/memory/weak_ptr.h"
10#include "base/time/time.h"
11#include "chrome/browser/prerender/prerender_histograms.h"
12#include "chrome/browser/prerender/prerender_origin.h"
13#include "content/public/browser/web_contents_observer.h"
14#include "content/public/browser/web_contents_user_data.h"
15#include "url/gurl.h"
16
17namespace autofill {
18struct PasswordForm;
19}
20
21namespace password_manager {
22class PasswordManager;
23}
24
25namespace prerender {
26
27class PrerenderManager;
28
29// PrerenderTabHelper is responsible for recording perceived pageload times
30// to compare PLT's with prerendering enabled and disabled.
31class PrerenderTabHelper
32    : public content::WebContentsObserver,
33      public content::WebContentsUserData<PrerenderTabHelper> {
34 public:
35  enum Event {
36    EVENT_LOGGED_IN_TABLE_REQUESTED = 0,
37    EVENT_LOGGED_IN_TABLE_PRESENT = 1,
38    EVENT_MAINFRAME_CHANGE = 2,
39    EVENT_MAINFRAME_CHANGE_DOMAIN_LOGGED_IN = 3,
40    EVENT_MAINFRAME_COMMIT = 4,
41    EVENT_MAINFRAME_COMMIT_DOMAIN_LOGGED_IN = 5,
42    EVENT_LOGIN_ACTION_ADDED = 6,
43    EVENT_LOGIN_ACTION_ADDED_PW_EMPTY = 7,
44    EVENT_MAX_VALUE
45  };
46
47  static void CreateForWebContentsWithPasswordManager(
48      content::WebContents* web_contents,
49      password_manager::PasswordManager* password_manager);
50
51  virtual ~PrerenderTabHelper();
52
53  // content::WebContentsObserver implementation.
54  virtual void DidGetRedirectForResourceRequest(
55      content::RenderViewHost* render_view_host,
56      const content::ResourceRedirectDetails& details) OVERRIDE;
57  virtual void DidStopLoading(
58      content::RenderViewHost* render_view_host) OVERRIDE;
59  virtual void DidStartProvisionalLoadForFrame(
60      content::RenderFrameHost* render_frame_host,
61      const GURL& validated_url,
62      bool is_error_page,
63      bool is_iframe_srcdoc) OVERRIDE;
64  virtual void DidCommitProvisionalLoadForFrame(
65      content::RenderFrameHost* render_frame_host,
66      const GURL& validated_url,
67      ui::PageTransition transition_type) OVERRIDE;
68
69  // Called when the URL of the main frame changed, either when the load
70  // commits, or a redirect happens.
71  void MainFrameUrlDidChange(const GURL& url);
72
73  // Called when a password form has been submitted.
74  void PasswordSubmitted(const autofill::PasswordForm& form);
75
76  // Called when this prerendered WebContents has just been swapped in.
77  void PrerenderSwappedIn();
78
79  // Called when a control prerender is resolved. Applies to the next load.
80  void WouldHavePrerenderedNextLoad(Origin origin);
81
82 private:
83  PrerenderTabHelper(content::WebContents* web_contents,
84                     password_manager::PasswordManager* password_manager);
85  friend class content::WebContentsUserData<PrerenderTabHelper>;
86
87  void RecordEvent(Event event) const;
88  void RecordEventIfLoggedInURL(Event event, const GURL& url);
89  void RecordEventIfLoggedInURLResult(Event event, scoped_ptr<bool> is_present,
90                                      scoped_ptr<bool> lookup_succeeded);
91
92  void RecordPerceivedPageLoadTime(
93      base::TimeDelta perceived_page_load_time,
94      double fraction_plt_elapsed_at_swap_in);
95
96  // Retrieves the PrerenderManager, or NULL, if none was found.
97  PrerenderManager* MaybeGetPrerenderManager() const;
98
99  // Returns whether the WebContents being observed is currently prerendering.
100  bool IsPrerendering();
101
102  // The type the current pending navigation, if there is one. If the tab is a
103  // prerender before swap, the value is always NAVIGATION_TYPE_PRERENDERED,
104  // even if the prerender is not currently loading.
105  NavigationType navigation_type_;
106
107  // If |navigation_type_| is not NAVIGATION_TYPE_NORMAL, the origin of the
108  // relevant prerender. Otherwise, ORIGIN_NONE.
109  Origin origin_;
110
111  // True if the next load will be associated with a control prerender. This
112  // extra state is needed because control prerenders are resolved before the
113  // actual load begins. |next_load_origin_| gives the origin of the control
114  // prerender.
115  bool next_load_is_control_prerender_;
116  Origin next_load_origin_;
117
118  // System time at which the current load was started for the purpose of
119  // the perceived page load time (PPLT). If null, there is no current
120  // load.
121  base::TimeTicks pplt_load_start_;
122
123  // System time at which the actual pageload started (pre-swapin), if
124  // a applicable (in cases when a prerender that was still loading was
125  // swapped in).
126  base::TimeTicks actual_load_start_;
127
128  // Current URL being loaded.
129  GURL url_;
130
131  base::WeakPtrFactory<PrerenderTabHelper> weak_factory_;
132
133  DISALLOW_COPY_AND_ASSIGN(PrerenderTabHelper);
134};
135
136}  // namespace prerender
137
138#endif  // CHROME_BROWSER_PRERENDER_PRERENDER_TAB_HELPER_H_
139