summaryrefslogtreecommitdiffstats
path: root/chrome/browser/prerender/prerender_link_manager.h
blob: 56e6ad808b619080554afa133bd430a19ffd9cd8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_PRERENDER_PRERENDER_LINK_MANAGER_H_
#define CHROME_BROWSER_PRERENDER_PRERENDER_LINK_MANAGER_H_

#include <list>

#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "base/time/time.h"
#include "chrome/browser/prerender/prerender_handle.h"
#include "components/keyed_service/core/keyed_service.h"
#include "url/gurl.h"

class Profile;

namespace content {
struct Referrer;
}

namespace gfx {
class Size;
}

FORWARD_DECLARE_TEST(WebViewTest, NoPrerenderer);

namespace prerender {

class PrerenderContents;
class PrerenderManager;

// PrerenderLinkManager implements the API on Link elements for all documents
// being rendered in this chrome instance.  It receives messages from the
// renderer indicating addition, cancelation and abandonment of link elements,
// and controls the PrerenderManager accordingly.
class PrerenderLinkManager : public KeyedService,
                             public PrerenderHandle::Observer {
 public:
  explicit PrerenderLinkManager(PrerenderManager* manager);
  virtual ~PrerenderLinkManager();

  // A <link rel=prerender ...> element has been inserted into the document.
  // The |prerender_id| must be unique per |child_id|, and is assigned by the
  // WebPrerendererClient.
  void OnAddPrerender(int child_id,
                      int prerender_id,
                      const GURL& url,
                      uint32 rel_types,
                      const content::Referrer& referrer,
                      const gfx::Size& size,
                      int render_view_route_id);

  // A <link rel=prerender ...> element has been explicitly removed from a
  // document.
  void OnCancelPrerender(int child_id, int prerender_id);

  // A renderer launching <link rel=prerender ...> has navigated away from the
  // launching page, the launching renderer process has crashed, or perhaps the
  // renderer process was fast-closed when the last render view in it was
  // closed.
  void OnAbandonPrerender(int child_id, int prerender_id);

  // If a renderer channel closes (crash, fast exit, etc...), that's effectively
  // an abandon of any prerenders launched by that child.
  void OnChannelClosing(int child_id);

 private:
  friend class PrerenderBrowserTest;
  friend class PrerenderTest;
  // WebViewTest.NoPrerenderer needs to access the private IsEmpty() method.
  FRIEND_TEST_ALL_PREFIXES(::WebViewTest, NoPrerenderer);

  struct LinkPrerender {
    LinkPrerender(int launcher_child_id,
                  int prerender_id,
                  const GURL& url,
                  uint32 rel_types,
                  const content::Referrer& referrer,
                  const gfx::Size& size,
                  int render_view_route_id,
                  base::TimeTicks creation_time,
                  PrerenderContents* deferred_launcher);
    ~LinkPrerender();

    // Parameters from PrerenderLinkManager::OnAddPrerender():
    int launcher_child_id;
    int prerender_id;
    GURL url;
    uint32 rel_types;
    content::Referrer referrer;
    gfx::Size size;
    int render_view_route_id;

    // The time at which this Prerender was added to PrerenderLinkManager.
    base::TimeTicks creation_time;

    // If non-NULL, this link prerender was launched by an unswapped prerender,
    // |deferred_launcher|. When |deferred_launcher| is swapped in, the field is
    // set to NULL.
    PrerenderContents* deferred_launcher;

    // Initially NULL, |handle| is set once we start this prerender. It is owned
    // by this struct, and must be deleted before destructing this struct.
    PrerenderHandle* handle;

    // True if this prerender has become a MatchComplete replacement. This state
    // is maintained so the renderer is not notified of a stop twice.
    bool is_match_complete_replacement;

    // True if this prerender has been abandoned by its launcher.
    bool has_been_abandoned;
  };

  class PendingPrerenderManager;

  bool IsEmpty() const;

  // Returns a count of currently running prerenders.
  size_t CountRunningPrerenders() const;

  // Start any prerenders that can be started, respecting concurrency limits for
  // the system and per launcher.
  void StartPrerenders();

  LinkPrerender* FindByLauncherChildIdAndPrerenderId(int child_id,
                                                     int prerender_id);

  LinkPrerender* FindByPrerenderHandle(PrerenderHandle* prerender_handle);

  // Removes |prerender| from the the prerender link manager. Deletes the
  // PrerenderHandle as needed.
  void RemovePrerender(LinkPrerender* prerender);

  // Cancels |prerender| and removes |prerender| from the prerender link
  // manager.
  void CancelPrerender(LinkPrerender* prerender);

  // Called when |launcher| is swapped in.
  void StartPendingPrerendersForLauncher(PrerenderContents* launcher);

  // Called when |launcher| is aborted.
  void CancelPendingPrerendersForLauncher(PrerenderContents* launcher);

  // From KeyedService:
  virtual void Shutdown() OVERRIDE;

  // From PrerenderHandle::Observer:
  virtual void OnPrerenderStart(PrerenderHandle* prerender_handle) OVERRIDE;
  virtual void OnPrerenderStopLoading(PrerenderHandle* prerender_handle)
      OVERRIDE;
  virtual void OnPrerenderDomContentLoaded(PrerenderHandle* prerender_handle)
      OVERRIDE;
  virtual void OnPrerenderStop(PrerenderHandle* prerender_handle) OVERRIDE;
  virtual void OnPrerenderCreatedMatchCompleteReplacement(
      PrerenderHandle* handle) OVERRIDE;

  bool has_shutdown_;

  PrerenderManager* manager_;

  // All prerenders known to this PrerenderLinkManager. Insertions are always
  // made at the back, so the oldest prerender is at the front, and the youngest
  // at the back.
  std::list<LinkPrerender> prerenders_;

  // Helper object to manage prerenders which are launched by other prerenders
  // and must be deferred until the launcher is swapped in.
  scoped_ptr<PendingPrerenderManager> pending_prerender_manager_;

  DISALLOW_COPY_AND_ASSIGN(PrerenderLinkManager);
};

}  // namespace prerender

#endif  // CHROME_BROWSER_PRERENDER_PRERENDER_LINK_MANAGER_H_