summaryrefslogtreecommitdiffstats
path: root/chrome/browser/prerender/prerender_contents.h
blob: feeb4f43963a6aa7540be0fadf9c17b8e5686e73 (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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
// 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_CONTENTS_H_
#define CHROME_BROWSER_PRERENDER_PRERENDER_CONTENTS_H_
#pragma once

#include <list>
#include <string>
#include <vector>

#include "base/memory/scoped_ptr.h"
#include "base/time.h"
#include "base/values.h"
#include "chrome/browser/prerender/prerender_final_status.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/referrer.h"

class Profile;
class TabContentsWrapper;
struct FaviconURL;

namespace base {
class ProcessMetrics;
}

namespace content {
class RenderViewHost;
class RenderViewHostDelegate;
class SessionStorageNamespace;
class WebContents;
}

namespace prerender {

class PrerenderManager;
class PrerenderRenderViewHostObserver;
class PrerenderTracker;

class PrerenderContents : public content::NotificationObserver,
                          public content::WebContentsObserver {
 public:
  // PrerenderContents::Create uses the currently registered Factory to create
  // the PrerenderContents. Factory is intended for testing.
  class Factory {
   public:
    Factory() {}
    virtual ~Factory() {}

    // Ownership is not transfered through this interface as prerender_manager,
    // prerender_tracker, and profile are stored as weak pointers.
    virtual PrerenderContents* CreatePrerenderContents(
        PrerenderManager* prerender_manager,
        PrerenderTracker* prerender_tracker,
        Profile* profile,
        const GURL& url,
        const content::Referrer& referrer,
        Origin origin,
        uint8 experiment_id) = 0;

   private:
    DISALLOW_COPY_AND_ASSIGN(Factory);
  };

  // Information on pages that the prerendered page has tried to prerender.
  struct PendingPrerenderData {
    PendingPrerenderData(Origin origin,
                         const GURL& url,
                         const content::Referrer& referrer);

    Origin origin;
    GURL url;
    content::Referrer referrer;
  };
  typedef std::list<PendingPrerenderData> PendingPrerenderList;

  // Indicates how this PrerenderContents relates to MatchComplete.
  // This is important to figure out in what histograms to record the
  // FinalStatus in, as described below.
  enum MatchCompleteStatus {
    // A regular prerender which will be recorded both in Match and
    // MatchComplete.
    MATCH_COMPLETE_DEFAULT,
    // A prerender that used to be a regular prerender, but has since
    // been replaced by a MatchComplete dummy.  Therefore, we will record
    // this only for Match, but not for MatchComplete.
    MATCH_COMPLETE_REPLACED,
    // A prerender that is a MatchComplete dummy replacing a regular
    // prerender.  Therefore, we will record this only for MatchComplete,
    // but not Match.
    MATCH_COMPLETE_REPLACEMENT
  };

  virtual ~PrerenderContents();

  bool Init();

  static Factory* CreateFactory();

  // |source_render_view_host| is the RenderViewHost that initiated
  // prerendering.
  virtual void StartPrerendering(
      const content::RenderViewHost* source_render_view_host,
      content::SessionStorageNamespace* session_storage_namespace);

  // Verifies that the prerendering is not using too many resources, and kills
  // it if not.
  void DestroyWhenUsingTooManyResources();

  content::RenderViewHost* render_view_host_mutable();
  const content::RenderViewHost* render_view_host() const;
  string16 title() const { return title_; }
  int32 page_id() const { return page_id_; }
  GURL icon_url() const { return icon_url_; }
  const GURL& prerender_url() const { return prerender_url_; }
  const content::Referrer& referrer() const { return referrer_; }
  bool has_stopped_loading() const { return has_stopped_loading_; }
  bool has_finished_loading() const { return has_finished_loading_; }
  bool prerendering_has_started() const { return prerendering_has_started_; }
  MatchCompleteStatus match_complete_status() const {
    return match_complete_status_;
  }
  void set_match_complete_status(MatchCompleteStatus status) {
    match_complete_status_ = status;
  }

  // Sets the parameter to the value of the associated RenderViewHost's child id
  // and returns a boolean indicating the validity of that id.
  virtual bool GetChildId(int* child_id) const;

  // Sets the parameter to the value of the associated RenderViewHost's route id
  // and returns a boolean indicating the validity of that id.
  virtual bool GetRouteId(int* route_id) const;

  // Set the final status for how the PrerenderContents was used. This
  // should only be called once, and should be called before the prerender
  // contents are destroyed.
  void set_final_status(FinalStatus final_status);
  FinalStatus final_status() const { return final_status_; }

  Origin origin() const { return origin_; }
  uint8 experiment_id() const { return experiment_id_; }

  base::TimeTicks load_start_time() const { return load_start_time_; }

  // Indicates whether this prerendered page can be used for the provided
  // URL, i.e. whether there is a match. |matching_url| is optional and will be
  // set to the URL that is found as a match if it is provided.
  bool MatchesURL(const GURL& url, GURL* matching_url) const;

  void OnJSOutOfMemory();
  bool ShouldSuppressDialogs();

  // content::WebContentsObserver implementation.
  virtual void DidStopLoading() OVERRIDE;
  virtual void DidStartProvisionalLoadForFrame(
      int64 frame_id,
      bool is_main_frame,
      const GURL& validated_url,
      bool is_error_page,
      content::RenderViewHost* render_view_host) OVERRIDE;
  virtual void DidFinishLoad(int64 frame_id,
                             const GURL& validated_url,
                             bool is_main_frame) OVERRIDE;

  virtual void RenderViewGone(base::TerminationStatus status) OVERRIDE;

  // content::NotificationObserver
  virtual void Observe(int type,
                       const content::NotificationSource& source,
                       const content::NotificationDetails& details) OVERRIDE;

  // Adds an alias URL, for one of the many redirections. If the URL can not
  // be prerendered - for example, it's an ftp URL - |this| will be destroyed
  // and false is returned. Otherwise, true is returned and the alias is
  // remembered.
  virtual bool AddAliasURL(const GURL& url);

  // Adds all alias URLs from another prerender.
  void AddAliasURLsFromOtherPrerenderContents(PrerenderContents* other_pc);

  // The preview TabContentsWrapper (may be null).
  TabContentsWrapper* prerender_contents() const {
    return prerender_contents_.get();
  }

  TabContentsWrapper* ReleasePrerenderContents();

  // Sets the final status, calls OnDestroy and adds |this| to the
  // PrerenderManager's pending deletes list.
  void Destroy(FinalStatus reason);

  // Applies all the URL history encountered during prerendering to the
  // new tab.
  void CommitHistory(TabContentsWrapper* tab);

  base::Value* GetAsValue() const;

  // Returns whether a pending cross-site navigation is happening.
  // This could happen with renderer-issued navigations, such as a
  // MouseEvent being dispatched by a link to a website installed as an app.
  bool IsCrossSiteNavigationPending() const;

  // Adds a pending prerender to the list.
  virtual void AddPendingPrerender(Origin origin,
                                   const GURL& url,
                                   const content::Referrer& referrer);

  // Returns true if |url| corresponds to a pending prerender.
  bool IsPendingEntry(const GURL& url) const;

  // Reissues any pending prerender requests from the prerendered page.  Also
  // clears the list of pending requests.
  void StartPendingPrerenders();

 protected:
  PrerenderContents(PrerenderManager* prerender_manager,
                    PrerenderTracker* prerender_tracker,
                    Profile* profile,
                    const GURL& url,
                    const content::Referrer& referrer,
                    Origin origin,
                    uint8 experiment_id);

  // Called whenever a RenderViewHost is created for prerendering.  Only called
  // once the RenderViewHost has a RenderView and RenderWidgetHostView.
  virtual void OnRenderViewHostCreated(
      content::RenderViewHost* new_render_view_host);

  content::NotificationRegistrar& notification_registrar() {
    return notification_registrar_;
  }

  const PendingPrerenderList* pending_prerender_list() const {
    return &pending_prerender_list_;
  }

  virtual content::WebContents* CreateWebContents(
      content::SessionStorageNamespace* session_storage_namespace);

 private:
  class TabContentsDelegateImpl;

  // Needs to be able to call the constructor.
  friend class PrerenderContentsFactoryImpl;

  friend class PrerenderRenderViewHostObserver;

  // Message handlers.
  void OnUpdateFaviconURL(int32 page_id, const std::vector<FaviconURL>& urls);

  // Returns the RenderViewHost Delegate for this prerender.
  content::WebContents* GetWebContents();

  // Returns the ProcessMetrics for the render process, if it exists.
  base::ProcessMetrics* MaybeGetProcessMetrics();

  // The prerender manager owning this object.
  PrerenderManager* prerender_manager_;

  // The prerender tracker tracking prerenders.
  PrerenderTracker* prerender_tracker_;

  // The URL being prerendered.
  GURL prerender_url_;

  // The referrer.
  content::Referrer referrer_;

  // The profile being used
  Profile* profile_;

  // Information about the title and URL of the page that this class as a
  // RenderViewHostDelegate has received from the RenderView.
  // Used to apply to the new RenderViewHost delegate that might eventually
  // own the contained RenderViewHost when the prerendered page is shown
  // in a WebContents.
  string16 title_;
  int32 page_id_;
  GURL url_;
  GURL icon_url_;
  content::NotificationRegistrar notification_registrar_;

  // A vector of URLs that this prerendered page matches against.
  // This array can contain more than element as a result of redirects,
  // such as HTTP redirects or javascript redirects.
  std::vector<GURL> alias_urls_;

  bool has_stopped_loading_;

  // True when the main frame has finished loading.
  bool has_finished_loading_;

  // This must be the same value as the PrerenderTracker has recorded for
  // |this|, when |this| has a RenderView.
  FinalStatus final_status_;

  bool prerendering_has_started_;

  // The MatchComplete status of the prerender, indicating how it relates
  // to being a MatchComplete dummy (see definition of MatchCompleteStatus
  // above).
  MatchCompleteStatus match_complete_status_;

  // Tracks whether or not prerendering has been cancelled by calling Destroy.
  // Used solely to prevent double deletion.
  bool prerendering_has_been_cancelled_;

  // Time at which we started to load the URL.  This is used to compute
  // the time elapsed from initiating a prerender until the time the
  // (potentially only partially) prerendered page is shown to the user.
  base::TimeTicks load_start_time_;

  // Process Metrics of the render process associated with the
  // RenderViewHost for this object.
  scoped_ptr<base::ProcessMetrics> process_metrics_;

  // The prerendered TabContentsWrapper; may be null.
  scoped_ptr<TabContentsWrapper> prerender_contents_;

  scoped_ptr<PrerenderRenderViewHostObserver> render_view_host_observer_;

  scoped_ptr<TabContentsDelegateImpl> tab_contents_delegate_;

  // These are -1 before a RenderView is created.
  int child_id_;
  int route_id_;

  // Origin for this prerender.
  Origin origin_;

  // Experiment during which this prerender is performed.
  uint8 experiment_id_;

  // List of all pages the prerendered page has tried to prerender.
  PendingPrerenderList pending_prerender_list_;

  // The process that created the child id.
  int creator_child_id_;

  DISALLOW_COPY_AND_ASSIGN(PrerenderContents);
};

}  // namespace prerender

#endif  // CHROME_BROWSER_PRERENDER_PRERENDER_CONTENTS_H_