// 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_MANAGER_H_
#define CHROME_BROWSER_PRERENDER_PRERENDER_MANAGER_H_

#include <list>
#include <map>
#include <string>
#include <utility>
#include <vector>

#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/weak_ptr.h"
#include "base/task/cancelable_task_tracker.h"
#include "base/threading/non_thread_safe.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chrome/browser/history/history_service.h"
#include "chrome/browser/media/media_capture_devices_dispatcher.h"
#include "chrome/browser/predictors/logged_in_predictor_table.h"
#include "chrome/browser/prerender/prerender_config.h"
#include "chrome/browser/prerender/prerender_contents.h"
#include "chrome/browser/prerender/prerender_events.h"
#include "chrome/browser/prerender/prerender_final_status.h"
#include "chrome/browser/prerender/prerender_histograms.h"
#include "chrome/browser/prerender/prerender_origin.h"
#include "chrome/browser/prerender/prerender_tracker.h"
#include "components/keyed_service/core/keyed_service.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/render_process_host_observer.h"
#include "content/public/browser/session_storage_namespace.h"
#include "content/public/browser/web_contents_observer.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_monster.h"
#include "url/gurl.h"

class Profile;
class InstantSearchPrerendererTest;
struct ChromeCookieDetails;

namespace base {
class DictionaryValue;
}

namespace chrome {
struct NavigateParams;
}

namespace content {
class WebContents;
}

namespace gfx {
class Size;
}

namespace net {
class URLRequestContextGetter;
}

