- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / prerender / prerender_contents.h
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_CONTENTS_H_
6 #define CHROME_BROWSER_PRERENDER_PRERENDER_CONTENTS_H_
7
8 #include <string>
9 #include <utility>
10 #include <vector>
11
12 #include "base/memory/scoped_ptr.h"
13 #include "base/memory/scoped_vector.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/observer_list.h"
16 #include "base/time/time.h"
17 #include "base/values.h"
18 #include "chrome/browser/prerender/prerender_final_status.h"
19 #include "chrome/browser/prerender/prerender_origin.h"
20 #include "content/public/browser/notification_observer.h"
21 #include "content/public/browser/notification_registrar.h"
22 #include "content/public/browser/web_contents_observer.h"
23 #include "content/public/common/referrer.h"
24 #include "ui/gfx/size.h"
25
26 class Profile;
27
28 namespace base {
29 class ProcessMetrics;
30 }
31
32 namespace content {
33 struct FaviconURL;
34 class RenderViewHost;
35 class SessionStorageNamespace;
36 class WebContents;
37 }
38
39 namespace history {
40 struct HistoryAddPageArgs;
41 }
42
43 namespace prerender {
44
45 class PrerenderHandle;
46 class PrerenderManager;
47
48 class PrerenderContents : public content::NotificationObserver,
49                           public content::WebContentsObserver {
50  public:
51   // PrerenderContents::Create uses the currently registered Factory to create
52   // the PrerenderContents. Factory is intended for testing.
53   class Factory {
54    public:
55     Factory() {}
56     virtual ~Factory() {}
57
58     // Ownership is not transfered through this interface as prerender_manager,
59     // prerender_tracker, and profile are stored as weak pointers.
60     virtual PrerenderContents* CreatePrerenderContents(
61         PrerenderManager* prerender_manager,
62         Profile* profile,
63         const GURL& url,
64         const content::Referrer& referrer,
65         Origin origin,
66         uint8 experiment_id) = 0;
67
68    private:
69     DISALLOW_COPY_AND_ASSIGN(Factory);
70   };
71
72   class Observer {
73    public:
74     // Signals that the prerender has started running.
75     virtual void OnPrerenderStart(PrerenderContents* contents) = 0;
76
77     // Signals that the prerender has had its load event.
78     virtual void OnPrerenderStopLoading(PrerenderContents* contents);
79
80     // Signals that the prerender has stopped running.
81     virtual void OnPrerenderStop(PrerenderContents* contents) = 0;
82
83     // Signals that this prerender has just become a MatchComplete replacement.
84     virtual void OnPrerenderCreatedMatchCompleteReplacement(
85         PrerenderContents* contents, PrerenderContents* replacement);
86
87    protected:
88     Observer();
89     virtual ~Observer() = 0;
90   };
91
92   // A container for extra data on pending prerenders.
93   struct PendingPrerenderInfo {
94    public:
95     PendingPrerenderInfo(
96         base::WeakPtr<PrerenderHandle> weak_prerender_handle,
97         Origin origin,
98         const GURL& url,
99         const content::Referrer& referrer,
100         const gfx::Size& size);
101
102     ~PendingPrerenderInfo();
103
104     base::WeakPtr<PrerenderHandle> weak_prerender_handle;
105     Origin origin;
106     GURL url;
107     content::Referrer referrer;
108     gfx::Size size;
109   };
110
111   // Indicates how this PrerenderContents relates to MatchComplete. This is to
112   // figure out which histograms to use to record the FinalStatus, Match (record
113   // all prerenders and control group prerenders) or MatchComplete (record
114   // running prerenders only in the way they would have been recorded in the
115   // control group).
116   enum MatchCompleteStatus {
117     // A regular prerender which will be recorded both in Match and
118     // MatchComplete.
119     MATCH_COMPLETE_DEFAULT,
120     // A prerender that used to be a regular prerender, but has since been
121     // replaced by a MatchComplete dummy. Therefore, we will record this only
122     // for Match, but not for MatchComplete.
123     MATCH_COMPLETE_REPLACED,
124     // A prerender that is a MatchComplete dummy replacing a regular prerender.
125     // In the control group, our prerender never would have been canceled, so
126     // we record in MatchComplete but not Match.
127     MATCH_COMPLETE_REPLACEMENT,
128     // A prerender that is a MatchComplete dummy, early in the process of being
129     // created. This prerender should not fail. Record for MatchComplete, but
130     // not Match.
131     MATCH_COMPLETE_REPLACEMENT_PENDING,
132   };
133
134   virtual ~PrerenderContents();
135
136   // All observers of a PrerenderContents are removed after the OnPrerenderStop
137   // event is sent, so there is no need to call RemoveObserver() in the normal
138   // use case.
139   void AddObserver(Observer* observer);
140   void RemoveObserver(Observer* observer);
141
142   // For MatchComplete correctness, create a dummy replacement prerender
143   // contents to stand in for this prerender contents that (which we are about
144   // to destroy).
145   PrerenderContents* CreateMatchCompleteReplacement();
146
147   bool Init();
148
149   static Factory* CreateFactory();
150
151   // Start rendering the contents in the prerendered state. If
152   // |is_control_group| is true, this will go through some of the mechanics of
153   // starting a prerender, without actually creating the RenderView.
154   // |creator_child_id| is the id of the child process that caused the prerender
155   // to be created, and is needed so that the prerendered URLs can be sent to it
156   // so render-initiated navigations will swap in the prerendered page. |size|
157   // indicates the rectangular dimensions that the prerendered page should be.
158   // |session_storage_namespace| indicates the namespace that the prerendered
159   // page should be part of.
160   virtual void StartPrerendering(
161       int creator_child_id,
162       const gfx::Size& size,
163       content::SessionStorageNamespace* session_storage_namespace);
164
165   // Verifies that the prerendering is not using too many resources, and kills
166   // it if not.
167   void DestroyWhenUsingTooManyResources();
168
169   content::RenderViewHost* GetRenderViewHostMutable();
170   const content::RenderViewHost* GetRenderViewHost() const;
171
172   PrerenderManager* prerender_manager() { return prerender_manager_; }
173
174   string16 title() const { return title_; }
175   int32 page_id() const { return page_id_; }
176   GURL icon_url() const { return icon_url_; }
177   const GURL& prerender_url() const { return prerender_url_; }
178   const content::Referrer& referrer() const { return referrer_; }
179   bool has_stopped_loading() const { return has_stopped_loading_; }
180   bool has_finished_loading() const { return has_finished_loading_; }
181   bool prerendering_has_started() const { return prerendering_has_started_; }
182   MatchCompleteStatus match_complete_status() const {
183     return match_complete_status_;
184   }
185   void set_match_complete_status(MatchCompleteStatus status) {
186     match_complete_status_ = status;
187   }
188
189   // Sets the parameter to the value of the associated RenderViewHost's child id
190   // and returns a boolean indicating the validity of that id.
191   virtual bool GetChildId(int* child_id) const;
192
193   // Sets the parameter to the value of the associated RenderViewHost's route id
194   // and returns a boolean indicating the validity of that id.
195   virtual bool GetRouteId(int* route_id) const;
196
197   // Set the final status for how the PrerenderContents was used. This
198   // should only be called once, and should be called before the prerender
199   // contents are destroyed.
200   void SetFinalStatus(FinalStatus final_status);
201   FinalStatus final_status() const { return final_status_; }
202
203   Origin origin() const { return origin_; }
204   uint8 experiment_id() const { return experiment_id_; }
205   int child_id() const { return child_id_; }
206
207   base::TimeTicks load_start_time() const { return load_start_time_; }
208
209   // Indicates whether this prerendered page can be used for the provided
210   // |url| and |session_storage_namespace|.
211   bool Matches(
212       const GURL& url,
213       const content::SessionStorageNamespace* session_storage_namespace) const;
214
215   // content::WebContentsObserver implementation.
216   virtual void DidStopLoading(
217       content::RenderViewHost* render_view_host) OVERRIDE;
218   virtual void DidStartProvisionalLoadForFrame(
219       int64 frame_id,
220       int64 parent_frame_id,
221       bool is_main_frame,
222       const GURL& validated_url,
223       bool is_error_page,
224       bool is_iframe_srcdoc,
225       content::RenderViewHost* render_view_host) OVERRIDE;
226   virtual void DidFinishLoad(
227       int64 frame_id,
228       const GURL& validated_url,
229       bool is_main_frame,
230       content::RenderViewHost* render_view_host) OVERRIDE;
231   virtual void DidNavigateMainFrame(
232       const content::LoadCommittedDetails& details,
233       const content::FrameNavigateParams& params) OVERRIDE;
234   virtual void DidGetRedirectForResourceRequest(
235       const content::ResourceRedirectDetails& details) OVERRIDE;
236   virtual void DidUpdateFaviconURL(int32 page_id,
237       const std::vector<content::FaviconURL>& urls) OVERRIDE;
238   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
239
240   virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
241
242   // content::NotificationObserver
243   virtual void Observe(int type,
244                        const content::NotificationSource& source,
245                        const content::NotificationDetails& details) OVERRIDE;
246
247   // Checks that a URL may be prerendered, for one of the many redirections. If
248   // the URL can not be prerendered - for example, it's an ftp URL - |this| will
249   // be destroyed and false is returned. Otherwise, true is returned.
250   virtual bool CheckURL(const GURL& url);
251
252   // Adds an alias URL. If the URL can not be prerendered, |this| will be
253   // destroyed and false is returned.
254   bool AddAliasURL(const GURL& url);
255
256   // The prerender WebContents (may be NULL).
257   content::WebContents* prerender_contents() const {
258     return prerender_contents_.get();
259   }
260
261   content::WebContents* ReleasePrerenderContents();
262
263   // Sets the final status, calls OnDestroy and adds |this| to the
264   // PrerenderManager's pending deletes list.
265   void Destroy(FinalStatus reason);
266
267   // Called by the history tab helper with the information that it woudl have
268   // added to the history service had this web contents not been used for
269   // prerendering.
270   void DidNavigate(const history::HistoryAddPageArgs& add_page_args);
271
272   // Applies all the URL history encountered during prerendering to the
273   // new tab.
274   void CommitHistory(content::WebContents* tab);
275
276   base::Value* GetAsValue() const;
277
278   // Returns whether a pending cross-site navigation is happening.
279   // This could happen with renderer-issued navigations, such as a
280   // MouseEvent being dispatched by a link to a website installed as an app.
281   bool IsCrossSiteNavigationPending() const;
282
283   // Adds a pending prerender to the list. If |weak_prerender_handle| still
284   // exists when this page is made visible, it will be launched.
285   virtual void AddPendingPrerender(
286       scoped_ptr<PendingPrerenderInfo> pending_prerender_info);
287
288   // Reissues any pending prerender requests from the prerendered page.  Also
289   // clears the list of pending requests. Sends notifications.
290   void PrepareForUse();
291
292   content::SessionStorageNamespace* GetSessionStorageNamespace() const;
293
294  protected:
295   PrerenderContents(PrerenderManager* prerender_manager,
296                     Profile* profile,
297                     const GURL& url,
298                     const content::Referrer& referrer,
299                     Origin origin,
300                     uint8 experiment_id);
301
302   // These call out to methods on our Observers, using our observer_list_. Note
303   // that NotifyPrerenderStop() also clears the observer list.
304   void NotifyPrerenderStart();
305   void NotifyPrerenderStopLoading();
306   void NotifyPrerenderStop();
307   void NotifyPrerenderCreatedMatchCompleteReplacement(
308       PrerenderContents* replacement);
309
310   // Called whenever a RenderViewHost is created for prerendering.  Only called
311   // once the RenderViewHost has a RenderView and RenderWidgetHostView.
312   virtual void OnRenderViewHostCreated(
313       content::RenderViewHost* new_render_view_host);
314
315   content::NotificationRegistrar& notification_registrar() {
316     return notification_registrar_;
317   }
318
319   size_t pending_prerender_count() const;
320
321   bool prerendering_has_been_cancelled() const {
322     return prerendering_has_been_cancelled_;
323   }
324
325   virtual content::WebContents* CreateWebContents(
326       content::SessionStorageNamespace* session_storage_namespace);
327
328   bool prerendering_has_started_;
329
330   // Time at which we started to load the URL.  This is used to compute
331   // the time elapsed from initiating a prerender until the time the
332   // (potentially only partially) prerendered page is shown to the user.
333   base::TimeTicks load_start_time_;
334
335  private:
336   class WebContentsDelegateImpl;
337
338   // Needs to be able to call the constructor.
339   friend class PrerenderContentsFactoryImpl;
340
341   // Returns the ProcessMetrics for the render process, if it exists.
342   base::ProcessMetrics* MaybeGetProcessMetrics();
343
344   // Message handlers.
345   void OnCancelPrerenderForPrinting();
346
347   ObserverList<Observer> observer_list_;
348
349   // The prerender manager owning this object.
350   PrerenderManager* prerender_manager_;
351
352   // The URL being prerendered.
353   GURL prerender_url_;
354
355   // The referrer.
356   content::Referrer referrer_;
357
358   // The profile being used
359   Profile* profile_;
360
361   // Information about the title and URL of the page that this class as a
362   // RenderViewHostDelegate has received from the RenderView.
363   // Used to apply to the new RenderViewHost delegate that might eventually
364   // own the contained RenderViewHost when the prerendered page is shown
365   // in a WebContents.
366   string16 title_;
367   int32 page_id_;
368   GURL url_;
369   GURL icon_url_;
370   content::NotificationRegistrar notification_registrar_;
371
372   // A vector of URLs that this prerendered page matches against.
373   // This array can contain more than element as a result of redirects,
374   // such as HTTP redirects or javascript redirects.
375   std::vector<GURL> alias_urls_;
376
377   // The session storage namespace id for use in matching. We must save it
378   // rather than get it from the RenderViewHost since in the control group
379   // we won't have a RenderViewHost.
380   int64 session_storage_namespace_id_;
381
382   bool has_stopped_loading_;
383
384   // True when the main frame has finished loading.
385   bool has_finished_loading_;
386
387   // This must be the same value as the PrerenderTracker has recorded for
388   // |this|, when |this| has a RenderView.
389   FinalStatus final_status_;
390
391   // The MatchComplete status of the prerender, indicating how it relates
392   // to being a MatchComplete dummy (see definition of MatchCompleteStatus
393   // above).
394   MatchCompleteStatus match_complete_status_;
395
396   // Tracks whether or not prerendering has been cancelled by calling Destroy.
397   // Used solely to prevent double deletion.
398   bool prerendering_has_been_cancelled_;
399
400   // Process Metrics of the render process associated with the
401   // RenderViewHost for this object.
402   scoped_ptr<base::ProcessMetrics> process_metrics_;
403
404   // The prerendered WebContents; may be null.
405   scoped_ptr<content::WebContents> prerender_contents_;
406
407   scoped_ptr<WebContentsDelegateImpl> web_contents_delegate_;
408
409   // These are -1 before a RenderView is created.
410   int child_id_;
411   int route_id_;
412
413   // Origin for this prerender.
414   Origin origin_;
415
416   // Experiment during which this prerender is performed.
417   uint8 experiment_id_;
418
419   // Prerenders that the prerendered page has tried to prerender. They remain
420   // pending until this page is displayed.
421   ScopedVector<PendingPrerenderInfo> pending_prerenders_;
422
423   // The process that created the child id.
424   int creator_child_id_;
425
426   // The size of the WebView from the launching page.
427   gfx::Size size_;
428
429   typedef std::vector<history::HistoryAddPageArgs> AddPageVector;
430
431   // Caches pages to be added to the history.
432   AddPageVector add_page_vector_;
433
434   DISALLOW_COPY_AND_ASSIGN(PrerenderContents);
435 };
436
437 }  // namespace prerender
438
439 #endif  // CHROME_BROWSER_PRERENDER_PRERENDER_CONTENTS_H_