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_MANAGER_H_
      6 #define CHROME_BROWSER_PRERENDER_PRERENDER_MANAGER_H_
      7 
      8 #include <list>
      9 #include <map>
     10 #include <string>
     11 #include <utility>
     12 #include <vector>
     13 
     14 #include "base/containers/hash_tables.h"
     15 #include "base/gtest_prod_util.h"
     16 #include "base/memory/scoped_ptr.h"
     17 #include "base/memory/scoped_vector.h"
     18 #include "base/memory/weak_ptr.h"
     19 #include "base/threading/non_thread_safe.h"
     20 #include "base/time/time.h"
     21 #include "base/timer/timer.h"
     22 #include "chrome/browser/history/history_service.h"
     23 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
     24 #include "chrome/browser/predictors/logged_in_predictor_table.h"
     25 #include "chrome/browser/prerender/prerender_config.h"
     26 #include "chrome/browser/prerender/prerender_contents.h"
     27 #include "chrome/browser/prerender/prerender_events.h"
     28 #include "chrome/browser/prerender/prerender_final_status.h"
     29 #include "chrome/browser/prerender/prerender_origin.h"
     30 #include "chrome/browser/prerender/prerender_tracker.h"
     31 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
     32 #include "content/public/browser/notification_observer.h"
     33 #include "content/public/browser/notification_registrar.h"
     34 #include "content/public/browser/session_storage_namespace.h"
     35 #include "content/public/browser/web_contents_observer.h"
     36 #include "net/cookies/canonical_cookie.h"
     37 #include "net/cookies/cookie_monster.h"
     38 #include "url/gurl.h"
     39 
     40 class Profile;
     41 class InstantSearchPrerendererTest;
     42 struct ChromeCookieDetails;
     43 
     44 namespace base {
     45 class DictionaryValue;
     46 }
     47 
     48 namespace chrome {
     49 struct NavigateParams;
     50 }
     51 
     52 namespace content {
     53 class WebContents;
     54 }
     55 
     56 namespace gfx {
     57 class Size;
     58 }
     59 
     60 namespace net {
     61 class URLRequestContextGetter;
     62 }
     63 
     64 #if defined(COMPILER_GCC)
     65 
     66 namespace BASE_HASH_NAMESPACE {
     67 template <>
     68 struct hash<content::WebContents*> {
     69   std::size_t operator()(content::WebContents* value) const {
     70     return reinterpret_cast<std::size_t>(value);
     71   }
     72 };
     73 
     74 }  // namespace BASE_HASH_NAMESPACE
     75 
     76 #endif
     77 
     78 namespace prerender {
     79 
     80 class PrerenderCondition;
     81 class PrerenderHandle;
     82 class PrerenderHistograms;
     83 class PrerenderHistory;
     84 class PrerenderLocalPredictor;
     85 
     86 // PrerenderManager is responsible for initiating and keeping prerendered
     87 // views of web pages. All methods must be called on the UI thread unless
     88 // indicated otherwise.
     89 class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>,
     90                          public base::NonThreadSafe,
     91                          public content::NotificationObserver,
     92                          public BrowserContextKeyedService,
     93                          public MediaCaptureDevicesDispatcher::Observer {
     94  public:
     95   // NOTE: New values need to be appended, since they are used in histograms.
     96   enum PrerenderManagerMode {
     97     PRERENDER_MODE_DISABLED = 0,
     98     PRERENDER_MODE_ENABLED = 1,
     99     PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP = 2,
    100     PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP = 3,
    101     // Obsolete: PRERENDER_MODE_EXPERIMENT_5MIN_TTL_GROUP = 4,
    102     PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP = 5,
    103     PRERENDER_MODE_EXPERIMENT_MULTI_PRERENDER_GROUP = 6,
    104     PRERENDER_MODE_EXPERIMENT_15MIN_TTL_GROUP = 7,
    105     PRERENDER_MODE_MAX
    106   };
    107 
    108   // One or more of these flags must be passed to ClearData() to specify just
    109   // what data to clear.  See function declaration for more information.
    110   enum ClearFlags {
    111     CLEAR_PRERENDER_CONTENTS = 0x1 << 0,
    112     CLEAR_PRERENDER_HISTORY = 0x1 << 1,
    113     CLEAR_MAX = 0x1 << 2
    114   };
    115 
    116   typedef predictors::LoggedInPredictorTable::LoggedInStateMap LoggedInStateMap;
    117 
    118   // ID indicating that no experiment is active.
    119   static const uint8 kNoExperiment = 0;
    120 
    121   // Owned by a Profile object for the lifetime of the profile.
    122   PrerenderManager(Profile* profile, PrerenderTracker* prerender_tracker);
    123 
    124   virtual ~PrerenderManager();
    125 
    126   // From BrowserContextKeyedService:
    127   virtual void Shutdown() OVERRIDE;
    128 
    129   // Entry points for adding prerenders.
    130 
    131   // Adds a prerender for |url| if valid. |process_id| and |route_id| identify
    132   // the RenderView that the prerender request came from. If |size| is empty, a
    133   // default from the PrerenderConfig is used. Returns a caller-owned
    134   // PrerenderHandle* if the URL was added, NULL if it was not. If the launching
    135   // RenderView is itself prerendering, the prerender is added as a pending
    136   // prerender.
    137   PrerenderHandle* AddPrerenderFromLinkRelPrerender(
    138       int process_id,
    139       int route_id,
    140       const GURL& url,
    141       const content::Referrer& referrer,
    142       const gfx::Size& size);
    143 
    144   // Adds a prerender for |url| if valid. As the prerender request is coming
    145   // from a source without a RenderViewHost (i.e., the omnibox) we don't have a
    146   // child or route id, or a referrer. This method uses sensible values for
    147   // those. The |session_storage_namespace| matches the namespace of the active
    148   // tab at the time the prerender is generated from the omnibox. Returns a
    149   // caller-owned PrerenderHandle*, or NULL.
    150   PrerenderHandle* AddPrerenderFromOmnibox(
    151       const GURL& url,
    152       content::SessionStorageNamespace* session_storage_namespace,
    153       const gfx::Size& size);
    154 
    155   PrerenderHandle* AddPrerenderFromLocalPredictor(
    156       const GURL& url,
    157       content::SessionStorageNamespace* session_storage_namespace,
    158       const gfx::Size& size);
    159 
    160   PrerenderHandle* AddPrerenderFromExternalRequest(
    161       const GURL& url,
    162       const content::Referrer& referrer,
    163       content::SessionStorageNamespace* session_storage_namespace,
    164       const gfx::Size& size);
    165 
    166   // Adds a prerender for Instant Search |url| if valid. The
    167   // |session_storage_namespace| matches the namespace of the active tab at the
    168   // time the prerender is generated. Returns a caller-owned PrerenderHandle* or
    169   // NULL.
    170   PrerenderHandle* AddPrerenderForInstant(
    171       const GURL& url,
    172       content::SessionStorageNamespace* session_storage_namespace,
    173       const gfx::Size& size);
    174 
    175   // If |process_id| and |view_id| refer to a running prerender, destroy
    176   // it with |final_status|.
    177   virtual void DestroyPrerenderForRenderView(int process_id,
    178                                              int view_id,
    179                                              FinalStatus final_status);
    180 
    181   // Cancels all active prerenders.
    182   void CancelAllPrerenders();
    183 
    184   // If |url| matches a valid prerendered page and |params| are compatible, try
    185   // to swap it and merge browsing histories. Returns |true| and updates
    186   // |params->target_contents| if a prerendered page is swapped in, |false|
    187   // otherwise.
    188   bool MaybeUsePrerenderedPage(const GURL& url,
    189                                chrome::NavigateParams* params);
    190 
    191   // Moves a PrerenderContents to the pending delete list from the list of
    192   // active prerenders when prerendering should be cancelled.
    193   virtual void MoveEntryToPendingDelete(PrerenderContents* entry,
    194                                         FinalStatus final_status);
    195 
    196   // Records the perceived page load time for a page - effectively the time from
    197   // when the user navigates to a page to when it finishes loading. The actual
    198   // load may have started prior to navigation due to prerender hints.
    199   // This must be called on the UI thread.
    200   // |fraction_plt_elapsed_at_swap_in| must either be in [0.0, 1.0], or a value
    201   // outside that range indicating that it doesn't apply.
    202   static void RecordPerceivedPageLoadTime(
    203       base::TimeDelta perceived_page_load_time,
    204       double fraction_plt_elapsed_at_swap_in,
    205       content::WebContents* web_contents,
    206       const GURL& url);
    207 
    208   // Records the percentage of pixels of the final page in place at swap-in.
    209   void RecordFractionPixelsFinalAtSwapin(
    210       content::WebContents* web_contents,
    211       double fraction);
    212 
    213   // Set whether prerendering is currently enabled for this manager.
    214   // Must be called on the UI thread.
    215   // If |enabled| is false, existing prerendered pages will still persist until
    216   // they time out, but new ones will not be generated.
    217   void set_enabled(bool enabled);
    218 
    219   static PrerenderManagerMode GetMode();
    220   static void SetMode(PrerenderManagerMode mode);
    221   static const char* GetModeString();
    222   static bool IsPrerenderingPossible();
    223   static bool ActuallyPrerendering();
    224   static bool IsControlGroup(uint8 experiment_id);
    225   static bool IsNoUseGroup();
    226 
    227   // Query the list of current prerender pages to see if the given web contents
    228   // is prerendering a page. The optional parameter |origin| is an output
    229   // parameter which, if a prerender is found, is set to the Origin of the
    230   // prerender |web_contents|.
    231   bool IsWebContentsPrerendering(const content::WebContents* web_contents,
    232                                  Origin* origin) const;
    233 
    234   // Whether the PrerenderManager has an active prerender with the given url and
    235   // SessionStorageNamespace associated with the given WebContens.
    236   bool HasPrerenderedUrl(GURL url, content::WebContents* web_contents) const;
    237 
    238   // Returns the PrerenderContents object for the given web_contents if it's
    239   // used for an active prerender page, otherwise returns NULL.
    240   PrerenderContents* GetPrerenderContents(
    241       const content::WebContents* web_contents) const;
    242 
    243   // Returns a list of all WebContents being prerendered.
    244   const std::vector<content::WebContents*> GetAllPrerenderingContents() const;
    245 
    246   // Maintaining and querying the set of WebContents belonging to this
    247   // PrerenderManager that are currently showing prerendered pages.
    248   void MarkWebContentsAsPrerendered(content::WebContents* web_contents,
    249                                     Origin origin);
    250   void MarkWebContentsAsWouldBePrerendered(content::WebContents* web_contents,
    251                                            Origin origin);
    252   void MarkWebContentsAsNotPrerendered(content::WebContents* web_contents);
    253 
    254   // Returns true if |web_contents| was originally a prerender that has since
    255   // been swapped in. The optional parameter |origin| is an output parameter
    256   // which, if a prerender is found, is set to the Origin of the prerender of
    257   // |web_contents|.
    258   bool IsWebContentsPrerendered(content::WebContents* web_contents,
    259                                 Origin* origin) const;
    260   bool WouldWebContentsBePrerendered(content::WebContents* web_contents,
    261                                      Origin* origin) const;
    262 
    263   // Checks whether |url| has been recently navigated to.
    264   bool HasRecentlyBeenNavigatedTo(Origin origin, const GURL& url);
    265 
    266   // Returns true iff the method given is valid for prerendering.
    267   static bool IsValidHttpMethod(const std::string& method);
    268 
    269   // Returns true iff the scheme of the URL given is valid for prerendering.
    270   static bool DoesURLHaveValidScheme(const GURL& url);
    271 
    272   // Returns true iff the scheme of the subresource URL given is valid for
    273   // prerendering.
    274   static bool DoesSubresourceURLHaveValidScheme(const GURL& url);
    275 
    276   // Returns a Value object containing the active pages being prerendered, and
    277   // a history of pages which were prerendered. The caller is responsible for
    278   // deleting the return value.
    279   base::DictionaryValue* GetAsValue() const;
    280 
    281   // Clears the data indicated by which bits of clear_flags are set.
    282   //
    283   // If the CLEAR_PRERENDER_CONTENTS bit is set, all active prerenders are
    284   // cancelled and then deleted, and any WebContents queued for destruction are
    285   // destroyed as well.
    286   //
    287   // If the CLEAR_PRERENDER_HISTORY bit is set, the prerender history is
    288   // cleared, including any entries newly created by destroying them in
    289   // response to the CLEAR_PRERENDER_CONTENTS flag.
    290   //
    291   // Intended to be used when clearing the cache or history.
    292   void ClearData(int clear_flags);
    293 
    294   // Record a final status of a prerendered page in a histogram.
    295   // This variation allows specifying whether prerendering had been started
    296   // (necessary to flag MatchComplete dummies).
    297   void RecordFinalStatusWithMatchCompleteStatus(
    298       Origin origin,
    299       uint8 experiment_id,
    300       PrerenderContents::MatchCompleteStatus mc_status,
    301       FinalStatus final_status) const;
    302 
    303   // Record a cookie status histogram (see prerender_histograms.h).
    304   void RecordCookieStatus(Origin origin,
    305                           uint8 experiment_id,
    306                           int cookie_status) const;
    307 
    308   // content::NotificationObserver
    309   virtual void Observe(int type,
    310                        const content::NotificationSource& source,
    311                        const content::NotificationDetails& details) OVERRIDE;
    312 
    313   // MediaCaptureDevicesDispatcher::Observer
    314   virtual void OnCreatingAudioStream(int render_process_id,
    315                                      int render_view_id) OVERRIDE;
    316 
    317   const Config& config() const { return config_; }
    318   Config& mutable_config() { return config_; }
    319 
    320   PrerenderTracker* prerender_tracker() { return prerender_tracker_; }
    321 
    322   // Adds a condition. This is owned by the PrerenderManager.
    323   void AddCondition(const PrerenderCondition* condition);
    324 
    325   // Records that some visible tab navigated (or was redirected) to the
    326   // provided URL.
    327   void RecordNavigation(const GURL& url);
    328 
    329   // Updates the LoggedInPredictor state to reflect that a login has likely
    330   // on the URL provided.
    331   void RecordLikelyLoginOnURL(const GURL& url);
    332 
    333   // Checks if the LoggedInPredictor shows that the user is likely logged on
    334   // to the site for the URL provided.
    335   void CheckIfLikelyLoggedInOnURL(const GURL& url,
    336                                   bool* lookup_result,
    337                                   bool* database_was_present,
    338                                   const base::Closure& result_cb);
    339 
    340   void OnHistoryServiceDidQueryURL(Origin origin,
    341                                    uint8 experiment_id,
    342                                    CancelableRequestProvider::Handle handle,
    343                                    bool success,
    344                                    const history::URLRow* url_row,
    345                                    history::VisitVector* visits);
    346 
    347   Profile* profile() const { return profile_; }
    348 
    349   // Classes which will be tested in prerender unit browser tests should use
    350   // these methods to get times for comparison, so that the test framework can
    351   // mock advancing/retarding time.
    352   virtual base::Time GetCurrentTime() const;
    353   virtual base::TimeTicks GetCurrentTimeTicks() const;
    354 
    355   scoped_refptr<predictors::LoggedInPredictorTable>
    356   logged_in_predictor_table() {
    357     return logged_in_predictor_table_;
    358   }
    359 
    360   PrerenderLocalPredictor* local_predictor() {
    361     return local_predictor_.get();
    362   }
    363 
    364   // Notification that a cookie event happened on a render frame. Will record a
    365   // cookie event for a given render frame, if it is being prerendered.
    366   // If cookies were sent, all cookies must be supplied in |cookie_list|.
    367   static void RecordCookieEvent(int process_id,
    368                                 int render_view_id,
    369                                 const GURL& url,
    370                                 const GURL& frame_url,
    371                                 PrerenderContents::CookieEvent event,
    372                                 const net::CookieList* cookie_list);
    373 
    374  protected:
    375   class PendingSwap;
    376   class PrerenderData : public base::SupportsWeakPtr<PrerenderData> {
    377    public:
    378     struct OrderByExpiryTime;
    379 
    380     PrerenderData(PrerenderManager* manager,
    381                   PrerenderContents* contents,
    382                   base::TimeTicks expiry_time);
    383 
    384     ~PrerenderData();
    385 
    386     // Turn this PrerenderData into a Match Complete replacement for itself,
    387     // placing the current prerender contents into |to_delete_prerenders_|.
    388     void MakeIntoMatchCompleteReplacement();
    389 
    390     // A new PrerenderHandle has been created for this PrerenderData.
    391     void OnHandleCreated(PrerenderHandle* prerender_handle);
    392 
    393     // The launcher associated with a handle is navigating away from the context
    394     // that launched this prerender. If the prerender is active, it may stay
    395     // alive briefly though, in case we we going through a redirect chain that
    396     // will eventually land at it.
    397     void OnHandleNavigatedAway(PrerenderHandle* prerender_handle);
    398 
    399     // The launcher associated with a handle has taken explicit action to cancel
    400     // this prerender. We may well destroy the prerender in this case if no
    401     // other handles continue to track it.
    402     void OnHandleCanceled(PrerenderHandle* prerender_handle);
    403 
    404     PrerenderContents* contents() { return contents_.get(); }
    405 
    406     PrerenderContents* ReleaseContents();
    407 
    408     int handle_count() const { return handle_count_; }
    409 
    410     base::TimeTicks expiry_time() const { return expiry_time_; }
    411     void set_expiry_time(base::TimeTicks expiry_time) {
    412       expiry_time_ = expiry_time;
    413     }
    414 
    415     void ClearPendingSwap();
    416 
    417     PendingSwap* pending_swap() { return pending_swap_.get(); }
    418     void set_pending_swap(PendingSwap* pending_swap) {
    419       pending_swap_.reset(pending_swap);
    420     }
    421 
    422    private:
    423     PrerenderManager* manager_;
    424     scoped_ptr<PrerenderContents> contents_;
    425 
    426     // The number of distinct PrerenderHandles created for |this|, including
    427     // ones that have called PrerenderData::OnHandleNavigatedAway(), but not
    428     // counting the ones that have called PrerenderData::OnHandleCanceled(). For
    429     // pending prerenders, this will always be 1, since the PrerenderManager
    430     // only merges handles of running prerenders.
    431     int handle_count_;
    432 
    433     // After this time, this prerender is no longer fresh, and should be
    434     // removed.
    435     base::TimeTicks expiry_time_;
    436 
    437     // If a session storage namespace merge is in progress for this object,
    438     // we need to keep track of various state associated with it.
    439     scoped_ptr<PendingSwap> pending_swap_;
    440 
    441     DISALLOW_COPY_AND_ASSIGN(PrerenderData);
    442   };
    443 
    444   // When a swap can't happen immediately, due to a sesison storage namespace
    445   // merge, there will be a pending swap object while the merge is in
    446   // progress. It retains all the data needed to do the merge, maintains
    447   // throttles for the navigation in the target WebContents that needs to be
    448   // delayed, and handles all conditions which would cancel a pending swap.
    449   class PendingSwap : public content::WebContentsObserver {
    450    public:
    451     PendingSwap(PrerenderManager* manager,
    452                 content::WebContents* target_contents,
    453                 PrerenderData* prerender_data,
    454                 const GURL& url,
    455                 bool should_replace_current_entry);
    456     virtual ~PendingSwap();
    457 
    458     void set_swap_successful(bool swap_successful) {
    459       swap_successful_ = swap_successful;
    460     }
    461 
    462     void BeginSwap();
    463 
    464     // content::WebContentsObserver implementation.
    465     virtual void ProvisionalChangeToMainFrameUrl(
    466         const GURL& url,
    467         content::RenderViewHost* render_view_host) OVERRIDE;
    468     virtual void DidCommitProvisionalLoadForFrame(
    469         int64 frame_id,
    470         const base::string16& frame_unique_name,
    471         bool is_main_frame,
    472         const GURL& validated_url,
    473         content::PageTransition transition_type,
    474         content::RenderViewHost* render_view_host) OVERRIDE;
    475     virtual void RenderViewCreated(
    476         content::RenderViewHost* render_view_host) OVERRIDE;
    477     virtual void DidFailProvisionalLoad(
    478         int64 frame_id,
    479         const base::string16& frame_unique_name,
    480         bool is_main_frame,
    481         const GURL& validated_url,
    482         int error_code,
    483         const base::string16& error_description,
    484         content::RenderViewHost* render_view_host) OVERRIDE;
    485     virtual void WebContentsDestroyed(content::WebContents* web_contents)
    486         OVERRIDE;
    487 
    488    private:
    489     void RecordEvent(PrerenderEvent event) const;
    490 
    491     void OnMergeCompleted(content::SessionStorageNamespace::MergeResult result);
    492     void OnMergeTimeout();
    493 
    494     // Prerender parameters.
    495     PrerenderManager* manager_;
    496     content::WebContents* target_contents_;
    497     PrerenderData* prerender_data_;
    498     GURL url_;
    499     bool should_replace_current_entry_;
    500 
    501     base::TimeTicks start_time_;
    502     std::vector<PrerenderTracker::ChildRouteIdPair> rvh_ids_;
    503     base::OneShotTimer<PendingSwap> merge_timeout_;
    504     bool swap_successful_;
    505 
    506     base::WeakPtrFactory<PendingSwap> weak_factory_;
    507   };
    508 
    509   void SetPrerenderContentsFactory(
    510       PrerenderContents::Factory* prerender_contents_factory);
    511 
    512   // Adds prerenders from the pending Prerenders, called by
    513   // PrerenderContents::StartPendingPrerenders.
    514   void StartPendingPrerenders(
    515       int process_id,
    516       ScopedVector<PrerenderContents::PendingPrerenderInfo>* pending_prerenders,
    517       content::SessionStorageNamespace* session_storage_namespace);
    518 
    519   // Called by a PrerenderData to signal that the launcher has navigated away
    520   // from the context that launched the prerender. A user may have clicked
    521   // a link in a page containing a <link rel=prerender> element, or the user
    522   // might have committed an omnibox navigation. This is used to possibly
    523   // shorten the TTL of the prerendered page.
    524   void SourceNavigatedAway(PrerenderData* prerender_data);
    525 
    526  private:
    527   friend class ::InstantSearchPrerendererTest;
    528   friend class PrerenderBrowserTest;
    529   friend class PrerenderContents;
    530   friend class PrerenderHandle;
    531   friend class UnitTestPrerenderManager;
    532 
    533   class OnCloseWebContentsDeleter;
    534   struct NavigationRecord;
    535 
    536   // For each WebContents that is swapped in, we store a
    537   // PrerenderedWebContentsData so that we can track the origin of the
    538   // prerender.
    539   struct PrerenderedWebContentsData {
    540     explicit PrerenderedWebContentsData(Origin origin);
    541 
    542     Origin origin;
    543   };
    544 
    545   // In the control group experimental group for each WebContents "not swapped
    546   // in" we create a WouldBePrerenderedWebContentsData to the origin of the
    547   // "prerender" we did not launch. We also track a state machine to ensure
    548   // the histogram reporting tracks what histograms would have done.
    549   struct WouldBePrerenderedWebContentsData {
    550     // When the WebContents gets a provisional load, we'd like to remove the
    551     // WebContents from  the map since the new navigation would not have swapped
    552     // in a prerender. But the first provisional load after the control
    553     // prerender is not "swapped in" is actually to the prerendered location! So
    554     // we don't remove the item from the map on the first provisional load, but
    555     // we do for subsequent loads.
    556     enum State {
    557       WAITING_FOR_PROVISIONAL_LOAD,
    558       SEEN_PROVISIONAL_LOAD,
    559     };
    560 
    561     explicit WouldBePrerenderedWebContentsData(Origin origin);
    562 
    563     Origin origin;
    564     State state;
    565   };
    566 
    567   // Time interval before a new prerender is allowed.
    568   static const int kMinTimeBetweenPrerendersMs = 500;
    569 
    570   // Time window for which we record old navigations, in milliseconds.
    571   static const int kNavigationRecordWindowMs = 5000;
    572 
    573   void OnCancelPrerenderHandle(PrerenderData* prerender_data);
    574 
    575   // Adds a prerender for |url| from |referrer| initiated from the process
    576   // |child_id|. The |origin| specifies how the prerender was added. If |size|
    577   // is empty, then PrerenderContents::StartPrerendering will instead use a
    578   // default from PrerenderConfig. Returns a PrerenderHandle*, owned by the
    579   // caller, or NULL.
    580   PrerenderHandle* AddPrerender(
    581       Origin origin,
    582       int child_id,
    583       const GURL& url,
    584       const content::Referrer& referrer,
    585       const gfx::Size& size,
    586       content::SessionStorageNamespace* session_storage_namespace);
    587 
    588   void StartSchedulingPeriodicCleanups();
    589   void StopSchedulingPeriodicCleanups();
    590 
    591   void EvictOldestPrerendersIfNecessary();
    592 
    593   // Deletes stale and cancelled prerendered PrerenderContents, as well as
    594   // WebContents that have been replaced by prerendered WebContents.
    595   // Also identifies and kills PrerenderContents that use too much
    596   // resources.
    597   void PeriodicCleanup();
    598 
    599   // Posts a task to call PeriodicCleanup.  Results in quicker destruction of
    600   // objects.  If |this| is deleted before the task is run, the task will
    601   // automatically be cancelled.
    602   void PostCleanupTask();
    603 
    604   base::TimeTicks GetExpiryTimeForNewPrerender(Origin origin) const;
    605   base::TimeTicks GetExpiryTimeForNavigatedAwayPrerender() const;
    606 
    607   void DeleteOldEntries();
    608   virtual PrerenderContents* CreatePrerenderContents(
    609       const GURL& url,
    610       const content::Referrer& referrer,
    611       Origin origin,
    612       uint8 experiment_id);
    613 
    614   // Insures the |active_prerenders_| are sorted by increasing expiry time. Call
    615   // after every mutation of active_prerenders_ that can possibly make it
    616   // unsorted (e.g. an insert, or changing an expiry time).
    617   void SortActivePrerenders();
    618 
    619   // Finds the active PrerenderData object for a running prerender matching
    620   // |url| and |session_storage_namespace|.
    621   PrerenderData* FindPrerenderData(
    622       const GURL& url,
    623       const content::SessionStorageNamespace* session_storage_namespace);
    624 
    625   // If |child_id| and |route_id| correspond to a RenderView that is an active
    626   // prerender, returns the PrerenderData object for that prerender. Otherwise,
    627   // returns NULL.
    628   PrerenderData* FindPrerenderDataForChildAndRoute(int child_id, int route_id);
    629 
    630   // Given the |prerender_contents|, find the iterator in active_prerenders_
    631   // correponding to the given prerender.
    632   ScopedVector<PrerenderData>::iterator
    633       FindIteratorForPrerenderContents(PrerenderContents* prerender_contents);
    634 
    635   bool DoesRateLimitAllowPrerender(Origin origin) const;
    636 
    637   // Deletes old WebContents that have been replaced by prerendered ones.  This
    638   // is needed because they're replaced in a callback from the old WebContents,
    639   // so cannot immediately be deleted.
    640   void DeleteOldWebContents();
    641 
    642   // Cleans up old NavigationRecord's.
    643   void CleanUpOldNavigations();
    644 
    645   // Arrange for the given WebContents to be deleted asap. If deleter is not
    646   // NULL, deletes that as well.
    647   void ScheduleDeleteOldWebContents(content::WebContents* tab,
    648                                     OnCloseWebContentsDeleter* deleter);
    649 
    650   // Adds to the history list.
    651   void AddToHistory(PrerenderContents* contents);
    652 
    653   // Returns a new Value representing the pages currently being prerendered. The
    654   // caller is responsible for delete'ing the return value.
    655   base::Value* GetActivePrerendersAsValue() const;
    656 
    657   // Destroys all pending prerenders using FinalStatus.  Also deletes them as
    658   // well as any swapped out WebContents queued for destruction.
    659   // Used both on destruction, and when clearing the browsing history.
    660   void DestroyAllContents(FinalStatus final_status);
    661 
    662   // Helper function to destroy a PrerenderContents with the specified
    663   // final_status, while at the same time recording that for the MatchComplete
    664   // case, that this prerender would have been used.
    665   void DestroyAndMarkMatchCompleteAsUsed(PrerenderContents* prerender_contents,
    666                                          FinalStatus final_status);
    667 
    668   // Record a final status of a prerendered page in a histogram.
    669   // This is a helper function which will ultimately call
    670   // RecordFinalStatusWthMatchCompleteStatus, using MATCH_COMPLETE_DEFAULT.
    671   void RecordFinalStatus(Origin origin,
    672                          uint8 experiment_id,
    673                          FinalStatus final_status) const;
    674 
    675   // Returns whether prerendering is currently enabled for this manager.
    676   // Must be called on the UI thread.
    677   bool IsEnabled() const;
    678 
    679   void CookieChanged(ChromeCookieDetails* details);
    680   void CookieChangedAnyCookiesLeftLookupResult(const std::string& domain_key,
    681                                                bool cookies_exist);
    682   void LoggedInPredictorDataReceived(scoped_ptr<LoggedInStateMap> new_map);
    683 
    684   void RecordEvent(PrerenderContents* contents, PrerenderEvent event) const;
    685 
    686   // Swaps a prerender |prerender_data| for |url| into the tab, replacing
    687   // |web_contents|.  Returns the new WebContents that was swapped in, or NULL
    688   // if a swap-in was not possible.  If |should_replace_current_entry| is true,
    689   // the current history entry in |web_contents| is replaced.
    690   content::WebContents* SwapInternal(const GURL& url,
    691                                      content::WebContents* web_contents,
    692                                      PrerenderData* prerender_data,
    693                                      bool should_replace_current_entry);
    694 
    695   // The configuration.
    696   Config config_;
    697 
    698   // Specifies whether prerendering is currently enabled for this
    699   // manager. The value can change dynamically during the lifetime
    700   // of the PrerenderManager.
    701   bool enabled_;
    702 
    703   // The profile that owns this PrerenderManager.
    704   Profile* profile_;
    705 
    706   PrerenderTracker* prerender_tracker_;
    707 
    708   // All running prerenders. Sorted by expiry time, in ascending order.
    709   ScopedVector<PrerenderData> active_prerenders_;
    710 
    711   // Prerenders awaiting deletion.
    712   ScopedVector<PrerenderData> to_delete_prerenders_;
    713 
    714   // List of recent navigations in this profile, sorted by ascending
    715   // navigate_time_.
    716   std::list<NavigationRecord> navigations_;
    717 
    718   // This map is from all WebContents which are currently displaying a
    719   // prerendered page which has already been swapped in to a
    720   // PrerenderedWebContentsData for tracking full lifetime information
    721   // on prerenders.
    722   base::hash_map<content::WebContents*, PrerenderedWebContentsData>
    723       prerendered_web_contents_data_;
    724 
    725   // WebContents that would have been swapped out for a prerendered WebContents
    726   // if the user was not part of the control group for measurement. When the
    727   // WebContents gets a provisional load, the WebContents is removed from
    728   // the map since the new navigation would not have swapped in a prerender.
    729   // However, one complication exists because the first provisional load after
    730   // the WebContents is marked as "Would Have Been Prerendered" is actually to
    731   // the prerendered location. So, we need to keep a state around that does
    732   // not clear the item from the map on the first provisional load, but does
    733   // for subsequent loads.
    734   base::hash_map<content::WebContents*, WouldBePrerenderedWebContentsData>
    735       would_be_prerendered_map_;
    736 
    737   scoped_ptr<PrerenderContents::Factory> prerender_contents_factory_;
    738 
    739   static PrerenderManagerMode mode_;
    740 
    741   // A count of how many prerenders we do per session. Initialized to 0 then
    742   // incremented and emitted to a histogram on each successful prerender.
    743   static int prerenders_per_session_count_;
    744 
    745   // RepeatingTimer to perform periodic cleanups of pending prerendered
    746   // pages.
    747   base::RepeatingTimer<PrerenderManager> repeating_timer_;
    748 
    749   // Track time of last prerender to limit prerender spam.
    750   base::TimeTicks last_prerender_start_time_;
    751 
    752   std::list<content::WebContents*> old_web_contents_list_;
    753 
    754   ScopedVector<OnCloseWebContentsDeleter> on_close_web_contents_deleters_;
    755 
    756   scoped_ptr<PrerenderHistory> prerender_history_;
    757 
    758   std::list<const PrerenderCondition*> prerender_conditions_;
    759 
    760   scoped_ptr<PrerenderHistograms> histograms_;
    761 
    762   scoped_ptr<PrerenderLocalPredictor> local_predictor_;
    763 
    764   scoped_refptr<predictors::LoggedInPredictorTable> logged_in_predictor_table_;
    765 
    766   // Here, we keep the logged in predictor state, but potentially a superset
    767   // of its actual (database-backed) state, since we do not incorporate
    768   // browser data deletion. We do not use this for actual lookups, but only
    769   // to query cookie data for domains we know there was a login before.
    770   // This is required to avoid a large number of cookie lookups on bulk
    771   // deletion of cookies.
    772   scoped_ptr<LoggedInStateMap> logged_in_state_;
    773 
    774   content::NotificationRegistrar notification_registrar_;
    775 
    776   CancelableRequestConsumer query_url_consumer_;
    777 
    778   DISALLOW_COPY_AND_ASSIGN(PrerenderManager);
    779 };
    780 
    781 PrerenderManager* FindPrerenderManagerUsingRenderProcessId(
    782     int render_process_id);
    783 
    784 }  // namespace prerender
    785 
    786 #endif  // CHROME_BROWSER_PRERENDER_PRERENDER_MANAGER_H_
    787