Home | History | Annotate | Download | only in prerender
      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