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_LINK_MANAGER_H_
6#define CHROME_BROWSER_PRERENDER_PRERENDER_LINK_MANAGER_H_
7
8#include <list>
9
10#include "base/basictypes.h"
11#include "base/gtest_prod_util.h"
12#include "base/time/time.h"
13#include "chrome/browser/prerender/prerender_handle.h"
14#include "components/keyed_service/core/keyed_service.h"
15#include "url/gurl.h"
16
17class Profile;
18
19namespace content {
20struct Referrer;
21}
22
23namespace gfx {
24class Size;
25}
26
27FORWARD_DECLARE_TEST(WebViewTest, NoPrerenderer);
28
29namespace prerender {
30
31class PrerenderContents;
32class PrerenderManager;
33
34// PrerenderLinkManager implements the API on Link elements for all documents
35// being rendered in this chrome instance.  It receives messages from the
36// renderer indicating addition, cancelation and abandonment of link elements,
37// and controls the PrerenderManager accordingly.
38class PrerenderLinkManager : public KeyedService,
39                             public PrerenderHandle::Observer {
40 public:
41  explicit PrerenderLinkManager(PrerenderManager* manager);
42  virtual ~PrerenderLinkManager();
43
44  // A <link rel=prerender ...> element has been inserted into the document.
45  // The |prerender_id| must be unique per |child_id|, and is assigned by the
46  // WebPrerendererClient.
47  void OnAddPrerender(int child_id,
48                      int prerender_id,
49                      const GURL& url,
50                      uint32 rel_types,
51                      const content::Referrer& referrer,
52                      const gfx::Size& size,
53                      int render_view_route_id);
54
55  // A <link rel=prerender ...> element has been explicitly removed from a
56  // document.
57  void OnCancelPrerender(int child_id, int prerender_id);
58
59  // A renderer launching <link rel=prerender ...> has navigated away from the
60  // launching page, the launching renderer process has crashed, or perhaps the
61  // renderer process was fast-closed when the last render view in it was
62  // closed.
63  void OnAbandonPrerender(int child_id, int prerender_id);
64
65  // If a renderer channel closes (crash, fast exit, etc...), that's effectively
66  // an abandon of any prerenders launched by that child.
67  void OnChannelClosing(int child_id);
68
69 private:
70  friend class PrerenderBrowserTest;
71  friend class PrerenderTest;
72  // WebViewTest.NoPrerenderer needs to access the private IsEmpty() method.
73  FRIEND_TEST_ALL_PREFIXES(::WebViewTest, NoPrerenderer);
74
75  struct LinkPrerender {
76    LinkPrerender(int launcher_child_id,
77                  int prerender_id,
78                  const GURL& url,
79                  uint32 rel_types,
80                  const content::Referrer& referrer,
81                  const gfx::Size& size,
82                  int render_view_route_id,
83                  base::TimeTicks creation_time,
84                  PrerenderContents* deferred_launcher);
85    ~LinkPrerender();
86
87    // Parameters from PrerenderLinkManager::OnAddPrerender():
88    int launcher_child_id;
89    int prerender_id;
90    GURL url;
91    uint32 rel_types;
92    content::Referrer referrer;
93    gfx::Size size;
94    int render_view_route_id;
95
96    // The time at which this Prerender was added to PrerenderLinkManager.
97    base::TimeTicks creation_time;
98
99    // If non-NULL, this link prerender was launched by an unswapped prerender,
100    // |deferred_launcher|. When |deferred_launcher| is swapped in, the field is
101    // set to NULL.
102    PrerenderContents* deferred_launcher;
103
104    // Initially NULL, |handle| is set once we start this prerender. It is owned
105    // by this struct, and must be deleted before destructing this struct.
106    PrerenderHandle* handle;
107
108    // True if this prerender has become a MatchComplete replacement. This state
109    // is maintained so the renderer is not notified of a stop twice.
110    bool is_match_complete_replacement;
111
112    // True if this prerender has been abandoned by its launcher.
113    bool has_been_abandoned;
114  };
115
116  class PendingPrerenderManager;
117
118  bool IsEmpty() const;
119
120  // Returns a count of currently running prerenders.
121  size_t CountRunningPrerenders() const;
122
123  // Start any prerenders that can be started, respecting concurrency limits for
124  // the system and per launcher.
125  void StartPrerenders();
126
127  LinkPrerender* FindByLauncherChildIdAndPrerenderId(int child_id,
128                                                     int prerender_id);
129
130  LinkPrerender* FindByPrerenderHandle(PrerenderHandle* prerender_handle);
131
132  // Removes |prerender| from the the prerender link manager. Deletes the
133  // PrerenderHandle as needed.
134  void RemovePrerender(LinkPrerender* prerender);
135
136  // Cancels |prerender| and removes |prerender| from the prerender link
137  // manager.
138  void CancelPrerender(LinkPrerender* prerender);
139
140  // Called when |launcher| is swapped in.
141  void StartPendingPrerendersForLauncher(PrerenderContents* launcher);
142
143  // Called when |launcher| is aborted.
144  void CancelPendingPrerendersForLauncher(PrerenderContents* launcher);
145
146  // From KeyedService:
147  virtual void Shutdown() OVERRIDE;
148
149  // From PrerenderHandle::Observer:
150  virtual void OnPrerenderStart(PrerenderHandle* prerender_handle) OVERRIDE;
151  virtual void OnPrerenderStopLoading(PrerenderHandle* prerender_handle)
152      OVERRIDE;
153  virtual void OnPrerenderDomContentLoaded(PrerenderHandle* prerender_handle)
154      OVERRIDE;
155  virtual void OnPrerenderStop(PrerenderHandle* prerender_handle) OVERRIDE;
156  virtual void OnPrerenderCreatedMatchCompleteReplacement(
157      PrerenderHandle* handle) OVERRIDE;
158
159  bool has_shutdown_;
160
161  PrerenderManager* manager_;
162
163  // All prerenders known to this PrerenderLinkManager. Insertions are always
164  // made at the back, so the oldest prerender is at the front, and the youngest
165  // at the back.
166  std::list<LinkPrerender> prerenders_;
167
168  // Helper object to manage prerenders which are launched by other prerenders
169  // and must be deferred until the launcher is swapped in.
170  scoped_ptr<PendingPrerenderManager> pending_prerender_manager_;
171
172  DISALLOW_COPY_AND_ASSIGN(PrerenderLinkManager);
173};
174
175}  // namespace prerender
176
177#endif  // CHROME_BROWSER_PRERENDER_PRERENDER_LINK_MANAGER_H_
178