namespace prerender {

class PrerenderCondition;
class PrerenderHandle;
class PrerenderHistory;
class PrerenderLocalPredictor;

// PrerenderManager is responsible for initiating and keeping prerendered
// views of web pages. All methods must be called on the UI thread unless
// indicated otherwise.
class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>,
                         public base::NonThreadSafe,
                         public content::NotificationObserver,
                         public content::RenderProcessHostObserver,
                         public KeyedService,
                         public MediaCaptureDevicesDispatcher::Observer {
 public:
  // NOTE: New values need to be appended, since they are used in histograms.
  enum PrerenderManagerMode {
    PRERENDER_MODE_DISABLED = 0,
    PRERENDER_MODE_ENABLED = 1,
    PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP = 2,
    PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP = 3,
    // Obsolete: PRERENDER_MODE_EXPERIMENT_5MIN_TTL_GROUP = 4,
    PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP = 5,
    PRERENDER_MODE_EXPERIMENT_MULTI_PRERENDER_GROUP = 6,
    PRERENDER_MODE_EXPERIMENT_15MIN_TTL_GROUP = 7,
    PRERENDER_MODE_MAX
  };

  // One or more of these flags must be passed to ClearData() to specify just
  // what data to clear.  See function declaration for more information.
  enum ClearFlags {
    CLEAR_PRERENDER_CONTENTS = 0x1 << 0,
    CLEAR_PRERENDER_HISTORY = 0x1 << 1,
    CLEAR_MAX = 0x1 << 2
  };

  typedef predictors::LoggedInPredictorTable::LoggedInStateMap LoggedInStateMap;

  // ID indicating that no experiment is active.
  static const uint8 kNoExperiment = 0;

  // Owned by a Profile object for the lifetime of the profile.
  PrerenderManager(Profile* profile, PrerenderTracker* prerender_tracker);

  virtual ~PrerenderManager();

  // From KeyedService:
  virtual void Shutdown() OVERRIDE;

  // Entry points for adding prerenders.

  // Adds a prerender for |url| if valid. |process_id| and |route_id| identify
  // the RenderView that the prerender request came from. If |size| is empty, a
  // default from the PrerenderConfig is used. Returns a caller-owned
  // PrerenderHandle* if the URL was added, NULL if it was not. If the launching
  // RenderView is itself prerendering, the prerender is added as a pending
  // prerender.
  PrerenderHandle* AddPrerenderFromLinkRelPrerender(
      int process_id,
      int route_id,
      const GURL& url,
      uint32 rel_types,
      const content::Referrer& referrer,
      const gfx::Size& size);

  // Adds a prerender for |url| if valid. As the prerender request is coming
  // from a source without a RenderViewHost (i.e., the omnibox) we don't have a
  // child or route id, or a referrer. This method uses sensible values for
  // those. The |session_storage_namespace| matches the namespace of the active
  // tab at the time the prerender is generated from the omnibox. Returns a
  // caller-owned PrerenderHandle*, or NULL.
  PrerenderHandle* AddPrerenderFromOmnibox(
      const GURL& url,
      content::SessionStorageNamespace* session_storage_namespace,
      const gfx::Size& size);

  PrerenderHandle* AddPrerenderFromLocalPredictor(
      const GURL& url,
      content::SessionStorageNamespace* session_storage_namespace,
      const gfx::Size& size);

  PrerenderHandle* AddPrerenderFromExternalRequest(
      const GURL& url,
      const content::Referrer& referrer,
      content::SessionStorageNamespace* session_storage_namespace,
      const gfx::Size& size);

  // Adds a prerender for Instant Search |url| if valid. The
  // |session_storage_namespace| matches the namespace of the active tab at the
  // time the prerender is generated. Returns a caller-owned PrerenderHandle* or
  // NULL.
  PrerenderHandle* AddPrerenderForInstant(
      const GURL& url,
      content::SessionStorageNamespace* session_storage_namespace,
      const gfx::Size& size);

  // Cancels all active prerenders.
  void CancelAllPrerenders();

  // If |url| matches a valid prerendered page and |params| are compatible, try
  // to swap it and merge browsing histories. Returns |true| and updates
  // |params->target_contents| if a prerendered page is swapped in, |false|
  // otherwise.
  bool MaybeUsePrerenderedPage(const GURL& url,
                               chrome::NavigateParams* params);

  // Moves a PrerenderContents to the pending delete list from the list of
  // active prerenders when prerendering should be cancelled.
  virtual void MoveEntryToPendingDelete(PrerenderContents* entry,
                                        FinalStatus final_status);

  // Records the page load time for a prerender that wasn't swapped in.
  void RecordPageLoadTimeNotSwappedIn(Origin origin,
                                      base::TimeDelta page_load_time,
                                      const GURL& url);

  // Records the perceived page load time for a page - effectively the time from
  // when the user navigates to a page to when it finishes loading. The actual
  // load may have started prior to navigation due to prerender hints.
  // This must be called on the UI thread.
  // |fraction_plt_elapsed_at_swap_in| must either be in [0.0, 1.0], or a value
  // outside that range indicating that it doesn't apply.
  void RecordPerceivedPageLoadTime(
      Origin origin,
      NavigationType navigation_type,
      base::TimeDelta perceived_page_load_time,
      double fraction_plt_elapsed_at_swap_in,
      const GURL& url);

  // Set whether prerendering is currently enabled for this manager.
  // Must be called on the UI thread.
  // If |enabled| is false, existing prerendered pages will still persist until
  // they time out, but new ones will not be generated.
  void set_enabled(bool enabled);

  static PrerenderManagerMode GetMode();
  static void SetMode(PrerenderManagerMode mode);
  static const char* GetModeString();
  static bool IsPrerenderingPossible();
  static bool ActuallyPrerendering();
  static bool IsControlGroup(uint8 experiment_id);
  static bool IsNoUseGroup();

  // Query the list of current prerender pages to see if the given web contents
  // is prerendering a page. The optional parameter |origin| is an output
  // parameter which, if a prerender is found, is set to the Origin of the
  // prerender |web_contents|.
  bool IsWebContentsPrerendering(const content::WebContents* web_contents,
                                 Origin* origin) const;

  // Whether the PrerenderManager has an active prerender with the given url and
  // SessionStorageNamespace associated with the given WebContens.
  bool HasPrerenderedUrl(GURL url, content::WebContents* web_contents) const;

  // Returns the PrerenderContents object for the given web_contents, otherwise
  // returns NULL. Note that the PrerenderContents may have been Destroy()ed,
  // but not yet deleted.
  PrerenderContents* GetPrerenderContents(
      const content::WebContents* web_contents) const;

  // Returns the PrerenderContents object for a given child_id, route_id pair,
  // otherwise returns NULL. Note that the PrerenderContents may have been
  // Destroy()ed, but not yet deleted.
  virtual PrerenderContents* GetPrerenderContentsForRoute(
      int child_id, int route_id) const;

  // Returns a list of all WebContents being prerendered.
  const std::vector<content::WebContents*> GetAllPrerenderingContents() const;

  // Checks whether |url| has been recently navigated to.
  bool HasRecentlyBeenNavigatedTo(Origin origin, const GURL& url);

  // Returns true iff the method given is valid for prerendering.
  static bool IsValidHttpMethod(const std::string& method);

  // Returns true iff the scheme of the URL given is valid for prerendering.
  static bool DoesURLHaveValidScheme(const GURL& url);

  // Returns true iff the scheme of the subresource URL given is valid for
  // prerendering.
  static bool DoesSubresourceURLHaveValidScheme(const GURL& url);

  // Returns a Value object containing the active pages being prerendered, and
  // a history of pages which were prerendered. The caller is responsible for
  // deleting the return value.
  base::DictionaryValue* GetAsValue() const;

  // Clears the data indicated by which bits of clear_flags are set.
  //
  // If the CLEAR_PRERENDER_CONTENTS bit is set, all active prerenders are
  // cancelled and then deleted, and any WebContents queued for destruction are
  // destroyed as well.
  //
  // If the CLEAR_PRERENDER_HISTORY bit is set, the prerender history is
  // cleared, including any entries newly created by destroying them in
  // response to the CLEAR_PRERENDER_CONTENTS flag.
  //
  // Intended to be used when clearing the cache or history.
  void ClearData(int clear_flags);

  // Record a final status of a prerendered page in a histogram.
  // This variation allows specifying whether prerendering had been started
  // (necessary to flag MatchComplete dummies).
  void RecordFinalStatusWithMatchCompleteStatus(
      Origin origin,
      uint8 experiment_id,
      PrerenderContents::MatchCompleteStatus mc_status,
      FinalStatus final_status) const;

  // Record a cookie status histogram (see prerender_histograms.h).
  void RecordCookieStatus(Origin origin,
                          uint8 experiment_id,
                          int cookie_status) const;

  // Record a cookie send type histogram (see prerender_histograms.h).
  void RecordCookieSendType(Origin origin,
                            uint8 experiment_id,
                            int cookie_send_type) const;

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

  // MediaCaptureDevicesDispatcher::Observer
  virtual void OnCreatingAudioStream(int render_process_id,
                                     int render_frame_id) OVERRIDE;

  const Config& config() const { return config_; }
  Config& mutable_config() { return config_; }

  PrerenderTracker* prerender_tracker() { return prerender_tracker_; }

  bool cookie_store_loaded() { return cookie_store_loaded_; }

  // Adds a condition. This is owned by the PrerenderManager.
  void AddCondition(const PrerenderCondition* condition);

  // Records that some visible tab navigated (or was redirected) to the
  // provided URL.
  void RecordNavigation(const GURL& url);

  // Updates the LoggedInPredictor state to reflect that a login has likely
  // on the URL provided.
  void RecordLikelyLoginOnURL(const GURL& url);

  // Checks if the LoggedInPredictor shows that the user is likely logged on
  // to the site for the URL provided.
  void CheckIfLikelyLoggedInOnURL(const GURL& url,
                                  bool* lookup_result,
                                  bool* database_was_present,
                                  const base::Closure& result_cb);

  void OnHistoryServiceDidQueryURL(Origin origin,
                                   uint8 experiment_id,
                                   bool success,
                                   const history::URLRow& url_row,
                                   const history::VisitVector& visits);

  Profile* profile() const { return profile_; }

  // Classes which will be tested in prerender unit browser tests should use
  // these methods to get times for comparison, so that the test framework can
  // mock advancing/retarding time.
  virtual base::Time GetCurrentTime() const;
  virtual base::TimeTicks GetCurrentTimeTicks() const;

  scoped_refptr<predictors::LoggedInPredictorTable>
  logged_in_predictor_table() {
    return logged_in_predictor_table_;
  }

  PrerenderLocalPredictor* local_predictor() {
    return local_predictor_.get();
  }

  // Notification that a cookie event happened on a render frame. Will record a
  // cookie event for a given render frame, if it is being prerendered.
  // If cookies were sent, all cookies must be supplied in |cookie_list|.
  static void RecordCookieEvent(int process_id,
                                int frame_id,
                                const GURL& url,
                                const GURL& frame_url,
                                bool is_for_blocking_resource,
                                PrerenderContents::CookieEvent event,
                                const net::CookieList* cookie_list);

  // Arranges for all session storage merges to hang indefinitely. This is used
  // to reliably test various swap abort cases.
  static void HangSessionStorageMergesForTesting();

  // Notification that a prerender has completed and its bytes should be
  // recorded.
  void RecordNetworkBytes(Origin origin, bool used, int64 prerender_bytes);

  // Returns whether prerendering is currently enabled for this manager.
  bool IsEnabled() const;

  // Add to the running tally of bytes transferred over the network for this
  // profile if prerendering is currently enabled.
  void AddProfileNetworkBytesIfEnabled(int64 bytes);

  // Registers a new ProcessHost performing a prerender. Called by
  // PrerenderContents.
  void AddPrerenderProcessHost(content::RenderProcessHost* process_host);

  // Returns whether or not |process_host| may be reused for new navigations
  // from a prerendering perspective. Currently, if Prerender Cookie Stores are
  // enabled, prerenders must be in their own processes that may not be shared.
  bool MayReuseProcessHost(content::RenderProcessHost* process_host);

  // content::RenderProcessHostObserver implementation.
  virtual void RenderProcessHostDestroyed(
      content::RenderProcessHost* host) OVERRIDE;

  // To be called once the cookie store for this profile has been loaded.
  void OnCookieStoreLoaded();

  // For testing purposes. Issues a callback once the cookie store has been
  // loaded.
  void set_on_cookie_store_loaded_cb_for_testing(base::Closure cb) {
    on_cookie_store_loaded_cb_for_testing_ = cb;
  }

 protected:
  class PendingSwap;
  class PrerenderData : public base::SupportsWeakPtr<PrerenderData> {
   public:
    struct OrderByExpiryTime;

    PrerenderData(PrerenderManager* manager,
                  PrerenderContents* contents,
                  base::TimeTicks expiry_time);

    ~PrerenderData();

    // Turn this PrerenderData into a Match Complete replacement for itself,
    // placing the current prerender contents into |to_delete_prerenders_|.
    void MakeIntoMatchCompleteReplacement();

    // A new PrerenderHandle has been created for this PrerenderData.
    void OnHandleCreated(PrerenderHandle* prerender_handle);

    // The launcher associated with a handle is navigating away from the context
    // that launched this prerender. If the prerender is active, it may stay
    // alive briefly though, in case we we going through a redirect chain that
    // will eventually land at it.
    void OnHandleNavigatedAway(PrerenderHandle* prerender_handle);

    // The launcher associated with a handle has taken explicit action to cancel
    // this prerender. We may well destroy the prerender in this case if no
    // other handles continue to track it.
    void OnHandleCanceled(PrerenderHandle* prerender_handle);

    PrerenderContents* contents() { return contents_.get(); }

    PrerenderContents* ReleaseContents();

    int handle_count() const { return handle_count_; }

    base::TimeTicks abandon_time() const { return abandon_time_; }

    base::TimeTicks expiry_time() const { return expiry_time_; }
    void set_expiry_time(base::TimeTicks expiry_time) {
      expiry_time_ = expiry_time;
    }

    void ClearPendingSwap();

    PendingSwap* pending_swap() { return pending_swap_.get(); }
    void set_pending_swap(PendingSwap* pending_swap) {
      pending_swap_.reset(pending_swap);
    }

   private:
    PrerenderManager* manager_;
    scoped_ptr<PrerenderContents> contents_;

    // The number of distinct PrerenderHandles created for |this|, including
    // ones that have called PrerenderData::OnHandleNavigatedAway(), but not
    // counting the ones that have called PrerenderData::OnHandleCanceled(). For
    // pending prerenders, this will always be 1, since the PrerenderManager
    // only merges handles of running prerenders.
    int handle_count_;

    // The time when OnHandleNavigatedAway was called.
    base::TimeTicks abandon_time_;

    // After this time, this prerender is no longer fresh, and should be
    // removed.
    base::TimeTicks expiry_time_;

    // If a session storage namespace merge is in progress for this object,
    // we need to keep track of various state associated with it.
    scoped_ptr<PendingSwap> pending_swap_;

    DISALLOW_COPY_AND_ASSIGN(PrerenderData);
  };

  // When a swap can't happen immediately, due to a sesison storage namespace
  // merge, there will be a pending swap object while the merge is in
  // progress. It retains all the data needed to do the merge, maintains
  // throttles for the navigation in the target WebContents that needs to be
  // delayed, and handles all conditions which would cancel a pending swap.
  class PendingSwap : public content::WebContentsObserver {
   public:
    PendingSwap(PrerenderManager* manager,
                content::WebContents* target_contents,
                PrerenderData* prerender_data,
                const GURL& url,
                bool should_replace_current_entry);
    virtual ~PendingSwap();

    content::WebContents* target_contents() const;
    void set_swap_successful(bool swap_successful) {
      swap_successful_ = swap_successful;
    }

    void BeginSwap();

    // content::WebContentsObserver implementation.
    virtual void AboutToNavigateRenderView(
        content::RenderViewHost* render_view_host) OVERRIDE;
    virtual void ProvisionalChangeToMainFrameUrl(
        const GURL& url,
        content::RenderFrameHost* render_frame_host) OVERRIDE;
    virtual void DidCommitProvisionalLoadForFrame(
        int64 frame_id,
        const base::string16& frame_unique_name,
        bool is_main_frame,
        const GURL& validated_url,
        content::PageTransition transition_type,
        content::RenderViewHost* render_view_host) OVERRIDE;
    virtual void DidFailProvisionalLoad(
        int64 frame_id,
        const base::string16& frame_unique_name,
        bool is_main_frame,
        const GURL& validated_url,
        int error_code,
        const base::string16& error_description,
        content::RenderViewHost* render_view_host) OVERRIDE;
    virtual void WebContentsDestroyed() OVERRIDE;

   private:
    void RecordEvent(PrerenderEvent event) const;

    void OnMergeCompleted(content::SessionStorageNamespace::MergeResult result);
    void OnMergeTimeout();

    // Prerender parameters.
    PrerenderManager* manager_;
    PrerenderData* prerender_data_;
    GURL url_;
    bool should_replace_current_entry_;

    base::TimeTicks start_time_;
    PrerenderTracker::ChildRouteIdPair target_route_id_;
    bool seen_target_route_id_;
    base::OneShotTimer<PendingSwap> merge_timeout_;
    bool swap_successful_;

    base::WeakPtrFactory<PendingSwap> weak_factory_;
  };

  void SetPrerenderContentsFactory(
      PrerenderContents::Factory* prerender_contents_factory);

  // Called by a PrerenderData to signal that the launcher has navigated away
  // from the context that launched the prerender. A user may have clicked
  // a link in a page containing a <link rel=prerender> element, or the user
  // might have committed an omnibox navigation. This is used to possibly
  // shorten the TTL of the prerendered page.
  void SourceNavigatedAway(PrerenderData* prerender_data);

  // Gets the request context for the profile.
  // For unit tests, this will be overriden to return NULL, since it is not
  // needed.
  virtual net::URLRequestContextGetter* GetURLRequestContext();

 private:
  friend class ::InstantSearchPrerendererTest;
  friend class PrerenderBrowserTest;
  friend class PrerenderContents;
  friend class PrerenderHandle;
  friend class UnitTestPrerenderManager;

  class OnCloseWebContentsDeleter;
  struct NavigationRecord;

  // Time interval before a new prerender is allowed.
  static const int kMinTimeBetweenPrerendersMs = 500;

  // Time window for which we record old navigations, in milliseconds.
  static const int kNavigationRecordWindowMs = 5000;

  void OnCancelPrerenderHandle(PrerenderData* prerender_data);

  // Adds a prerender for |url| from |referrer| initiated from the process
  // |child_id|. The |origin| specifies how the prerender was added. If |size|
  // is empty, then PrerenderContents::StartPrerendering will instead use a
  // default from PrerenderConfig. Returns a PrerenderHandle*, owned by the
  // caller, or NULL.
  PrerenderHandle* AddPrerender(
      Origin origin,
      int child_id,
      const GURL& url,
      const content::Referrer& referrer,
      const gfx::Size& size,
      content::SessionStorageNamespace* session_storage_namespace);

  void StartSchedulingPeriodicCleanups();
  void StopSchedulingPeriodicCleanups();

  void EvictOldestPrerendersIfNecessary();

  // Deletes stale and cancelled prerendered PrerenderContents, as well as
  // WebContents that have been replaced by prerendered WebContents.
  // Also identifies and kills PrerenderContents that use too much
  // resources.
  void PeriodicCleanup();

  // Posts a task to call PeriodicCleanup.  Results in quicker destruction of
  // objects.  If |this| is deleted before the task is run, the task will
  // automatically be cancelled.
  void PostCleanupTask();

  base::TimeTicks GetExpiryTimeForNewPrerender(Origin origin) const;
  base::TimeTicks GetExpiryTimeForNavigatedAwayPrerender() const;

  void DeleteOldEntries();
  virtual PrerenderContents* CreatePrerenderContents(
      const GURL& url,
      const content::Referrer& referrer,
      Origin origin,
      uint8 experiment_id);

  // Insures the |active_prerenders_| are sorted by increasing expiry time. Call
  // after every mutation of active_prerenders_ that can possibly make it
  // unsorted (e.g. an insert, or changing an expiry time).
  void SortActivePrerenders();

  // Finds the active PrerenderData object for a running prerender matching
  // |url| and |session_storage_namespace|.
  PrerenderData* FindPrerenderData(
      const GURL& url,
      const content::SessionStorageNamespace* session_storage_namespace);

  // Finds the active PrerenderData object currently in a PendingSwap for
  // |target_contents|. Otherwise, returns NULL.
  PrerenderData* FindPrerenderDataForTargetContents(
      content::WebContents* target_contents);

  // Given the |prerender_contents|, find the iterator in active_prerenders_
  // correponding to the given prerender.
  ScopedVector<PrerenderData>::iterator
      FindIteratorForPrerenderContents(PrerenderContents* prerender_contents);

  bool DoesRateLimitAllowPrerender(Origin origin) const;

  // Deletes old WebContents that have been replaced by prerendered ones.  This
  // is needed because they're replaced in a callback from the old WebContents,
  // so cannot immediately be deleted.
  void DeleteOldWebContents();

  // Cleans up old NavigationRecord's.
  void CleanUpOldNavigations();

  // Arrange for the given WebContents to be deleted asap. If deleter is not
  // NULL, deletes that as well.
  void ScheduleDeleteOldWebContents(content::WebContents* tab,
                                    OnCloseWebContentsDeleter* deleter);

  // Adds to the history list.
  void AddToHistory(PrerenderContents* contents);

  // Returns a new Value representing the pages currently being prerendered. The
  // caller is responsible for delete'ing the return value.
  base::Value* GetActivePrerendersAsValue() const;

  // Destroys all pending prerenders using FinalStatus.  Also deletes them as
  // well as any swapped out WebContents queued for destruction.
  // Used both on destruction, and when clearing the browsing history.
  void DestroyAllContents(FinalStatus final_status);

  // Helper function to destroy a PrerenderContents with the specified
  // final_status, while at the same time recording that for the MatchComplete
  // case, that this prerender would have been used.
  void DestroyAndMarkMatchCompleteAsUsed(PrerenderContents* prerender_contents,
                                         FinalStatus final_status);

  // Records the final status a prerender in the case that a PrerenderContents
  // was never created, and also adds a PrerenderHistory entry.
  // This is a helper function which will ultimately call
  // RecordFinalStatusWthMatchCompleteStatus, using MATCH_COMPLETE_DEFAULT.
  void RecordFinalStatusWithoutCreatingPrerenderContents(
      const GURL& url, Origin origin, uint8 experiment_id,
      FinalStatus final_status) const;


  void CookieChanged(ChromeCookieDetails* details);
  void CookieChangedAnyCookiesLeftLookupResult(const std::string& domain_key,
                                               bool cookies_exist);
  void LoggedInPredictorDataReceived(scoped_ptr<LoggedInStateMap> new_map);

  void RecordEvent(PrerenderContents* contents, PrerenderEvent event) const;

  // Swaps a prerender |prerender_data| for |url| into the tab, replacing
  // |web_contents|.  Returns the new WebContents that was swapped in, or NULL
  // if a swap-in was not possible.  If |should_replace_current_entry| is true,
  // the current history entry in |web_contents| is replaced.
  content::WebContents* SwapInternal(const GURL& url,
                                     content::WebContents* web_contents,
                                     PrerenderData* prerender_data,
                                     bool should_replace_current_entry);

  // The configuration.
  Config config_;

  // Specifies whether prerendering is currently enabled for this
  // manager. The value can change dynamically during the lifetime
  // of the PrerenderManager.
  bool enabled_;

  // The profile that owns this PrerenderManager.
  Profile* profile_;

  PrerenderTracker* prerender_tracker_;

  // All running prerenders. Sorted by expiry time, in ascending order.
  ScopedVector<PrerenderData> active_prerenders_;

  // Prerenders awaiting deletion.
  ScopedVector<PrerenderData> to_delete_prerenders_;

  // List of recent navigations in this profile, sorted by ascending
  // navigate_time_.
  std::list<NavigationRecord> navigations_;

  scoped_ptr<PrerenderContents::Factory> prerender_contents_factory_;

  static PrerenderManagerMode mode_;

  // A count of how many prerenders we do per session. Initialized to 0 then
  // incremented and emitted to a histogram on each successful prerender.
  static int prerenders_per_session_count_;

  // RepeatingTimer to perform periodic cleanups of pending prerendered
  // pages.
  base::RepeatingTimer<PrerenderManager> repeating_timer_;

  // Track time of last prerender to limit prerender spam.
  base::TimeTicks last_prerender_start_time_;

  std::list<content::WebContents*> old_web_contents_list_;

  ScopedVector<OnCloseWebContentsDeleter> on_close_web_contents_deleters_;

  scoped_ptr<PrerenderHistory> prerender_history_;

  std::list<const PrerenderCondition*> prerender_conditions_;

  scoped_ptr<PrerenderHistograms> histograms_;

  scoped_ptr<PrerenderLocalPredictor> local_predictor_;

  scoped_refptr<predictors::LoggedInPredictorTable> logged_in_predictor_table_;

  // Here, we keep the logged in predictor state, but potentially a superset
  // of its actual (database-backed) state, since we do not incorporate
  // browser data deletion. We do not use this for actual lookups, but only
  // to query cookie data for domains we know there was a login before.
  // This is required to avoid a large number of cookie lookups on bulk
  // deletion of cookies.
  scoped_ptr<LoggedInStateMap> logged_in_state_;

  content::NotificationRegistrar notification_registrar_;

  base::CancelableTaskTracker query_url_tracker_;

  // The number of bytes transferred over the network for the profile this
  // PrerenderManager is attached to.
  int64 profile_network_bytes_;

  // The value of profile_network_bytes_ that was last recorded.
  int64 last_recorded_profile_network_bytes_;

  // Set of process hosts being prerendered.
  typedef std::set<content::RenderProcessHost*> PrerenderProcessSet;
  PrerenderProcessSet prerender_process_hosts_;

  // Indicates whether the cookie store for this profile has fully loaded yet.
  bool cookie_store_loaded_;

  base::Closure on_cookie_store_loaded_cb_for_testing_;

  DISALLOW_COPY_AND_ASSIGN(PrerenderManager);
};

}  // namespace prerender

#endif  // CHROME_BROWSER_PRERENDER_PRERENDER_MANAGER_H_
