• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_TRACKER_H_
6 #define CHROME_BROWSER_PRERENDER_PRERENDER_TRACKER_H_
7 
8 #include <map>
9 #include <set>
10 #include <utility>
11 #include <vector>
12 
13 #include "base/gtest_prod_util.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/synchronization/lock.h"
16 #include "base/threading/non_thread_safe.h"
17 #include "chrome/browser/prerender/prerender_contents.h"
18 #include "chrome/browser/prerender/prerender_final_status.h"
19 #include "url/gurl.h"
20 
21 namespace prerender {
22 
23 class PrerenderManager;
24 class PrerenderPendingSwapThrottle;
25 class PrerenderResourceThrottle;
26 struct RenderViewInfo;
27 
28 // PrerenderTracker is responsible for keeping track of all prerendering
29 // RenderViews and their statuses.  Its list is guaranteed to be up to date
30 // and can be modified on any thread.
31 class PrerenderTracker : public base::NonThreadSafe,
32                          public PrerenderContents::Observer {
33  public:
34   typedef std::pair<int, int> ChildRouteIdPair;
35 
36   PrerenderTracker();
37   virtual ~PrerenderTracker();
38 
39   // Attempts to set the status of the specified RenderViewHost to
40   // FINAL_STATUS_USED.  Returns true on success.  Returns false if it has
41   // already been cancelled for any reason or is no longer prerendering.
42   // Can only be called only on the UI thread.  This method will not call
43   // PrerenderContents::SetFinalStatus() on the corresponding PrerenderContents.
44   //
45   // If it returns true, all subsequent calls to TryCancel and TryUse for the
46   // RenderView will return false.
47   bool TryUse(int child_id, int route_id);
48 
49   // Attempts to cancel prerendering by the specified RenderView, setting the
50   // FinalStatus to |final_status|.  Returns true if the specified prerender has
51   // been cancelled, either as a result of this call or for any other reason.
52   // If the call results in cancelling a PrerenderContents, a task to destroy
53   // it is also posted to the UI thread.
54   //
55   // When true is returned, it is guaranteed that the RenderView will never
56   // be displayed.  When false is returned, the RenderView has either been
57   // swapped into a tab or has already been destroyed.
58   bool TryCancel(int child_id, int route_id, FinalStatus final_status);
59 
60   // Same as above, but can only called on the IO Thread.  Does not acquire a
61   // lock when the RenderView is not being prerendered.
62   bool TryCancelOnIOThread(int child_id, int route_id,
63                            FinalStatus final_status);
64 
65   // Gets the FinalStatus of the specified prerendered RenderView.  Returns
66   // |true| and sets |final_status| to the status of the RenderView if it
67   // is found, returns false otherwise.
68   bool GetFinalStatus(int child_id, int route_id,
69                       FinalStatus* final_status) const;
70 
71   // Returns whether or not a RenderView is prerendering.  Can only be called on
72   // the IO thread.  Does not acquire a lock, so may claim a RenderView that has
73   // been displayed or destroyed is still prerendering.
74   bool IsPrerenderingOnIOThread(int child_id, int route_id) const;
75 
76   // Returns whether or not a RenderView and URL are regarding a pending
77   // prerender swap. Can only be called on the IO thread. Does not acquire a
78   // lock.
79   bool IsPendingSwapRequestOnIOThread(int child_id, int route_id,
80                                       const GURL& url) const;
81 
82   // Called when a PrerenderResourceThrottle defers a request. Cancel
83   // or Resume will be called on |throttle| when the prerender is
84   // canceled or used, respectively.
85   void AddResourceThrottleOnIOThread(
86       int child_id, int route_id,
87       const base::WeakPtr<PrerenderResourceThrottle>& throttle);
88 
89   // Called when a PrerenderResourceThrottle defers a request. Cancel
90   // or Resume will be called on |throttle| when the prerender is
91   // canceled or used, respectively.
92   void AddPendingSwapThrottleOnIOThread(
93       int child_id, int route_id, const GURL& url,
94       const base::WeakPtr<PrerenderPendingSwapThrottle>& throttle);
95 
96   // Called to add throttles for a pending prerender swap.
97   void AddPrerenderPendingSwap(const ChildRouteIdPair& child_route_id_pair,
98                                const GURL& url);
99 
100   // Called to remove the throttles for a pending prerender swap.
101   void RemovePrerenderPendingSwap(const ChildRouteIdPair& child_route_id_pair,
102                                   bool swap_successful);
103 
104  private:
105   friend class PrerenderContents;
106   FRIEND_TEST_ALL_PREFIXES(PrerenderTrackerTest, PrerenderTrackerNull);
107   FRIEND_TEST_ALL_PREFIXES(PrerenderTrackerTest, PrerenderTrackerUsed);
108   FRIEND_TEST_ALL_PREFIXES(PrerenderTrackerTest, PrerenderTrackerCancelled);
109   FRIEND_TEST_ALL_PREFIXES(PrerenderTrackerTest, PrerenderTrackerCancelledOnIO);
110   FRIEND_TEST_ALL_PREFIXES(PrerenderTrackerTest, PrerenderTrackerCancelledFast);
111   FRIEND_TEST_ALL_PREFIXES(PrerenderTrackerTest, PrerenderTrackerMultiple);
112 
113   // Map of child/route id pairs to final statuses.
114   typedef std::map<ChildRouteIdPair, RenderViewInfo> FinalStatusMap;
115   // List of throttled requests.
116   typedef std::vector<base::WeakPtr<PrerenderResourceThrottle> >
117       ResourceThrottleList;
118   // Set of throttled requests.
119   typedef std::map<ChildRouteIdPair, ResourceThrottleList> ResourceThrottleMap;
120   struct PendingSwapThrottleData {
121     explicit PendingSwapThrottleData(const GURL& swap_url);
122     ~PendingSwapThrottleData();
123     GURL url;
124     std::vector<base::WeakPtr<PrerenderPendingSwapThrottle> > throttles;
125   };
126   // Set of throttles for pending swaps.
127   typedef std::map<ChildRouteIdPair, PendingSwapThrottleData>
128       PendingSwapThrottleMap;
129 
130   // From PrerenderContents::Observer:
131   virtual void OnPrerenderStart(PrerenderContents* prerender_contents) OVERRIDE;
132   virtual void OnPrerenderStop(PrerenderContents* prerender_contents) OVERRIDE;
133 
134   // Attempts to set the FinalStatus of the specified RenderView to
135   // |desired_final_status|.  If non-NULL, |actual_final_status| is set to the
136   // FinalStatus of the RenderView.
137   //
138   // If the FinalStatus of the RenderView is successfully set, returns true and
139   // sets |actual_final_status| to |desired_final_status|.
140   //
141   // If the FinalStatus of the RenderView was already set, returns false and
142   // sets |actual_final_status| to the actual FinalStatus of the RenderView.
143   //
144   // If the RenderView is not a prerendering RenderView, returns false and sets
145   // |actual_final_status| to FINAL_STATUS_MAX.
146   bool SetFinalStatus(int child_id, int route_id,
147                       FinalStatus desired_final_status,
148                       FinalStatus* actual_final_status);
149 
150   // Add/remove the specified pair to |possibly_prerendering_io_thread_set_| on
151   // the IO Thread.
152   void AddPrerenderOnIOThread(const ChildRouteIdPair& child_route_id_pair);
153   void RemovePrerenderOnIOThread(const ChildRouteIdPair& child_route_id_pair,
154                                  FinalStatus final_status);
155 
156   // Add/remove prerenders pending swap on the IO Thread.
157   void AddPrerenderPendingSwapOnIOThread(
158       const ChildRouteIdPair& child_route_id_pair, const GURL& url);
159   void RemovePrerenderPendingSwapOnIOThread(
160       const ChildRouteIdPair& child_route_id_pair,
161       bool swap_successful);
162 
163   // Tasks posted to the IO Thread to call the above functions.
164   static void AddPrerenderOnIOThreadTask(
165       const ChildRouteIdPair& child_route_id_pair);
166   static void RemovePrerenderOnIOThreadTask(
167       const ChildRouteIdPair& child_route_id_pair,
168       FinalStatus final_status);
169   static void AddPrerenderPendingSwapOnIOThreadTask(
170       const ChildRouteIdPair& child_route_id_pair, const GURL& url);
171   static void RemovePrerenderPendingSwapOnIOThreadTask(
172       const ChildRouteIdPair& child_route_id_pair,
173       bool swap_successful);
174 
175   static PrerenderTracker* GetDefault();
176 
177   // |final_status_map_lock_| protects access to |final_status_map_|.
178   mutable base::Lock final_status_map_lock_;
179   // Map containing child/route id pairs and their final statuses.  Must only be
180   // accessed while the lock is held.  Values are always accurate and up to
181   // date.
182   FinalStatusMap final_status_map_;
183 
184   // Resources that are throttled, pending a prerender use.  The keys are a
185   // superset of child/route id pairs that are prerendering.  Can only access on
186   // the IO thread.  May contain entries that have since been displayed.  Used
187   // to prevent locking when not needed.
188   ResourceThrottleMap resource_throttle_io_thread_map_;
189 
190   // Map of pending prerender swaps and their associated throttles,
191   // maintained on the IO thread.
192   PendingSwapThrottleMap pending_swap_throttle_map_;
193 
194   DISALLOW_COPY_AND_ASSIGN(PrerenderTracker);
195 };
196 
197 }  // namespace prerender
198 
199 #endif  // CHROME_BROWSER_PRERENDER_PRERENDER_TRACKER_H_
200