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/browser_context_keyed_service/browser_context_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 PrerenderHandle;
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 BrowserContextKeyedService,
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                      const content::Referrer& referrer,
51                      const gfx::Size& size,
52                      int render_view_route_id);
53
54  // A <link rel=prerender ...> element has been explicitly removed from a
55  // document.
56  void OnCancelPrerender(int child_id, int prerender_id);
57
58  // A renderer launching <link rel=prerender ...> has navigated away from the
59  // launching page, the launching renderer process has crashed, or perhaps the
60  // renderer process was fast-closed when the last render view in it was
61  // closed.
62  void OnAbandonPrerender(int child_id, int prerender_id);
63
64  // If a renderer channel closes (crash, fast exit, etc...), that's effectively
65  // an abandon of any prerenders launched by that child.
66  void OnChannelClosing(int child_id);
67
68 private:
69  friend class PrerenderBrowserTest;
70  friend class PrerenderTest;
71  // WebViewTest.NoPrerenderer needs to access the private IsEmpty() method.
72  FRIEND_TEST_ALL_PREFIXES(::WebViewTest, NoPrerenderer);
73
74  struct LinkPrerender {
75    LinkPrerender(int launcher_child_id,
76                  int prerender_id,
77                  const GURL& url,
78                  const content::Referrer& referrer,
79                  const gfx::Size& size,
80                  int render_view_route_id,
81                  base::TimeTicks creation_time);
82    ~LinkPrerender();
83
84    // Parameters from PrerenderLinkManager::OnAddPrerender():
85    int launcher_child_id;
86    int prerender_id;
87    GURL url;
88    content::Referrer referrer;
89    gfx::Size size;
90    int render_view_route_id;
91
92    // The time at which this Prerender was added to PrerenderLinkManager.
93    base::TimeTicks creation_time;
94
95    // Initially NULL, |handle| is set once we start this prerender. It is owned
96    // by this struct, and must be deleted before destructing this struct.
97    PrerenderHandle* handle;
98  };
99
100  bool IsEmpty() const;
101
102  // Returns a count of currently running prerenders.
103  size_t CountRunningPrerenders() const;
104
105  // Start any prerenders that can be started, respecting concurrency limits for
106  // the system and per launcher.
107  void StartPrerenders();
108
109  LinkPrerender* FindByLauncherChildIdAndPrerenderId(int child_id,
110                                                     int prerender_id);
111
112  LinkPrerender* FindByPrerenderHandle(PrerenderHandle* prerender_handle);
113
114  void RemovePrerender(LinkPrerender* prerender);
115
116  // From BrowserContextKeyedService:
117  virtual void Shutdown() OVERRIDE;
118
119  // From PrerenderHandle::Observer:
120  virtual void OnPrerenderStart(PrerenderHandle* prerender_handle) OVERRIDE;
121  virtual void OnPrerenderStopLoading(PrerenderHandle* prerender_handle)
122      OVERRIDE;
123  virtual void OnPrerenderStop(PrerenderHandle* prerender_handle) OVERRIDE;
124
125  bool has_shutdown_;
126
127  PrerenderManager* manager_;
128
129  // All prerenders known to this PrerenderLinkManager. Insertions are always
130  // made at the back, so the oldest prerender is at the front, and the youngest
131  // at the back.
132  std::list<LinkPrerender> prerenders_;
133
134  DISALLOW_COPY_AND_ASSIGN(PrerenderLinkManager);
135};
136
137}  // namespace prerender
138
139#endif  // CHROME_BROWSER_PRERENDER_PRERENDER_LINK_MANAGER_H_
140
141